File indexing completed on 2024-12-01 03:41:22
0001 /* 0002 This file is or will be part of KDE desktop environment 0003 SPDX-FileCopyrightText: 1999 Matt Koss <koss@miesto.sk> 0004 0005 SPDX-License-Identifier: LGPL-2.0-only 0006 */ 0007 0008 #include "kioworkertest.h" 0009 0010 #include "../src/utils_p.h" 0011 0012 #include <kio/copyjob.h> 0013 #include <kio/deletejob.h> 0014 #include <kio/listjob.h> 0015 #include <kio/mimetypejob.h> 0016 #include <kio/mkdirjob.h> 0017 #include <kio/simplejob.h> 0018 #include <kio/statjob.h> 0019 #include <kio/transferjob.h> 0020 #include <kprotocolinfo.h> 0021 0022 // QT_STAT_LNK on Windows 0023 #include "kioglobal_p.h" 0024 0025 #include <KJobUiDelegate> 0026 0027 #include <QApplication> 0028 #include <QCommandLineOption> 0029 #include <QCommandLineParser> 0030 #include <QDebug> 0031 #include <QDir> 0032 #include <QGroupBox> 0033 #include <QLayout> 0034 #include <QLocale> 0035 #include <QMessageBox> 0036 #include <QStatusBar> 0037 #include <QThread> 0038 #include <QTimer> 0039 #include <QUrl> 0040 #include <qplatformdefs.h> 0041 0042 using namespace KIO; 0043 0044 KioWorkerTest::KioWorkerTest(QString src, QString dest, uint op, uint pr) 0045 : QMainWindow(nullptr) 0046 { 0047 job = nullptr; 0048 0049 main_widget = new QWidget(this); 0050 QBoxLayout *topLayout = new QVBoxLayout(main_widget); 0051 0052 QGridLayout *grid = new QGridLayout(); 0053 topLayout->addLayout(grid); 0054 0055 grid->setRowStretch(0, 1); 0056 grid->setRowStretch(1, 1); 0057 0058 grid->setColumnStretch(0, 1); 0059 grid->setColumnStretch(1, 100); 0060 0061 lb_from = new QLabel(QStringLiteral("From:"), main_widget); 0062 grid->addWidget(lb_from, 0, 0); 0063 0064 le_source = new QLineEdit(main_widget); 0065 grid->addWidget(le_source, 0, 1); 0066 le_source->setText(src); 0067 0068 lb_to = new QLabel(QStringLiteral("To:"), main_widget); 0069 grid->addWidget(lb_to, 1, 0); 0070 0071 le_dest = new QLineEdit(main_widget); 0072 grid->addWidget(le_dest, 1, 1); 0073 le_dest->setText(dest); 0074 0075 // Operation groupbox & buttons 0076 opButtons = new QButtonGroup(main_widget); 0077 QGroupBox *box = new QGroupBox(QStringLiteral("Operation"), main_widget); 0078 topLayout->addWidget(box, 10); 0079 connect(opButtons, &QButtonGroup::buttonClicked, this, &KioWorkerTest::changeOperation); 0080 0081 QBoxLayout *hbLayout = new QHBoxLayout(box); 0082 0083 rbList = new QRadioButton(QStringLiteral("List"), box); 0084 opButtons->addButton(rbList); 0085 hbLayout->addWidget(rbList, 5); 0086 0087 rbListRecursive = new QRadioButton(QStringLiteral("ListRecursive"), box); 0088 opButtons->addButton(rbListRecursive); 0089 hbLayout->addWidget(rbListRecursive, 5); 0090 0091 rbStat = new QRadioButton(QStringLiteral("Stat"), box); 0092 opButtons->addButton(rbStat); 0093 hbLayout->addWidget(rbStat, 5); 0094 0095 rbGet = new QRadioButton(QStringLiteral("Get"), box); 0096 opButtons->addButton(rbGet); 0097 hbLayout->addWidget(rbGet, 5); 0098 0099 rbPut = new QRadioButton(QStringLiteral("Put"), box); 0100 opButtons->addButton(rbPut); 0101 hbLayout->addWidget(rbPut, 5); 0102 0103 rbCopy = new QRadioButton(QStringLiteral("Copy"), box); 0104 opButtons->addButton(rbCopy); 0105 hbLayout->addWidget(rbCopy, 5); 0106 0107 rbMove = new QRadioButton(QStringLiteral("Move"), box); 0108 opButtons->addButton(rbMove); 0109 hbLayout->addWidget(rbMove, 5); 0110 0111 rbDelete = new QRadioButton(QStringLiteral("Delete"), box); 0112 opButtons->addButton(rbDelete); 0113 hbLayout->addWidget(rbDelete, 5); 0114 0115 rbMkdir = new QRadioButton(QStringLiteral("Mkdir"), box); 0116 opButtons->addButton(rbMkdir); 0117 hbLayout->addWidget(rbMkdir, 5); 0118 0119 rbMimetype = new QRadioButton(QStringLiteral("Mimetype"), box); 0120 opButtons->addButton(rbMimetype); 0121 hbLayout->addWidget(rbMimetype, 5); 0122 0123 QAbstractButton *b = opButtons->buttons()[op]; 0124 b->setChecked(true); 0125 changeOperation(b); 0126 0127 // Progress groupbox & buttons 0128 progressButtons = new QButtonGroup(main_widget); 0129 box = new QGroupBox(QStringLiteral("Progress dialog mode"), main_widget); 0130 topLayout->addWidget(box, 10); 0131 connect(progressButtons, &QButtonGroup::buttonClicked, this, &KioWorkerTest::changeProgressMode); 0132 0133 hbLayout = new QHBoxLayout(box); 0134 0135 rbProgressNone = new QRadioButton(QStringLiteral("None"), box); 0136 progressButtons->addButton(rbProgressNone); 0137 hbLayout->addWidget(rbProgressNone, 5); 0138 0139 rbProgressDefault = new QRadioButton(QStringLiteral("Default"), box); 0140 progressButtons->addButton(rbProgressDefault); 0141 hbLayout->addWidget(rbProgressDefault, 5); 0142 0143 rbProgressStatus = new QRadioButton(QStringLiteral("Status"), box); 0144 progressButtons->addButton(rbProgressStatus); 0145 hbLayout->addWidget(rbProgressStatus, 5); 0146 0147 b = progressButtons->buttons()[pr]; 0148 b->setChecked(true); 0149 changeProgressMode(b); 0150 0151 // statusbar progress widget 0152 statusTracker = new KStatusBarJobTracker(statusBar()); 0153 0154 // run & stop buttons 0155 hbLayout = new QHBoxLayout(); 0156 topLayout->addLayout(hbLayout); 0157 hbLayout->setParent(topLayout); 0158 0159 pbStart = new QPushButton(QStringLiteral("&Start"), main_widget); 0160 pbStart->setFixedSize(pbStart->sizeHint()); 0161 connect(pbStart, &QAbstractButton::clicked, this, &KioWorkerTest::startJob); 0162 hbLayout->addWidget(pbStart, 5); 0163 0164 pbStop = new QPushButton(QStringLiteral("Sto&p"), main_widget); 0165 pbStop->setFixedSize(pbStop->sizeHint()); 0166 pbStop->setEnabled(false); 0167 connect(pbStop, &QAbstractButton::clicked, this, &KioWorkerTest::stopJob); 0168 hbLayout->addWidget(pbStop, 5); 0169 0170 // close button 0171 close = new QPushButton(QStringLiteral("&Close"), main_widget); 0172 close->setFixedSize(close->sizeHint()); 0173 connect(close, &QAbstractButton::clicked, this, &KioWorkerTest::slotQuit); 0174 0175 topLayout->addWidget(close, 5); 0176 0177 main_widget->setMinimumSize(main_widget->sizeHint()); 0178 setCentralWidget(main_widget); 0179 } 0180 0181 void KioWorkerTest::slotQuit() 0182 { 0183 qApp->quit(); 0184 } 0185 0186 void KioWorkerTest::changeOperation(QAbstractButton *b) 0187 { 0188 // only two urls for copy and move 0189 bool enab = rbCopy->isChecked() || rbMove->isChecked(); 0190 0191 le_dest->setEnabled(enab); 0192 0193 selectedOperation = opButtons->buttons().indexOf(b); 0194 } 0195 0196 void KioWorkerTest::changeProgressMode(QAbstractButton *b) 0197 { 0198 progressMode = progressButtons->buttons().indexOf(b); 0199 0200 if (progressMode == ProgressStatus) { 0201 statusBar()->show(); 0202 } else { 0203 statusBar()->hide(); 0204 } 0205 } 0206 0207 void KioWorkerTest::startJob() 0208 { 0209 QUrl sCurrent(QUrl::fromLocalFile(QDir::currentPath())); 0210 QString sSrc(le_source->text()); 0211 QUrl src = QUrl(sCurrent).resolved(QUrl(sSrc)); 0212 0213 if (!src.isValid()) { 0214 QMessageBox::critical(this, QStringLiteral("KioWorker Error Message"), QStringLiteral("Source URL is malformed")); 0215 return; 0216 } 0217 0218 QString sDest(le_dest->text()); 0219 QUrl dest = QUrl(sCurrent).resolved(QUrl(sDest)); 0220 0221 if (!dest.isValid() && (selectedOperation == Copy || selectedOperation == Move)) { 0222 QMessageBox::critical(this, QStringLiteral("KioWorker Error Message"), QStringLiteral("Destination URL is malformed")); 0223 return; 0224 } 0225 0226 pbStart->setEnabled(false); 0227 0228 KIO::JobFlags observe = DefaultFlags; 0229 if (progressMode != ProgressDefault) { 0230 observe = HideProgressInfo; 0231 } 0232 0233 switch (selectedOperation) { 0234 case List: { 0235 KIO::ListJob *listJob = KIO::listDir(src); 0236 job = listJob; 0237 connect(listJob, &KIO::ListJob::entries, this, &KioWorkerTest::slotEntries); 0238 break; 0239 } 0240 0241 case ListRecursive: { 0242 KIO::ListJob *listJob = KIO::listRecursive(src); 0243 job = listJob; 0244 connect(listJob, &KIO::ListJob::entries, this, &KioWorkerTest::slotEntries); 0245 break; 0246 } 0247 0248 case Stat: 0249 job = KIO::stat(src); 0250 break; 0251 0252 case Get: { 0253 KIO::TransferJob *tjob = KIO::get(src, KIO::Reload); 0254 job = tjob; 0255 connect(tjob, &KIO::TransferJob::data, this, &KioWorkerTest::slotData); 0256 break; 0257 } 0258 0259 case Put: { 0260 putBuffer = 0; 0261 KIO::TransferJob *tjob = KIO::put(src, -1, KIO::Overwrite); 0262 tjob->setTotalSize(48 * 1024 * 1024); 0263 job = tjob; 0264 connect(tjob, &TransferJob::dataReq, this, &KioWorkerTest::slotDataReq); 0265 break; 0266 } 0267 0268 case Copy: 0269 job = KIO::copy(src, dest, observe); 0270 break; 0271 0272 case Move: 0273 job = KIO::move(src, dest, observe); 0274 break; 0275 0276 case Delete: 0277 job = KIO::del(src, observe); 0278 break; 0279 0280 case Mkdir: 0281 job = KIO::mkdir(src); 0282 break; 0283 0284 case Mimetype: 0285 job = KIO::mimetype(src); 0286 break; 0287 } 0288 0289 statusBar()->addWidget(statusTracker->widget(job), 0); 0290 0291 connect(job, &KJob::result, this, &KioWorkerTest::slotResult); 0292 0293 if (progressMode == ProgressStatus) { 0294 statusTracker->registerJob(job); 0295 } 0296 0297 pbStop->setEnabled(true); 0298 } 0299 0300 void KioWorkerTest::slotResult(KJob *_job) 0301 { 0302 if (_job->error()) { 0303 _job->uiDelegate()->showErrorMessage(); 0304 } else if (selectedOperation == Stat) { 0305 UDSEntry entry = static_cast<KIO::StatJob *>(_job)->statResult(); 0306 printUDSEntry(entry); 0307 } else if (selectedOperation == Mimetype) { 0308 qDebug() << "MIME type is " << static_cast<KIO::MimetypeJob *>(_job)->mimetype(); 0309 } 0310 0311 if (job == _job) { 0312 job = nullptr; 0313 } 0314 0315 pbStart->setEnabled(true); 0316 pbStop->setEnabled(false); 0317 0318 // statusBar()->removeWidget( statusTracker->widget(job) ); 0319 } 0320 0321 void KioWorkerTest::printUDSEntry(const KIO::UDSEntry &entry) 0322 { 0323 // It's rather rare to iterate that way, usually you'd use numberValue/stringValue directly. 0324 // This is just to print out all that we got 0325 0326 QDateTime timestamp; 0327 0328 const QList<uint> keys = entry.fields(); 0329 for (auto it = keys.cbegin(); it != keys.cend(); ++it) { 0330 switch (*it) { 0331 case KIO::UDSEntry::UDS_FILE_TYPE: { 0332 mode_t mode = (mode_t)entry.numberValue(*it); 0333 qDebug() << "File Type : " << mode; 0334 if (Utils::isDirMask(mode)) { 0335 qDebug() << "is a dir"; 0336 } 0337 if (Utils::isLinkMask(mode)) { 0338 qDebug() << "is a link"; 0339 } 0340 break; 0341 } 0342 case KIO::UDSEntry::UDS_ACCESS: 0343 qDebug() << "Access permissions : " << (mode_t)(entry.numberValue(*it)); 0344 break; 0345 case KIO::UDSEntry::UDS_USER: 0346 qDebug() << "User : " << (entry.stringValue(*it)); 0347 break; 0348 case KIO::UDSEntry::UDS_GROUP: 0349 qDebug() << "Group : " << (entry.stringValue(*it)); 0350 break; 0351 case KIO::UDSEntry::UDS_LOCAL_USER_ID: 0352 qDebug() << "User id : " << (entry.numberValue(*it)); 0353 break; 0354 case KIO::UDSEntry::UDS_LOCAL_GROUP_ID: 0355 qDebug() << "Group id : " << (entry.numberValue(*it)); 0356 break; 0357 case KIO::UDSEntry::UDS_NAME: 0358 qDebug() << "Name : " << (entry.stringValue(*it)); 0359 // m_strText = decodeFileName( it.value().toString() ); 0360 break; 0361 case KIO::UDSEntry::UDS_URL: 0362 qDebug() << "URL : " << (entry.stringValue(*it)); 0363 break; 0364 case KIO::UDSEntry::UDS_MIME_TYPE: 0365 qDebug() << "MimeType : " << (entry.stringValue(*it)); 0366 break; 0367 case KIO::UDSEntry::UDS_LINK_DEST: 0368 qDebug() << "LinkDest : " << (entry.stringValue(*it)); 0369 break; 0370 case KIO::UDSEntry::UDS_SIZE: 0371 qDebug() << "Size: " << KIO::convertSize(entry.numberValue(*it)); 0372 break; 0373 case KIO::UDSEntry::UDS_CREATION_TIME: 0374 timestamp = QDateTime::fromSecsSinceEpoch(entry.numberValue(*it)); 0375 qDebug() << "CreationTime: " << QLocale().toString(timestamp, QLocale::ShortFormat); 0376 break; 0377 case KIO::UDSEntry::UDS_MODIFICATION_TIME: 0378 timestamp = QDateTime::fromSecsSinceEpoch(entry.numberValue(*it)); 0379 qDebug() << "ModificationTime: " << QLocale().toString(timestamp, QLocale::ShortFormat); 0380 break; 0381 case KIO::UDSEntry::UDS_ACCESS_TIME: 0382 timestamp = QDateTime::fromSecsSinceEpoch(entry.numberValue(*it)); 0383 qDebug() << "AccessTime: " << QLocale().toString(timestamp, QLocale::ShortFormat); 0384 break; 0385 } 0386 } 0387 } 0388 0389 void KioWorkerTest::slotEntries(KIO::Job *job, const KIO::UDSEntryList &list) 0390 { 0391 QUrl url = static_cast<KIO::ListJob *>(job)->url(); 0392 KProtocolInfo::ExtraFieldList extraFields = KProtocolInfo::extraFields(url); 0393 UDSEntryList::ConstIterator it = list.begin(); 0394 for (; it != list.end(); ++it) { 0395 // For each file... 0396 QString name = (*it).stringValue(KIO::UDSEntry::UDS_NAME); 0397 qDebug() << name; 0398 0399 KProtocolInfo::ExtraFieldList::Iterator extraFieldsIt = extraFields.begin(); 0400 const QList<uint> fields = it->fields(); 0401 QList<uint>::ConstIterator it2 = fields.begin(); 0402 for (; it2 != fields.end(); it2++) { 0403 if (*it2 >= UDSEntry::UDS_EXTRA && *it2 <= UDSEntry::UDS_EXTRA_END) { 0404 if (extraFieldsIt != extraFields.end()) { 0405 QString column = (*extraFieldsIt).name; 0406 // QString type = (*extraFieldsIt).type; 0407 qDebug() << " Extra data (" << column << ") :" << it->stringValue(*it2); 0408 ++extraFieldsIt; 0409 } else { 0410 qDebug() << " Extra data (UNDEFINED) :" << it->stringValue(*it2); 0411 } 0412 } 0413 } 0414 } 0415 } 0416 0417 void KioWorkerTest::slotData(KIO::Job *, const QByteArray &data) 0418 { 0419 if (data.size() == 0) { 0420 qDebug() << "Data: <End>"; 0421 } else { 0422 qDebug() << "Data: \"" << QString::fromUtf8(data) << "\""; 0423 } 0424 } 0425 0426 void KioWorkerTest::slotDataReq(KIO::Job *, QByteArray &data) 0427 { 0428 /* clang-format off */ 0429 const char *fileDataArray[] = { 0430 "Hello world\n", 0431 "This is a test file\n", 0432 "You can safely delete it.\n", 0433 "BIG\n", 0434 "BIG1\n", 0435 "BIG2\n", 0436 "BIG3\n", 0437 "BIG4\n", 0438 "BIG5\n", 0439 nullptr 0440 }; 0441 /* clang-format on */ 0442 0443 const char *fileData = fileDataArray[putBuffer++]; 0444 0445 if (!fileData) { 0446 qDebug() << "DataReq: <End>"; 0447 return; 0448 } 0449 if (!strncmp(fileData, "BIG", 3)) { 0450 data.fill(0, 8 * 1024 * 1024); 0451 } else { 0452 data = QByteArray(fileData, strlen(fileData)); 0453 } 0454 qDebug() << "DataReq: \"" << fileData << "\""; 0455 QThread::sleep(1); // want to see progress info... 0456 } 0457 0458 void KioWorkerTest::stopJob() 0459 { 0460 qDebug() << "KioWorkerTest::stopJob()"; 0461 job->kill(); 0462 job = nullptr; 0463 0464 pbStop->setEnabled(false); 0465 pbStart->setEnabled(true); 0466 } 0467 0468 int main(int argc, char **argv) 0469 { 0470 const char version[] = "v0.0.0 0000"; // :-) 0471 0472 QApplication app(argc, argv); 0473 app.setApplicationVersion(QString::fromLatin1(version)); 0474 0475 uint op = KioWorkerTest::Copy; 0476 uint pr = 0; 0477 QString src; 0478 QString dest; 0479 QString operation; 0480 { 0481 QCommandLineParser parser; 0482 parser.addVersionOption(); 0483 parser.setApplicationDescription(QStringLiteral("Test for KIO workers")); 0484 parser.addHelpOption(); 0485 parser.addOption( 0486 QCommandLineOption(QStringList() << QStringLiteral("s") << QStringLiteral("src"), QStringLiteral("Source URL"), QStringLiteral("url"))); 0487 parser.addOption( 0488 QCommandLineOption(QStringList() << QStringLiteral("d") << QStringLiteral("dest"), QStringLiteral("Destination URL"), QStringLiteral("url"))); 0489 parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("o") << QStringLiteral("operation"), 0490 QStringLiteral("Operation (list,listrecursive,stat,get,put,copy,move,del,mkdir)"), 0491 QStringLiteral("operation"))); 0492 parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("p") << QStringLiteral("progress"), 0493 QStringLiteral("Progress Type (none,default,status)"), 0494 QStringLiteral("progress"), 0495 QStringLiteral("default"))); 0496 parser.process(app); 0497 0498 src = parser.value(QStringLiteral("src")); 0499 dest = parser.value(QStringLiteral("dest")); 0500 0501 operation = parser.value(QStringLiteral("operation")); 0502 if (operation == QLatin1String("list")) { 0503 op = KioWorkerTest::List; 0504 } else if (operation == QLatin1String("listrecursive")) { 0505 op = KioWorkerTest::ListRecursive; 0506 } else if (operation == QLatin1String("stat")) { 0507 op = KioWorkerTest::Stat; 0508 } else if (operation == QLatin1String("get")) { 0509 op = KioWorkerTest::Get; 0510 } else if (operation == QLatin1String("put")) { 0511 op = KioWorkerTest::Put; 0512 } else if (operation == QLatin1String("copy")) { 0513 op = KioWorkerTest::Copy; 0514 } else if (operation == QLatin1String("move")) { 0515 op = KioWorkerTest::Move; 0516 } else if (operation == QLatin1String("del")) { 0517 op = KioWorkerTest::Delete; 0518 } else if (operation == QLatin1String("mkdir")) { 0519 op = KioWorkerTest::Mkdir; 0520 } else if (!operation.isEmpty()) { 0521 qWarning("Unknown operation, see --help"); 0522 return 1; 0523 } 0524 0525 QString progress = parser.value(QStringLiteral("progress")); 0526 if (progress == QLatin1String("none")) { 0527 pr = KioWorkerTest::ProgressNone; 0528 } else if (progress == QLatin1String("default")) { 0529 pr = KioWorkerTest::ProgressDefault; 0530 } else if (progress == QLatin1String("status")) { 0531 pr = KioWorkerTest::ProgressStatus; 0532 } else { 0533 qWarning("Unknown progress mode, see --help"); 0534 return 1; 0535 } 0536 } 0537 0538 KioWorkerTest *test = new KioWorkerTest(src, dest, op, pr); 0539 if (!operation.isEmpty()) { 0540 QTimer::singleShot(100, test, SLOT(startJob())); 0541 } 0542 test->show(); 0543 test->resize(test->sizeHint()); 0544 0545 return app.exec(); 0546 } 0547 0548 #include "moc_kioworkertest.cpp"