File indexing completed on 2024-09-08 12:19:36
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 : KMainWindow(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, qOverload<QAbstractButton *>(&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, qOverload<QAbstractButton *>(&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::statDetails(src, KIO::StatJob::SourceSide); 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 QVector<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_NAME: 0352 qDebug() << "Name : " << (entry.stringValue(*it)); 0353 // m_strText = decodeFileName( it.value().toString() ); 0354 break; 0355 case KIO::UDSEntry::UDS_URL: 0356 qDebug() << "URL : " << (entry.stringValue(*it)); 0357 break; 0358 case KIO::UDSEntry::UDS_MIME_TYPE: 0359 qDebug() << "MimeType : " << (entry.stringValue(*it)); 0360 break; 0361 case KIO::UDSEntry::UDS_LINK_DEST: 0362 qDebug() << "LinkDest : " << (entry.stringValue(*it)); 0363 break; 0364 case KIO::UDSEntry::UDS_SIZE: 0365 qDebug() << "Size: " << KIO::convertSize(entry.numberValue(*it)); 0366 break; 0367 case KIO::UDSEntry::UDS_CREATION_TIME: 0368 timestamp = QDateTime::fromSecsSinceEpoch(entry.numberValue(*it)); 0369 qDebug() << "CreationTime: " << QLocale().toString(timestamp, QLocale::ShortFormat); 0370 break; 0371 case KIO::UDSEntry::UDS_MODIFICATION_TIME: 0372 timestamp = QDateTime::fromSecsSinceEpoch(entry.numberValue(*it)); 0373 qDebug() << "ModificationTime: " << QLocale().toString(timestamp, QLocale::ShortFormat); 0374 break; 0375 case KIO::UDSEntry::UDS_ACCESS_TIME: 0376 timestamp = QDateTime::fromSecsSinceEpoch(entry.numberValue(*it)); 0377 qDebug() << "AccessTime: " << QLocale().toString(timestamp, QLocale::ShortFormat); 0378 break; 0379 } 0380 } 0381 } 0382 0383 void KioWorkerTest::slotEntries(KIO::Job *job, const KIO::UDSEntryList &list) 0384 { 0385 QUrl url = static_cast<KIO::ListJob *>(job)->url(); 0386 KProtocolInfo::ExtraFieldList extraFields = KProtocolInfo::extraFields(url); 0387 UDSEntryList::ConstIterator it = list.begin(); 0388 for (; it != list.end(); ++it) { 0389 // For each file... 0390 QString name = (*it).stringValue(KIO::UDSEntry::UDS_NAME); 0391 qDebug() << name; 0392 0393 KProtocolInfo::ExtraFieldList::Iterator extraFieldsIt = extraFields.begin(); 0394 const QVector<uint> fields = it->fields(); 0395 QVector<uint>::ConstIterator it2 = fields.begin(); 0396 for (; it2 != fields.end(); it2++) { 0397 if (*it2 >= UDSEntry::UDS_EXTRA && *it2 <= UDSEntry::UDS_EXTRA_END) { 0398 if (extraFieldsIt != extraFields.end()) { 0399 QString column = (*extraFieldsIt).name; 0400 // QString type = (*extraFieldsIt).type; 0401 qDebug() << " Extra data (" << column << ") :" << it->stringValue(*it2); 0402 ++extraFieldsIt; 0403 } else { 0404 qDebug() << " Extra data (UNDEFINED) :" << it->stringValue(*it2); 0405 } 0406 } 0407 } 0408 } 0409 } 0410 0411 void KioWorkerTest::slotData(KIO::Job *, const QByteArray &data) 0412 { 0413 if (data.size() == 0) { 0414 qDebug() << "Data: <End>"; 0415 } else { 0416 qDebug() << "Data: \"" << QString(data) << "\""; 0417 } 0418 } 0419 0420 void KioWorkerTest::slotDataReq(KIO::Job *, QByteArray &data) 0421 { 0422 /* clang-format off */ 0423 const char *fileDataArray[] = { 0424 "Hello world\n", 0425 "This is a test file\n", 0426 "You can safely delete it.\n", 0427 "BIG\n", 0428 "BIG1\n", 0429 "BIG2\n", 0430 "BIG3\n", 0431 "BIG4\n", 0432 "BIG5\n", 0433 nullptr 0434 }; 0435 /* clang-format on */ 0436 0437 const char *fileData = fileDataArray[putBuffer++]; 0438 0439 if (!fileData) { 0440 qDebug() << "DataReq: <End>"; 0441 return; 0442 } 0443 if (!strncmp(fileData, "BIG", 3)) { 0444 data.fill(0, 8 * 1024 * 1024); 0445 } else { 0446 data = QByteArray(fileData, strlen(fileData)); 0447 } 0448 qDebug() << "DataReq: \"" << fileData << "\""; 0449 QThread::sleep(1); // want to see progress info... 0450 } 0451 0452 void KioWorkerTest::stopJob() 0453 { 0454 qDebug() << "KioWorkerTest::stopJob()"; 0455 job->kill(); 0456 job = nullptr; 0457 0458 pbStop->setEnabled(false); 0459 pbStart->setEnabled(true); 0460 } 0461 0462 int main(int argc, char **argv) 0463 { 0464 const char version[] = "v0.0.0 0000"; // :-) 0465 0466 QApplication app(argc, argv); 0467 app.setApplicationVersion(version); 0468 0469 uint op = KioWorkerTest::Copy; 0470 uint pr = 0; 0471 QString src; 0472 QString dest; 0473 QString operation; 0474 { 0475 QCommandLineParser parser; 0476 parser.addVersionOption(); 0477 parser.setApplicationDescription(QStringLiteral("Test for KIO workers")); 0478 parser.addHelpOption(); 0479 parser.addOption( 0480 QCommandLineOption(QStringList() << QStringLiteral("s") << QStringLiteral("src"), QStringLiteral("Source URL"), QStringLiteral("url"))); 0481 parser.addOption( 0482 QCommandLineOption(QStringList() << QStringLiteral("d") << QStringLiteral("dest"), QStringLiteral("Destination URL"), QStringLiteral("url"))); 0483 parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("o") << QStringLiteral("operation"), 0484 QStringLiteral("Operation (list,listrecursive,stat,get,put,copy,move,del,mkdir)"), 0485 QStringLiteral("operation"))); 0486 parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("p") << QStringLiteral("progress"), 0487 QStringLiteral("Progress Type (none,default,status)"), 0488 QStringLiteral("progress"), 0489 QStringLiteral("default"))); 0490 parser.process(app); 0491 0492 src = parser.value(QStringLiteral("src")); 0493 dest = parser.value(QStringLiteral("dest")); 0494 0495 operation = parser.value(QStringLiteral("operation")); 0496 if (operation == QLatin1String("list")) { 0497 op = KioWorkerTest::List; 0498 } else if (operation == QLatin1String("listrecursive")) { 0499 op = KioWorkerTest::ListRecursive; 0500 } else if (operation == QLatin1String("stat")) { 0501 op = KioWorkerTest::Stat; 0502 } else if (operation == QLatin1String("get")) { 0503 op = KioWorkerTest::Get; 0504 } else if (operation == QLatin1String("put")) { 0505 op = KioWorkerTest::Put; 0506 } else if (operation == QLatin1String("copy")) { 0507 op = KioWorkerTest::Copy; 0508 } else if (operation == QLatin1String("move")) { 0509 op = KioWorkerTest::Move; 0510 } else if (operation == QLatin1String("del")) { 0511 op = KioWorkerTest::Delete; 0512 } else if (operation == QLatin1String("mkdir")) { 0513 op = KioWorkerTest::Mkdir; 0514 } else if (!operation.isEmpty()) { 0515 qWarning("Unknown operation, see --help"); 0516 return 1; 0517 } 0518 0519 QString progress = parser.value(QStringLiteral("progress")); 0520 if (progress == QLatin1String("none")) { 0521 pr = KioWorkerTest::ProgressNone; 0522 } else if (progress == QLatin1String("default")) { 0523 pr = KioWorkerTest::ProgressDefault; 0524 } else if (progress == QLatin1String("status")) { 0525 pr = KioWorkerTest::ProgressStatus; 0526 } else { 0527 qWarning("Unknown progress mode, see --help"); 0528 return 1; 0529 } 0530 } 0531 0532 KioWorkerTest *test = new KioWorkerTest(src, dest, op, pr); 0533 if (!operation.isEmpty()) { 0534 QTimer::singleShot(100, test, SLOT(startJob())); 0535 } 0536 test->show(); 0537 test->resize(test->sizeHint()); 0538 0539 app.exec(); 0540 } 0541 0542 #include "moc_kioworkertest.cpp"