1 | /* |
2 | This file is part of the KDE libraries |
3 | SPDX-FileCopyrightText: 2003 Leo Savernik <l.savernik@aon.at> |
4 | Derived from worker.cpp |
5 | |
6 | SPDX-License-Identifier: LGPL-2.0-only |
7 | */ |
8 | |
9 | #include "commands_p.h" |
10 | #include "dataprotocol_p.h" |
11 | #include "dataworker_p.h" |
12 | #include "workerbase.h" |
13 | |
14 | #include <KLocalizedString> |
15 | |
16 | #include <QDataStream> |
17 | #include <QTimer> |
18 | |
19 | using namespace KIO; |
20 | |
21 | static constexpr int s_kioDataPollInterval = 0; |
22 | |
23 | // don't forget to sync DISPATCH_DECL in dataworker_p.h |
24 | /* clang-format off */ |
25 | #define DISPATCH_IMPL(type) \ |
26 | void DataWorker::dispatch_##type() \ |
27 | { \ |
28 | if (_suspended) { \ |
29 | QueueStruct q(Queue_##type); \ |
30 | q.size = -1; \ |
31 | dispatchQueue.push_back(q); \ |
32 | if (!timer->isActive()) { \ |
33 | timer->start(s_kioDataPollInterval); \ |
34 | } \ |
35 | } else \ |
36 | Q_EMIT type(); \ |
37 | } |
38 | |
39 | // don't forget to sync DISPATCH_DECL1 in dataworker_p.h |
40 | #define DISPATCH_IMPL1(type, paramtype, paramname) \ |
41 | void DataWorker::dispatch_##type(paramtype paramname) \ |
42 | { \ |
43 | if (_suspended) { \ |
44 | QueueStruct q(Queue_##type); \ |
45 | q.paramname = paramname; \ |
46 | dispatchQueue.push_back(q); \ |
47 | if (!timer->isActive()) { \ |
48 | timer->start(s_kioDataPollInterval); \ |
49 | } \ |
50 | } else \ |
51 | Q_EMIT type(paramname); \ |
52 | } |
53 | |
54 | DataWorker::DataWorker() |
55 | : Worker(QStringLiteral("data" )) |
56 | { |
57 | // qDebug() << this; |
58 | _suspended = false; |
59 | timer = new QTimer(this); |
60 | connect(sender: timer, signal: &QTimer::timeout, context: this, slot: &DataWorker::dispatchNext); |
61 | } |
62 | |
63 | DataWorker::~DataWorker() |
64 | { |
65 | // qDebug() << this; |
66 | } |
67 | |
68 | void DataWorker::suspend() |
69 | { |
70 | _suspended = true; |
71 | // qDebug() << this; |
72 | timer->stop(); |
73 | } |
74 | |
75 | void DataWorker::resume() |
76 | { |
77 | _suspended = false; |
78 | // qDebug() << this; |
79 | // aarrrgh! This makes the once hyper fast and efficient data protocol |
80 | // implementation slow as molasses. But it wouldn't work otherwise, |
81 | // and I don't want to start messing around with threads |
82 | timer->start(msec: s_kioDataPollInterval); |
83 | } |
84 | |
85 | // finished is a special case. If we emit it right away, then |
86 | // TransferJob::start can delete the job even before the end of the method |
87 | void DataWorker::dispatch_finished() |
88 | { |
89 | QueueStruct q(Queue_finished); |
90 | q.size = -1; |
91 | dispatchQueue.push_back(t: q); |
92 | if (!timer->isActive()) { |
93 | timer->start(msec: s_kioDataPollInterval); |
94 | } |
95 | } |
96 | |
97 | void DataWorker::dispatchNext() |
98 | { |
99 | if (dispatchQueue.empty()) { |
100 | timer->stop(); |
101 | return; |
102 | } |
103 | |
104 | const QueueStruct &q = dispatchQueue.front(); |
105 | // qDebug() << this << "dispatching" << q.type << dispatchQueue.size() << "left"; |
106 | switch (q.type) { |
107 | case Queue_mimeType: |
108 | Q_EMIT mimeType(q.s); |
109 | break; |
110 | case Queue_totalSize: |
111 | Q_EMIT totalSize(q.size); |
112 | break; |
113 | case Queue_sendMetaData: |
114 | sendMetaData(); |
115 | break; |
116 | case Queue_data: |
117 | Q_EMIT data(q.ba); |
118 | break; |
119 | case Queue_finished: |
120 | Q_EMIT finished(); |
121 | break; |
122 | } /*end switch*/ |
123 | |
124 | dispatchQueue.pop_front(); |
125 | } |
126 | |
127 | void DataWorker::send(int cmd, const QByteArray &arr) |
128 | { |
129 | QDataStream stream(arr); |
130 | |
131 | QUrl url; |
132 | |
133 | switch (cmd) { |
134 | case CMD_GET: { |
135 | stream >> url; |
136 | get(url); |
137 | break; |
138 | } |
139 | case CMD_MIMETYPE: { |
140 | stream >> url; |
141 | mimetype(url); |
142 | break; |
143 | } |
144 | // ignore these (must not emit error, otherwise SIGSEGV occurs) |
145 | case CMD_REPARSECONFIGURATION: |
146 | case CMD_META_DATA: |
147 | break; |
148 | default: |
149 | Q_EMIT error(ERR_UNSUPPORTED_ACTION, unsupportedActionErrorString(QStringLiteral("data" ), cmd)); |
150 | } /*end switch*/ |
151 | } |
152 | |
153 | bool DataWorker::suspended() |
154 | { |
155 | return _suspended; |
156 | } |
157 | |
158 | void DataWorker::setHost(const QString & /*host*/, quint16 /*port*/, const QString & /*user*/, const QString & /*passwd*/) |
159 | { |
160 | // irrelevant -> will be ignored |
161 | } |
162 | |
163 | void DataWorker::setConfig(const MetaData & /*config*/) |
164 | { |
165 | // FIXME: decide to handle this directly or not at all |
166 | #if 0 |
167 | QByteArray data; |
168 | QDataStream stream(data, QIODevice::WriteOnly); |
169 | stream << config; |
170 | slaveconn.send(CMD_CONFIG, data); |
171 | #endif |
172 | } |
173 | |
174 | void DataWorker::setAllMetaData(const MetaData &md) |
175 | { |
176 | meta_data = md; |
177 | } |
178 | |
179 | void DataWorker::sendMetaData() |
180 | { |
181 | Q_EMIT metaData(meta_data); |
182 | } |
183 | |
184 | DISPATCH_IMPL1(mimeType, const QString &, s) |
185 | DISPATCH_IMPL1(totalSize, KIO::filesize_t, size) |
186 | DISPATCH_IMPL(sendMetaData) |
187 | DISPATCH_IMPL1(data, const QByteArray &, ba) |
188 | |
189 | #undef DISPATCH_IMPL |
190 | #undef DISPATCH_IMPL1 |
191 | |
192 | #include "moc_dataworker_p.cpp" |
193 | |