File indexing completed on 2024-04-21 03:55:00

0001 /*
0002     This file is part of the KDE libraries
0003     SPDX-FileCopyrightText: 2003 Leo Savernik <l.savernik@aon.at>
0004     Derived from worker.cpp
0005 
0006     SPDX-License-Identifier: LGPL-2.0-only
0007 */
0008 
0009 #include "commands_p.h"
0010 #include "dataprotocol_p.h"
0011 #include "dataworker_p.h"
0012 #include "workerbase.h"
0013 
0014 #include <KLocalizedString>
0015 
0016 #include <QDataStream>
0017 #include <QTimer>
0018 
0019 using namespace KIO;
0020 
0021 static constexpr int s_kioDataPollInterval = 0;
0022 
0023 // don't forget to sync DISPATCH_DECL in dataworker_p.h
0024 /* clang-format off */
0025 #define DISPATCH_IMPL(type) \
0026     void DataWorker::dispatch_##type() \
0027     { \
0028         if (_suspended) { \
0029             QueueStruct q(Queue_##type); \
0030             q.size = -1; \
0031             dispatchQueue.push_back(q); \
0032             if (!timer->isActive()) { \
0033                 timer->start(s_kioDataPollInterval); \
0034             } \
0035         } else \
0036             Q_EMIT type(); \
0037     }
0038 
0039 // don't forget to sync DISPATCH_DECL1 in dataworker_p.h
0040 #define DISPATCH_IMPL1(type, paramtype, paramname) \
0041     void DataWorker::dispatch_##type(paramtype paramname) \
0042     { \
0043         if (_suspended) { \
0044             QueueStruct q(Queue_##type); \
0045             q.paramname = paramname; \
0046             dispatchQueue.push_back(q); \
0047             if (!timer->isActive()) { \
0048                 timer->start(s_kioDataPollInterval); \
0049             } \
0050         } else \
0051             Q_EMIT type(paramname); \
0052     }
0053 
0054 DataWorker::DataWorker()
0055     : Worker(QStringLiteral("data"))
0056 {
0057     // qDebug() << this;
0058     _suspended = false;
0059     timer = new QTimer(this);
0060     connect(timer, &QTimer::timeout, this, &DataWorker::dispatchNext);
0061 }
0062 
0063 DataWorker::~DataWorker()
0064 {
0065     // qDebug() << this;
0066 }
0067 
0068 void DataWorker::suspend()
0069 {
0070     _suspended = true;
0071     // qDebug() << this;
0072     timer->stop();
0073 }
0074 
0075 void DataWorker::resume()
0076 {
0077     _suspended = false;
0078     // qDebug() << this;
0079     // aarrrgh! This makes the once hyper fast and efficient data protocol
0080     // implementation slow as molasses. But it wouldn't work otherwise,
0081     // and I don't want to start messing around with threads
0082     timer->start(s_kioDataPollInterval);
0083 }
0084 
0085 // finished is a special case. If we emit it right away, then
0086 // TransferJob::start can delete the job even before the end of the method
0087 void DataWorker::dispatch_finished()
0088 {
0089     QueueStruct q(Queue_finished);
0090     q.size = -1;
0091     dispatchQueue.push_back(q);
0092     if (!timer->isActive()) {
0093         timer->start(s_kioDataPollInterval);
0094     }
0095 }
0096 
0097 void DataWorker::dispatchNext()
0098 {
0099     if (dispatchQueue.empty()) {
0100         timer->stop();
0101         return;
0102     }
0103 
0104     const QueueStruct &q = dispatchQueue.front();
0105     // qDebug() << this << "dispatching" << q.type << dispatchQueue.size() << "left";
0106     switch (q.type) {
0107     case Queue_mimeType:
0108         Q_EMIT mimeType(q.s);
0109         break;
0110     case Queue_totalSize:
0111         Q_EMIT totalSize(q.size);
0112         break;
0113     case Queue_sendMetaData:
0114         sendMetaData();
0115         break;
0116     case Queue_data:
0117         Q_EMIT data(q.ba);
0118         break;
0119     case Queue_finished:
0120         Q_EMIT finished();
0121         break;
0122     } /*end switch*/
0123 
0124     dispatchQueue.pop_front();
0125 }
0126 
0127 void DataWorker::send(int cmd, const QByteArray &arr)
0128 {
0129     QDataStream stream(arr);
0130 
0131     QUrl url;
0132 
0133     switch (cmd) {
0134     case CMD_GET: {
0135         stream >> url;
0136         get(url);
0137         break;
0138     }
0139     case CMD_MIMETYPE: {
0140         stream >> url;
0141         mimetype(url);
0142         break;
0143     }
0144     // ignore these (must not emit error, otherwise SIGSEGV occurs)
0145     case CMD_REPARSECONFIGURATION:
0146     case CMD_META_DATA:
0147         break;
0148     default:
0149         Q_EMIT error(ERR_UNSUPPORTED_ACTION, unsupportedActionErrorString(QStringLiteral("data"), cmd));
0150     } /*end switch*/
0151 }
0152 
0153 bool DataWorker::suspended()
0154 {
0155     return _suspended;
0156 }
0157 
0158 void DataWorker::setHost(const QString & /*host*/, quint16 /*port*/, const QString & /*user*/, const QString & /*passwd*/)
0159 {
0160     // irrelevant -> will be ignored
0161 }
0162 
0163 void DataWorker::setConfig(const MetaData & /*config*/)
0164 {
0165     // FIXME: decide to handle this directly or not at all
0166 #if 0
0167     QByteArray data;
0168     QDataStream stream(data, QIODevice::WriteOnly);
0169     stream << config;
0170     slaveconn.send(CMD_CONFIG, data);
0171 #endif
0172 }
0173 
0174 void DataWorker::setAllMetaData(const MetaData &md)
0175 {
0176     meta_data = md;
0177 }
0178 
0179 void DataWorker::sendMetaData()
0180 {
0181     Q_EMIT metaData(meta_data);
0182 }
0183 
0184 DISPATCH_IMPL1(mimeType, const QString &, s)
0185 DISPATCH_IMPL1(totalSize, KIO::filesize_t, size)
0186 DISPATCH_IMPL(sendMetaData)
0187 DISPATCH_IMPL1(data, const QByteArray &, ba)
0188 
0189 #undef DISPATCH_IMPL
0190 #undef DISPATCH_IMPL1
0191 
0192 #include "moc_dataworker_p.cpp"