2
* Copyright 2007 Aaron Seigo <aseigo@kde.org>
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as
6
* published by the Free Software Foundation; either version 2,
7
* or (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details
14
* You should have received a copy of the GNU Library General Public
15
* License along with this program; if not, write to the
16
* Free Software Foundation, Inc.,
17
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
#include "engineexplorer.h"
22
#include <QApplication>
23
#include <QStandardItemModel>
27
#include <KIconLoader>
30
#include <KStandardAction>
31
#include <KStringHandler>
35
#include <Soprano/Node>
36
Q_DECLARE_METATYPE(Soprano::Node)
37
#endif // FOUND_SOPRANO
38
Q_DECLARE_METATYPE(Plasma::DataEngine::Data)
40
#include <Plasma/DataEngineManager>
42
#include "serviceviewer.h"
43
#include "titlecombobox.h"
45
EngineExplorer::EngineExplorer(QWidget* parent)
49
m_requestingSource(false)
52
(void) qRegisterMetaType<Soprano::Node>();
54
setWindowTitle(i18n("Plasma Engine Explorer"));
55
QWidget* mainWidget = new QWidget(this);
56
setMainWidget(mainWidget);
59
m_engineManager = Plasma::DataEngineManager::self();
60
m_dataModel = new QStandardItemModel(this);
62
int size = IconSize(KIconLoader::Dialog);
63
m_title->setPixmap(pix.pixmap(size, size));
64
connect(m_engines, SIGNAL(activated(QString)), this, SLOT(showEngine(QString)));
65
connect(m_sourceRequesterButton, SIGNAL(clicked(bool)), this, SLOT(requestSource()));
66
m_data->setModel(m_dataModel);
67
m_data->setWordWrap(true);
69
m_searchLine->setTreeView(m_data);
70
m_searchLine->setClickMessage(i18n("Search"));
73
m_engines->setFocus();
75
setButtons(KDialog::Close | KDialog::User1 | KDialog::User2);
76
setButtonText(KDialog::User1, i18n("Collapse All"));
77
setButtonText(KDialog::User2, i18n("Expand All"));
78
connect(this, SIGNAL(user1Clicked()), m_data, SLOT(collapseAll()));
79
connect(this, SIGNAL(user2Clicked()), m_data, SLOT(expandAll()));
80
enableButton(KDialog::User1, false);
81
enableButton(KDialog::User2, false);
83
addAction(KStandardAction::quit(qApp, SLOT(quit()), this));
85
connect(m_data, SIGNAL(customContextMenuRequested(QPoint)),
86
this, SLOT(showDataContextMenu(QPoint)));
87
m_data->setContextMenuPolicy(Qt::CustomContextMenu);
88
connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(cleanUp()));
91
EngineExplorer::~EngineExplorer()
95
void EngineExplorer::cleanUp()
97
if (!m_engineName.isEmpty()) {
98
m_engineManager->unloadEngine(m_engineName);
102
void EngineExplorer::setApp(const QString &app)
106
if (m_engines->count() > 0) {
111
void EngineExplorer::setEngine(const QString &engine)
113
//find the engine in the combo box
114
int index = m_engines->findText(engine);
116
kDebug() << QString("Engine %1 found!").arg(engine);
117
m_engines->setCurrentIndex(index);
122
void EngineExplorer::setInterval(const int interval)
124
m_updateInterval->setValue(interval);
127
void EngineExplorer::dataUpdated(const QString& source, const Plasma::DataEngine::Data& data)
129
QList<QStandardItem*> items = m_dataModel->findItems(source, 0);
131
if (items.isEmpty()) {
135
QStandardItem* parent = items.first();
137
int rows = showData(parent, data);
139
while (parent->rowCount() > rows) {
140
parent->removeRow(rows);
144
void EngineExplorer::listEngines()
147
QStringList engines = m_engineManager->listAllEngines(m_app);
149
m_engines->addItems(engines);
150
m_engines->setCurrentIndex(-1);
153
void EngineExplorer::showEngine(const QString& name)
155
m_sourceRequester->setEnabled(false);
156
m_sourceRequesterButton->setEnabled(false);
157
enableButton(KDialog::User1, false);
158
enableButton(KDialog::User2, false);
159
m_dataModel->clear();
160
m_dataModel->setColumnCount(4);
162
headers << i18n("DataSource") << i18n("Key") << i18n("Value") << i18n("Type");
163
m_dataModel->setHorizontalHeaderLabels(headers);
167
if (!m_engineName.isEmpty()) {
168
m_engineManager->unloadEngine(m_engineName);
172
if (m_engineName.isEmpty()) {
177
m_engine = m_engineManager->loadEngine(m_engineName);
179
m_engineName.clear();
184
//kDebug() << "showing engine " << m_engine->objectName();
185
//kDebug() << "we have " << sources.count() << " data sources";
186
connect(m_engine, SIGNAL(sourceAdded(QString)), this, SLOT(addSource(QString)));
187
connect(m_engine, SIGNAL(sourceRemoved(QString)), this, SLOT(removeSource(QString)));
188
foreach (const QString& source, m_engine->sources()) {
189
//kDebug() << "adding " << source;
193
m_sourceRequesterButton->setEnabled(true);
194
m_updateInterval->setEnabled(true);
195
m_sourceRequester->setEnabled(true);
196
m_sourceRequester->setFocus();
200
void EngineExplorer::addSource(const QString& source)
202
kDebug() << "adding" << source;
203
QList<QStandardItem*> items = m_dataModel->findItems(source, 0);
204
if (!items.isEmpty()) {
205
kDebug() << "er... already there?";
209
QStandardItem* parent = new QStandardItem(source);
210
m_dataModel->appendRow(parent);
212
kDebug() << "getting data for source " << source;
214
if (!m_requestingSource || m_sourceRequester->text() != source) {
215
kDebug() << "connecting up now";
216
m_engine->connectSource(source, this);
222
enableButton(KDialog::User1, true);
223
enableButton(KDialog::User2, true);
226
void EngineExplorer::removeSource(const QString& source)
228
QList<QStandardItem*> items = m_dataModel->findItems(source, 0);
230
if (items.count() < 1) {
234
foreach (QStandardItem* item, items) {
235
m_dataModel->removeRow(item->row());
239
m_engine->disconnectSource(source, this);
243
void EngineExplorer::requestSource()
245
requestSource(m_sourceRequester->text());
248
void EngineExplorer::requestSource(const QString &source)
250
if (!m_engine || source.isEmpty()) {
254
kDebug() << "request source" << source;
255
m_requestingSource = true;
256
m_engine->connectSource(source, this, (uint)m_updateInterval->value());
257
m_requestingSource = false;
260
void EngineExplorer::showDataContextMenu(const QPoint &point)
262
QModelIndex index = m_data->indexAt(point);
263
if (index.isValid()) {
264
if (index.parent().isValid()) {
265
index = index.parent();
268
if (index.column() != 0) {
269
index = m_dataModel->index(index.row(), 0);
272
const QString source = index.data().toString();
274
menu.addTitle(source);
275
QAction *service = menu.addAction(i18n("Get associated service"));
276
QAction *update = menu.addAction(i18n("Update source now"));
277
QAction *remove = menu.addAction(i18n("Remove source"));
279
QAction *activated = menu.exec(m_data->viewport()->mapToGlobal(point));
280
if (activated == service) {
281
ServiceViewer *viewer = new ServiceViewer(m_engine, source);
283
} else if (activated == update) {
284
m_engine->connectSource(source, this);
285
Plasma::DataEngine::Data data = m_engine->query(source);
286
} else if (activated == remove) {
287
removeSource(source);
292
QString EngineExplorer::convertToString(const QVariant &value)
294
switch (value.type())
296
case QVariant::BitArray: {
297
return i18np("<1 bit>", "<%1 bits>", value.toBitArray().size());
299
case QVariant::Bitmap: {
300
QBitmap bitmap = value.value<QBitmap>();
301
return QString("<%1x%2px - %3bpp>").arg(bitmap.width()).arg(bitmap.height()).arg(bitmap.depth());
303
case QVariant::ByteArray: {
304
// Return the array size if it is not displayable
305
if (value.toString().isEmpty()) {
306
return i18np("<1 byte>", "<%1 bytes>", value.toByteArray().size());
309
return value.toString();
312
case QVariant::Image: {
313
QImage image = value.value<QImage>();
314
return QString("<%1x%2px - %3bpp>").arg(image.width()).arg(image.height()).arg(image.depth());
316
case QVariant::Line: {
317
QLine line = value.toLine();
318
return QString("<x1:%1, y1:%2, x2:%3, y2:%4>").arg(line.x1()).arg(line.y1()).arg(line.x2()).arg(line.y2());
320
case QVariant::LineF: {
321
QLineF lineF = value.toLineF();
322
return QString("<x1:%1, y1:%2, x2:%3, y2:%4>").arg(lineF.x1()).arg(lineF.y1()).arg(lineF.x2()).arg(lineF.y2());
324
case QVariant::Locale: {
325
return QString("%1").arg(value.toLocale().name());
327
case QVariant::Map: {
328
QVariantMap map = value.toMap();
329
QString str = i18np("<1 item>", "<%1 items>", map.size());
331
QMapIterator<QString, QVariant> it(map);
332
while (it.hasNext()) {
334
str += "\n" + it.key() + ": " + convertToString(it.value());
339
case QVariant::Pixmap: {
340
QPixmap pixmap = value.value<QPixmap>();
341
return QString("<%1x%2px - %3bpp>").arg(pixmap.width()).arg(pixmap.height()).arg(pixmap.depth());
343
case QVariant::Point: {
344
QPoint point = value.toPoint();
345
return QString("<x:%1, y:%2>").arg(point.x()).arg(point.y());
347
case QVariant::PointF: {
348
QPointF pointF = value.toPointF();
349
return QString("<x:%1, y:%2>").arg(pointF.x()).arg(pointF.y());
351
case QVariant::Rect: {
352
QRect rect = value.toRect();
353
return QString("<x:%1, y:%2, w:%3, h:%4>").arg(rect.x()).arg(rect.y()).arg(rect.width()).arg(rect.height());
355
case QVariant::RectF: {
356
QRectF rectF = value.toRectF();
357
return QString("<x:%1, y:%2, w:%3, h:%4>").arg(rectF.x()).arg(rectF.y()).arg(rectF.width()).arg(rectF.height());
359
case QVariant::RegExp: {
360
return QString("%1").arg(value.toRegExp().pattern());
362
case QVariant::Region: {
363
QRect region = value.value<QRegion>().boundingRect();
364
return QString("<x:%1, y:%2, w:%3, h:%4>").arg(region.x()).arg(region.y()).arg(region.width()).arg(region.height());
366
case QVariant::Size: {
367
QSize size = value.toSize();
368
return QString("<w:%1, h:%2>").arg(size.width()).arg(size.height());
370
case QVariant::SizeF: {
371
QSizeF sizeF = value.toSizeF();
372
return QString("<w:%1, h:%2>").arg(sizeF.width()).arg(sizeF.height());
374
case QVariant::Url: {
375
return QString("%1").arg(value.toUrl().toString());
379
if (QLatin1String(value.typeName()) == "Soprano::Node") {
380
Soprano::Node node = value.value<Soprano::Node>();
381
if (node.isLiteral()) {
382
return convertToString(node.literal().variant());
383
} else if (node.isResource()) {
384
return node.uri().toString();
385
} else if (node.isBlank()) {
386
return QString("_:%1").arg(node.identifier());
390
Plasma::DataEngine::Data data = value.value<Plasma::DataEngine::Data>();
391
if (!data.isEmpty()) {
393
QHashIterator<QString, QVariant> it(data);
395
while (it.hasNext()) {
397
result << (it.key() + ": " + it.value().toString());
400
return result.join("\n");
401
} else if (value.canConvert(QVariant::String)) {
402
if (value.toString().isEmpty()) {
403
return i18nc("The user did a query to a dataengine and it returned empty data", "<empty>");
406
return value.toString();
410
return i18nc("A the dataengine returned something that the humble view on the engineexplorer can't display, like a picture", "<not displayable>");
415
int EngineExplorer::showData(QStandardItem* parent, Plasma::DataEngine::Data data)
418
Plasma::DataEngine::DataIterator it(data);
419
// parent->insertRows(0, data.count());
420
// parent->setColumnCount(3);
421
while (it.hasNext()) {
423
parent->setChild(rowCount, 1, new QStandardItem(it.key()));
424
if (it.value().canConvert(QVariant::List)) {
425
foreach(const QVariant &var, it.value().toList()) {
426
QStandardItem *item = new QStandardItem(convertToString(var));
427
item->setToolTip(item->text());
428
parent->setChild(rowCount, 2, item);
429
parent->setChild(rowCount, 3, new QStandardItem(var.typeName()));
434
if (it.value().canConvert<QIcon>()) {
435
item = new QStandardItem(it.value().value<QIcon>(), "");
437
item = new QStandardItem(convertToString(it.value()));
440
item->setToolTip(item->text());
441
parent->setChild(rowCount, 2, item);
442
parent->setChild(rowCount, 3, new QStandardItem(it.value().typeName()));
450
void EngineExplorer::updateTitle()
453
m_title->setPixmap(KIcon("plasma").pixmap(IconSize(KIconLoader::Dialog)));
454
m_title->setText(i18n("Plasma DataEngine Explorer"));
458
m_title->setText(ki18ncp("The name of the engine followed by the number of data sources",
459
"%1 Engine - 1 data source", "%1 Engine - %2 data sources")
460
.subs(KStringHandler::capwords(m_engine->name()))
461
.subs(m_sourceCount).toString());
463
if (m_engine->icon().isEmpty()) {
464
m_title->setPixmap(KIcon("plasma").pixmap(IconSize(KIconLoader::Dialog)));
466
//m_title->setPixmap(KIcon("alarmclock").pixmap(IconSize(KIconLoader::Dialog)));
467
m_title->setPixmap(KIcon(m_engine->icon()).pixmap(IconSize(KIconLoader::Dialog)));
471
#include "engineexplorer.moc"