1 /*
2 * SPDX-FileCopyrightText: 2008 Aaron Seigo <aseigo@kde.org>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7 #include "serviceviewer.h"
8
9 #include <KLocalizedString>
10 #include <KMessageBox>
11 #include <KStringHandler>
12 #include <QDebug>
13 #include <QDialogButtonBox>
14
15 #include <Plasma/DataEngine>
16 #include <Plasma/Service>
17 #include <Plasma/ServiceJob>
18
19 #include "engineexplorer.h"
20
ServiceViewer(Plasma::DataEngine * engine,const QString & source,QWidget * parent)21 ServiceViewer::ServiceViewer(Plasma::DataEngine *engine, const QString &source, QWidget *parent)
22 : QDialog(parent)
23 , m_engine(engine)
24 , m_service(nullptr)
25 , m_source(source)
26 , m_operationCount(0)
27 , m_operationButton(new QPushButton(i18n("Start Operation"), this))
28 {
29 setAttribute(Qt::WA_DeleteOnClose);
30 QWidget *mainWidget = new QWidget(this);
31 QVBoxLayout *layout = new QVBoxLayout();
32
33 QDialogButtonBox *buttonBox = new QDialogButtonBox(this);
34 buttonBox->addButton(m_operationButton, QDialogButtonBox::ActionRole);
35 buttonBox->addButton(QDialogButtonBox::Close);
36
37 connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
38
39 layout->addWidget(mainWidget);
40 layout->addWidget(buttonBox);
41 setLayout(layout);
42
43 setupUi(mainWidget);
44 m_operationStatus->hide();
45
46 connect(m_operationButton, &QAbstractButton::clicked, this, &ServiceViewer::startOperation);
47 m_operationButton->setEnabled(false);
48
49 connect(m_operations, SIGNAL(currentIndexChanged(QString)), this, SLOT(operationSelected(QString)));
50
51 QString engineName = i18nc("Plasma engine with unknown name", "Unknown");
52 QString serviceName = i18nc("Plasma service with unknown name", "Unknown");
53
54 if (m_engine) {
55 if (m_engine->pluginInfo().isValid()) {
56 engineName = KStringHandler::capwords(m_engine->pluginInfo().name());
57 }
58 qDebug() << "########### CALLING SERVICE FOR SOURCE: " << m_source;
59 m_service = m_engine->serviceForSource(m_source);
60
61 if (m_service != nullptr) {
62 serviceName = m_service->name();
63 updateOperations();
64 connect(m_service, SIGNAL(operationsChanged()), this, SLOT(updateOperations()));
65 connect(m_engine, &QObject::destroyed, this, &ServiceViewer::engineDestroyed);
66 } else {
67 KMessageBox::sorry(this, i18n("No valid service was returned. Verify that a service is available for this source."));
68 close();
69 }
70 }
71
72 setWindowTitle(i18nc("%1 is a Plasma service name", "%1 Service Explorer", serviceName));
73
74 QString title = i18nc("Source: name of the data, Service: writes data instead of fetching",
75 "DataEngine: <b>%1</b>; Source: <b>%2</b>; Service: <b>%3</b>",
76 engineName,
77 m_source,
78 serviceName);
79 m_title->setText(title);
80 m_operations->setFocus();
81 }
82
~ServiceViewer()83 ServiceViewer::~ServiceViewer()
84 {
85 delete m_service;
86 m_engine = nullptr;
87 }
88
updateOperations()89 void ServiceViewer::updateOperations()
90 {
91 if (!m_engine) {
92 return;
93 }
94
95 bool enable = false;
96
97 m_operations->clear();
98 m_operationDescription->clear();
99
100 if (m_service) {
101 const QStringList operations = m_service->operationNames();
102
103 if (!operations.isEmpty()) {
104 enable = true;
105
106 foreach (const QString &operation, operations) {
107 m_operations->addItem(operation);
108 }
109 }
110 }
111
112 m_operations->setEnabled(enable);
113 m_operationsLabel->setEnabled(enable);
114 m_operationDescription->setEnabled(enable);
115 }
116
startOperation()117 void ServiceViewer::startOperation()
118 {
119 if (!m_service) {
120 return;
121 }
122
123 QString operation = m_operations->currentText();
124 QVariantMap desc = m_service->operationDescription(operation);
125 for (int i = 0; i < m_operationDescription->rowCount(); ++i) {
126 QTableWidgetItem *item = m_operationDescription->item(i, 1);
127 QString value = item->text();
128
129 if (value.isEmpty()) {
130 continue;
131 }
132
133 item = m_operationDescription->item(i, 0);
134 QString key = item->text();
135 desc[key] = value;
136 }
137
138 updateJobCount(1);
139 Plasma::ServiceJob *job = m_service->startOperationCall(desc);
140 connect(job, &KJob::finished, this, &ServiceViewer::operationResult);
141 }
142
operationSelected(const QString & operation)143 void ServiceViewer::operationSelected(const QString &operation)
144 {
145 if (!m_service) {
146 return;
147 }
148
149 m_operationButton->setEnabled(true);
150 QStringList headers;
151 headers << i18n("Key") << i18n("Value");
152 m_operationDescription->setHorizontalHeaderLabels(headers);
153
154 QVariantMap desc = m_service->operationDescription(operation);
155 int i = 0;
156 const QStringList keys = desc.keys();
157 m_operationDescription->setRowCount(keys.count());
158 foreach (const QString &key, keys) {
159 QTableWidgetItem *item = new QTableWidgetItem(key);
160 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
161 m_operationDescription->setItem(i, 0, item);
162
163 item = new QTableWidgetItem(desc[key].toString());
164 m_operationDescription->setItem(i, 1, item);
165
166 ++i;
167 }
168 }
169
operationResult(KJob * j)170 void ServiceViewer::operationResult(KJob *j)
171 {
172 if (!m_service) {
173 return;
174 }
175
176 Plasma::ServiceJob *job = qobject_cast<Plasma::ServiceJob *>(j);
177 if (!job) {
178 return;
179 }
180
181 updateJobCount(-1);
182
183 if (job->error()) {
184 KMessageBox::information(this,
185 i18n("<b>'%1'</b> operation with destination <b>'%2'</b> failed. "
186 "<p>The error was: <b>'%3: %4'</b></p>",
187 job->operationName(),
188 job->destination(),
189 job->error(),
190 job->errorString()),
191 i18n("Operation Result"));
192 } else {
193 QString result = EngineExplorer::convertToString(job->result());
194 if (result.isEmpty()) {
195 result = i18n("No response from job.");
196 }
197
198 KMessageBox::information(this,
199 i18n("<b>'%1'</b> operation with destination <b>'%2'</b> returned successfully. "
200 "<p>The result was: <b>'%3'</b></p>",
201 job->operationName(),
202 job->destination(),
203 result),
204 i18n("Operation Result"));
205 }
206
207 qDebug() << "operation results are in!";
208 }
209
engineDestroyed()210 void ServiceViewer::engineDestroyed()
211 {
212 m_service = nullptr;
213 m_engine = nullptr;
214 hide();
215 deleteLater();
216 }
217
updateJobCount(int numberOfJobs)218 void ServiceViewer::updateJobCount(int numberOfJobs)
219 {
220 m_operationCount += numberOfJobs;
221
222 if (m_operationCount < 1) {
223 m_operationCount = 0;
224 m_operationStatus->hide();
225 } else {
226 m_operationStatus->setText(i18np("One active operation…", "%1 operations active…", m_operationCount));
227 m_operationStatus->show();
228 }
229 }
230