cf12defd28
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
549 lines
17 KiB
C++
549 lines
17 KiB
C++
/*
|
|
This file is or will be part of KDE desktop environment
|
|
SPDX-FileCopyrightText: 1999 Matt Koss <koss@miesto.sk>
|
|
|
|
SPDX-License-Identifier: LGPL-2.0-only
|
|
*/
|
|
|
|
#include "kioworkertest.h"
|
|
|
|
#include "../src/utils_p.h"
|
|
|
|
#include <kio/copyjob.h>
|
|
#include <kio/deletejob.h>
|
|
#include <kio/listjob.h>
|
|
#include <kio/mimetypejob.h>
|
|
#include <kio/mkdirjob.h>
|
|
#include <kio/simplejob.h>
|
|
#include <kio/statjob.h>
|
|
#include <kio/transferjob.h>
|
|
#include <kprotocolinfo.h>
|
|
|
|
// QT_STAT_LNK on Windows
|
|
#include "kioglobal_p.h"
|
|
|
|
#include <KJobUiDelegate>
|
|
|
|
#include <QApplication>
|
|
#include <QCommandLineOption>
|
|
#include <QCommandLineParser>
|
|
#include <QDebug>
|
|
#include <QDir>
|
|
#include <QGroupBox>
|
|
#include <QLayout>
|
|
#include <QLocale>
|
|
#include <QMessageBox>
|
|
#include <QStatusBar>
|
|
#include <QThread>
|
|
#include <QTimer>
|
|
#include <QUrl>
|
|
#include <qplatformdefs.h>
|
|
|
|
using namespace KIO;
|
|
|
|
KioWorkerTest::KioWorkerTest(QString src, QString dest, uint op, uint pr)
|
|
: QMainWindow(nullptr)
|
|
{
|
|
job = nullptr;
|
|
|
|
main_widget = new QWidget(this);
|
|
QBoxLayout *topLayout = new QVBoxLayout(main_widget);
|
|
|
|
QGridLayout *grid = new QGridLayout();
|
|
topLayout->addLayout(grid);
|
|
|
|
grid->setRowStretch(0, 1);
|
|
grid->setRowStretch(1, 1);
|
|
|
|
grid->setColumnStretch(0, 1);
|
|
grid->setColumnStretch(1, 100);
|
|
|
|
lb_from = new QLabel(QStringLiteral("From:"), main_widget);
|
|
grid->addWidget(lb_from, 0, 0);
|
|
|
|
le_source = new QLineEdit(main_widget);
|
|
grid->addWidget(le_source, 0, 1);
|
|
le_source->setText(src);
|
|
|
|
lb_to = new QLabel(QStringLiteral("To:"), main_widget);
|
|
grid->addWidget(lb_to, 1, 0);
|
|
|
|
le_dest = new QLineEdit(main_widget);
|
|
grid->addWidget(le_dest, 1, 1);
|
|
le_dest->setText(dest);
|
|
|
|
// Operation groupbox & buttons
|
|
opButtons = new QButtonGroup(main_widget);
|
|
QGroupBox *box = new QGroupBox(QStringLiteral("Operation"), main_widget);
|
|
topLayout->addWidget(box, 10);
|
|
connect(opButtons, &QButtonGroup::buttonClicked, this, &KioWorkerTest::changeOperation);
|
|
|
|
QBoxLayout *hbLayout = new QHBoxLayout(box);
|
|
|
|
rbList = new QRadioButton(QStringLiteral("List"), box);
|
|
opButtons->addButton(rbList);
|
|
hbLayout->addWidget(rbList, 5);
|
|
|
|
rbListRecursive = new QRadioButton(QStringLiteral("ListRecursive"), box);
|
|
opButtons->addButton(rbListRecursive);
|
|
hbLayout->addWidget(rbListRecursive, 5);
|
|
|
|
rbStat = new QRadioButton(QStringLiteral("Stat"), box);
|
|
opButtons->addButton(rbStat);
|
|
hbLayout->addWidget(rbStat, 5);
|
|
|
|
rbGet = new QRadioButton(QStringLiteral("Get"), box);
|
|
opButtons->addButton(rbGet);
|
|
hbLayout->addWidget(rbGet, 5);
|
|
|
|
rbPut = new QRadioButton(QStringLiteral("Put"), box);
|
|
opButtons->addButton(rbPut);
|
|
hbLayout->addWidget(rbPut, 5);
|
|
|
|
rbCopy = new QRadioButton(QStringLiteral("Copy"), box);
|
|
opButtons->addButton(rbCopy);
|
|
hbLayout->addWidget(rbCopy, 5);
|
|
|
|
rbMove = new QRadioButton(QStringLiteral("Move"), box);
|
|
opButtons->addButton(rbMove);
|
|
hbLayout->addWidget(rbMove, 5);
|
|
|
|
rbDelete = new QRadioButton(QStringLiteral("Delete"), box);
|
|
opButtons->addButton(rbDelete);
|
|
hbLayout->addWidget(rbDelete, 5);
|
|
|
|
rbMkdir = new QRadioButton(QStringLiteral("Mkdir"), box);
|
|
opButtons->addButton(rbMkdir);
|
|
hbLayout->addWidget(rbMkdir, 5);
|
|
|
|
rbMimetype = new QRadioButton(QStringLiteral("Mimetype"), box);
|
|
opButtons->addButton(rbMimetype);
|
|
hbLayout->addWidget(rbMimetype, 5);
|
|
|
|
QAbstractButton *b = opButtons->buttons()[op];
|
|
b->setChecked(true);
|
|
changeOperation(b);
|
|
|
|
// Progress groupbox & buttons
|
|
progressButtons = new QButtonGroup(main_widget);
|
|
box = new QGroupBox(QStringLiteral("Progress dialog mode"), main_widget);
|
|
topLayout->addWidget(box, 10);
|
|
connect(progressButtons, &QButtonGroup::buttonClicked, this, &KioWorkerTest::changeProgressMode);
|
|
|
|
hbLayout = new QHBoxLayout(box);
|
|
|
|
rbProgressNone = new QRadioButton(QStringLiteral("None"), box);
|
|
progressButtons->addButton(rbProgressNone);
|
|
hbLayout->addWidget(rbProgressNone, 5);
|
|
|
|
rbProgressDefault = new QRadioButton(QStringLiteral("Default"), box);
|
|
progressButtons->addButton(rbProgressDefault);
|
|
hbLayout->addWidget(rbProgressDefault, 5);
|
|
|
|
rbProgressStatus = new QRadioButton(QStringLiteral("Status"), box);
|
|
progressButtons->addButton(rbProgressStatus);
|
|
hbLayout->addWidget(rbProgressStatus, 5);
|
|
|
|
b = progressButtons->buttons()[pr];
|
|
b->setChecked(true);
|
|
changeProgressMode(b);
|
|
|
|
// statusbar progress widget
|
|
statusTracker = new KStatusBarJobTracker(statusBar());
|
|
|
|
// run & stop buttons
|
|
hbLayout = new QHBoxLayout();
|
|
topLayout->addLayout(hbLayout);
|
|
hbLayout->setParent(topLayout);
|
|
|
|
pbStart = new QPushButton(QStringLiteral("&Start"), main_widget);
|
|
pbStart->setFixedSize(pbStart->sizeHint());
|
|
connect(pbStart, &QAbstractButton::clicked, this, &KioWorkerTest::startJob);
|
|
hbLayout->addWidget(pbStart, 5);
|
|
|
|
pbStop = new QPushButton(QStringLiteral("Sto&p"), main_widget);
|
|
pbStop->setFixedSize(pbStop->sizeHint());
|
|
pbStop->setEnabled(false);
|
|
connect(pbStop, &QAbstractButton::clicked, this, &KioWorkerTest::stopJob);
|
|
hbLayout->addWidget(pbStop, 5);
|
|
|
|
// close button
|
|
close = new QPushButton(QStringLiteral("&Close"), main_widget);
|
|
close->setFixedSize(close->sizeHint());
|
|
connect(close, &QAbstractButton::clicked, this, &KioWorkerTest::slotQuit);
|
|
|
|
topLayout->addWidget(close, 5);
|
|
|
|
main_widget->setMinimumSize(main_widget->sizeHint());
|
|
setCentralWidget(main_widget);
|
|
}
|
|
|
|
void KioWorkerTest::slotQuit()
|
|
{
|
|
qApp->quit();
|
|
}
|
|
|
|
void KioWorkerTest::changeOperation(QAbstractButton *b)
|
|
{
|
|
// only two urls for copy and move
|
|
bool enab = rbCopy->isChecked() || rbMove->isChecked();
|
|
|
|
le_dest->setEnabled(enab);
|
|
|
|
selectedOperation = opButtons->buttons().indexOf(b);
|
|
}
|
|
|
|
void KioWorkerTest::changeProgressMode(QAbstractButton *b)
|
|
{
|
|
progressMode = progressButtons->buttons().indexOf(b);
|
|
|
|
if (progressMode == ProgressStatus) {
|
|
statusBar()->show();
|
|
} else {
|
|
statusBar()->hide();
|
|
}
|
|
}
|
|
|
|
void KioWorkerTest::startJob()
|
|
{
|
|
QUrl sCurrent(QUrl::fromLocalFile(QDir::currentPath()));
|
|
QString sSrc(le_source->text());
|
|
QUrl src = QUrl(sCurrent).resolved(QUrl(sSrc));
|
|
|
|
if (!src.isValid()) {
|
|
QMessageBox::critical(this, QStringLiteral("KioWorker Error Message"), QStringLiteral("Source URL is malformed"));
|
|
return;
|
|
}
|
|
|
|
QString sDest(le_dest->text());
|
|
QUrl dest = QUrl(sCurrent).resolved(QUrl(sDest));
|
|
|
|
if (!dest.isValid() && (selectedOperation == Copy || selectedOperation == Move)) {
|
|
QMessageBox::critical(this, QStringLiteral("KioWorker Error Message"), QStringLiteral("Destination URL is malformed"));
|
|
return;
|
|
}
|
|
|
|
pbStart->setEnabled(false);
|
|
|
|
KIO::JobFlags observe = DefaultFlags;
|
|
if (progressMode != ProgressDefault) {
|
|
observe = HideProgressInfo;
|
|
}
|
|
|
|
switch (selectedOperation) {
|
|
case List: {
|
|
KIO::ListJob *listJob = KIO::listDir(src);
|
|
job = listJob;
|
|
connect(listJob, &KIO::ListJob::entries, this, &KioWorkerTest::slotEntries);
|
|
break;
|
|
}
|
|
|
|
case ListRecursive: {
|
|
KIO::ListJob *listJob = KIO::listRecursive(src);
|
|
job = listJob;
|
|
connect(listJob, &KIO::ListJob::entries, this, &KioWorkerTest::slotEntries);
|
|
break;
|
|
}
|
|
|
|
case Stat:
|
|
job = KIO::stat(src);
|
|
break;
|
|
|
|
case Get: {
|
|
KIO::TransferJob *tjob = KIO::get(src, KIO::Reload);
|
|
job = tjob;
|
|
connect(tjob, &KIO::TransferJob::data, this, &KioWorkerTest::slotData);
|
|
break;
|
|
}
|
|
|
|
case Put: {
|
|
putBuffer = 0;
|
|
KIO::TransferJob *tjob = KIO::put(src, -1, KIO::Overwrite);
|
|
tjob->setTotalSize(48 * 1024 * 1024);
|
|
job = tjob;
|
|
connect(tjob, &TransferJob::dataReq, this, &KioWorkerTest::slotDataReq);
|
|
break;
|
|
}
|
|
|
|
case Copy:
|
|
job = KIO::copy(src, dest, observe);
|
|
break;
|
|
|
|
case Move:
|
|
job = KIO::move(src, dest, observe);
|
|
break;
|
|
|
|
case Delete:
|
|
job = KIO::del(src, observe);
|
|
break;
|
|
|
|
case Mkdir:
|
|
job = KIO::mkdir(src);
|
|
break;
|
|
|
|
case Mimetype:
|
|
job = KIO::mimetype(src);
|
|
break;
|
|
}
|
|
|
|
statusBar()->addWidget(statusTracker->widget(job), 0);
|
|
|
|
connect(job, &KJob::result, this, &KioWorkerTest::slotResult);
|
|
|
|
if (progressMode == ProgressStatus) {
|
|
statusTracker->registerJob(job);
|
|
}
|
|
|
|
pbStop->setEnabled(true);
|
|
}
|
|
|
|
void KioWorkerTest::slotResult(KJob *_job)
|
|
{
|
|
if (_job->error()) {
|
|
_job->uiDelegate()->showErrorMessage();
|
|
} else if (selectedOperation == Stat) {
|
|
UDSEntry entry = static_cast<KIO::StatJob *>(_job)->statResult();
|
|
printUDSEntry(entry);
|
|
} else if (selectedOperation == Mimetype) {
|
|
qDebug() << "MIME type is " << static_cast<KIO::MimetypeJob *>(_job)->mimetype();
|
|
}
|
|
|
|
if (job == _job) {
|
|
job = nullptr;
|
|
}
|
|
|
|
pbStart->setEnabled(true);
|
|
pbStop->setEnabled(false);
|
|
|
|
// statusBar()->removeWidget( statusTracker->widget(job) );
|
|
}
|
|
|
|
void KioWorkerTest::printUDSEntry(const KIO::UDSEntry &entry)
|
|
{
|
|
// It's rather rare to iterate that way, usually you'd use numberValue/stringValue directly.
|
|
// This is just to print out all that we got
|
|
|
|
QDateTime timestamp;
|
|
|
|
const QList<uint> keys = entry.fields();
|
|
for (auto it = keys.cbegin(); it != keys.cend(); ++it) {
|
|
switch (*it) {
|
|
case KIO::UDSEntry::UDS_FILE_TYPE: {
|
|
mode_t mode = (mode_t)entry.numberValue(*it);
|
|
qDebug() << "File Type : " << mode;
|
|
if (Utils::isDirMask(mode)) {
|
|
qDebug() << "is a dir";
|
|
}
|
|
if (Utils::isLinkMask(mode)) {
|
|
qDebug() << "is a link";
|
|
}
|
|
break;
|
|
}
|
|
case KIO::UDSEntry::UDS_ACCESS:
|
|
qDebug() << "Access permissions : " << (mode_t)(entry.numberValue(*it));
|
|
break;
|
|
case KIO::UDSEntry::UDS_USER:
|
|
qDebug() << "User : " << (entry.stringValue(*it));
|
|
break;
|
|
case KIO::UDSEntry::UDS_GROUP:
|
|
qDebug() << "Group : " << (entry.stringValue(*it));
|
|
break;
|
|
case KIO::UDSEntry::UDS_LOCAL_USER_ID:
|
|
qDebug() << "User id : " << (entry.numberValue(*it));
|
|
break;
|
|
case KIO::UDSEntry::UDS_LOCAL_GROUP_ID:
|
|
qDebug() << "Group id : " << (entry.numberValue(*it));
|
|
break;
|
|
case KIO::UDSEntry::UDS_NAME:
|
|
qDebug() << "Name : " << (entry.stringValue(*it));
|
|
// m_strText = decodeFileName( it.value().toString() );
|
|
break;
|
|
case KIO::UDSEntry::UDS_URL:
|
|
qDebug() << "URL : " << (entry.stringValue(*it));
|
|
break;
|
|
case KIO::UDSEntry::UDS_MIME_TYPE:
|
|
qDebug() << "MimeType : " << (entry.stringValue(*it));
|
|
break;
|
|
case KIO::UDSEntry::UDS_LINK_DEST:
|
|
qDebug() << "LinkDest : " << (entry.stringValue(*it));
|
|
break;
|
|
case KIO::UDSEntry::UDS_SIZE:
|
|
qDebug() << "Size: " << KIO::convertSize(entry.numberValue(*it));
|
|
break;
|
|
case KIO::UDSEntry::UDS_CREATION_TIME:
|
|
timestamp = QDateTime::fromSecsSinceEpoch(entry.numberValue(*it));
|
|
qDebug() << "CreationTime: " << QLocale().toString(timestamp, QLocale::ShortFormat);
|
|
break;
|
|
case KIO::UDSEntry::UDS_MODIFICATION_TIME:
|
|
timestamp = QDateTime::fromSecsSinceEpoch(entry.numberValue(*it));
|
|
qDebug() << "ModificationTime: " << QLocale().toString(timestamp, QLocale::ShortFormat);
|
|
break;
|
|
case KIO::UDSEntry::UDS_ACCESS_TIME:
|
|
timestamp = QDateTime::fromSecsSinceEpoch(entry.numberValue(*it));
|
|
qDebug() << "AccessTime: " << QLocale().toString(timestamp, QLocale::ShortFormat);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void KioWorkerTest::slotEntries(KIO::Job *job, const KIO::UDSEntryList &list)
|
|
{
|
|
QUrl url = static_cast<KIO::ListJob *>(job)->url();
|
|
KProtocolInfo::ExtraFieldList extraFields = KProtocolInfo::extraFields(url);
|
|
UDSEntryList::ConstIterator it = list.begin();
|
|
for (; it != list.end(); ++it) {
|
|
// For each file...
|
|
QString name = (*it).stringValue(KIO::UDSEntry::UDS_NAME);
|
|
qDebug() << name;
|
|
|
|
KProtocolInfo::ExtraFieldList::Iterator extraFieldsIt = extraFields.begin();
|
|
const QList<uint> fields = it->fields();
|
|
QList<uint>::ConstIterator it2 = fields.begin();
|
|
for (; it2 != fields.end(); it2++) {
|
|
if (*it2 >= UDSEntry::UDS_EXTRA && *it2 <= UDSEntry::UDS_EXTRA_END) {
|
|
if (extraFieldsIt != extraFields.end()) {
|
|
QString column = (*extraFieldsIt).name;
|
|
// QString type = (*extraFieldsIt).type;
|
|
qDebug() << " Extra data (" << column << ") :" << it->stringValue(*it2);
|
|
++extraFieldsIt;
|
|
} else {
|
|
qDebug() << " Extra data (UNDEFINED) :" << it->stringValue(*it2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void KioWorkerTest::slotData(KIO::Job *, const QByteArray &data)
|
|
{
|
|
if (data.size() == 0) {
|
|
qDebug() << "Data: <End>";
|
|
} else {
|
|
qDebug() << "Data: \"" << QString::fromUtf8(data) << "\"";
|
|
}
|
|
}
|
|
|
|
void KioWorkerTest::slotDataReq(KIO::Job *, QByteArray &data)
|
|
{
|
|
/* clang-format off */
|
|
const char *fileDataArray[] = {
|
|
"Hello world\n",
|
|
"This is a test file\n",
|
|
"You can safely delete it.\n",
|
|
"BIG\n",
|
|
"BIG1\n",
|
|
"BIG2\n",
|
|
"BIG3\n",
|
|
"BIG4\n",
|
|
"BIG5\n",
|
|
nullptr
|
|
};
|
|
/* clang-format on */
|
|
|
|
const char *fileData = fileDataArray[putBuffer++];
|
|
|
|
if (!fileData) {
|
|
qDebug() << "DataReq: <End>";
|
|
return;
|
|
}
|
|
if (!strncmp(fileData, "BIG", 3)) {
|
|
data.fill(0, 8 * 1024 * 1024);
|
|
} else {
|
|
data = QByteArray(fileData, strlen(fileData));
|
|
}
|
|
qDebug() << "DataReq: \"" << fileData << "\"";
|
|
QThread::sleep(1); // want to see progress info...
|
|
}
|
|
|
|
void KioWorkerTest::stopJob()
|
|
{
|
|
qDebug() << "KioWorkerTest::stopJob()";
|
|
job->kill();
|
|
job = nullptr;
|
|
|
|
pbStop->setEnabled(false);
|
|
pbStart->setEnabled(true);
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
const char version[] = "v0.0.0 0000"; // :-)
|
|
|
|
QApplication app(argc, argv);
|
|
app.setApplicationVersion(QString::fromLatin1(version));
|
|
|
|
uint op = KioWorkerTest::Copy;
|
|
uint pr = 0;
|
|
QString src;
|
|
QString dest;
|
|
QString operation;
|
|
{
|
|
QCommandLineParser parser;
|
|
parser.addVersionOption();
|
|
parser.setApplicationDescription(QStringLiteral("Test for KIO workers"));
|
|
parser.addHelpOption();
|
|
parser.addOption(
|
|
QCommandLineOption(QStringList() << QStringLiteral("s") << QStringLiteral("src"), QStringLiteral("Source URL"), QStringLiteral("url")));
|
|
parser.addOption(
|
|
QCommandLineOption(QStringList() << QStringLiteral("d") << QStringLiteral("dest"), QStringLiteral("Destination URL"), QStringLiteral("url")));
|
|
parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("o") << QStringLiteral("operation"),
|
|
QStringLiteral("Operation (list,listrecursive,stat,get,put,copy,move,del,mkdir)"),
|
|
QStringLiteral("operation")));
|
|
parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("p") << QStringLiteral("progress"),
|
|
QStringLiteral("Progress Type (none,default,status)"),
|
|
QStringLiteral("progress"),
|
|
QStringLiteral("default")));
|
|
parser.process(app);
|
|
|
|
src = parser.value(QStringLiteral("src"));
|
|
dest = parser.value(QStringLiteral("dest"));
|
|
|
|
operation = parser.value(QStringLiteral("operation"));
|
|
if (operation == QLatin1String("list")) {
|
|
op = KioWorkerTest::List;
|
|
} else if (operation == QLatin1String("listrecursive")) {
|
|
op = KioWorkerTest::ListRecursive;
|
|
} else if (operation == QLatin1String("stat")) {
|
|
op = KioWorkerTest::Stat;
|
|
} else if (operation == QLatin1String("get")) {
|
|
op = KioWorkerTest::Get;
|
|
} else if (operation == QLatin1String("put")) {
|
|
op = KioWorkerTest::Put;
|
|
} else if (operation == QLatin1String("copy")) {
|
|
op = KioWorkerTest::Copy;
|
|
} else if (operation == QLatin1String("move")) {
|
|
op = KioWorkerTest::Move;
|
|
} else if (operation == QLatin1String("del")) {
|
|
op = KioWorkerTest::Delete;
|
|
} else if (operation == QLatin1String("mkdir")) {
|
|
op = KioWorkerTest::Mkdir;
|
|
} else if (!operation.isEmpty()) {
|
|
qWarning("Unknown operation, see --help");
|
|
return 1;
|
|
}
|
|
|
|
QString progress = parser.value(QStringLiteral("progress"));
|
|
if (progress == QLatin1String("none")) {
|
|
pr = KioWorkerTest::ProgressNone;
|
|
} else if (progress == QLatin1String("default")) {
|
|
pr = KioWorkerTest::ProgressDefault;
|
|
} else if (progress == QLatin1String("status")) {
|
|
pr = KioWorkerTest::ProgressStatus;
|
|
} else {
|
|
qWarning("Unknown progress mode, see --help");
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
KioWorkerTest *test = new KioWorkerTest(src, dest, op, pr);
|
|
if (!operation.isEmpty()) {
|
|
QTimer::singleShot(100, test, SLOT(startJob()));
|
|
}
|
|
test->show();
|
|
test->resize(test->sizeHint());
|
|
|
|
return app.exec();
|
|
}
|
|
|
|
#include "moc_kioworkertest.cpp"
|