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>
24 #include <QVBoxLayout>
25 #include <QHBoxLayout>
31 #include <KIconLoader>
34 #include <KStandardAction>
35 #include <KStringHandler>
38 #include <Soprano/Node>
39 Q_DECLARE_METATYPE(Soprano::Node
)
40 #endif // FOUND_SOPRANO
41 Q_DECLARE_METATYPE(Plasma::DataEngine::Data
)
43 #include <Plasma/DataEngineManager>
45 #include "serviceviewer.h"
46 #include "titlecombobox.h"
48 EngineExplorer::EngineExplorer(QWidget
* parent
)
52 m_requestingSource(false)
55 (void) qRegisterMetaType
<Soprano::Node
>();
57 setWindowTitle(i18n("Plasma Engine Explorer"));
58 QWidget
* mainWidget
= new QWidget(this);
59 setMainWidget(mainWidget
);
62 m_engineManager
= Plasma::DataEngineManager::self();
63 m_dataModel
= new QStandardItemModel(this);
65 int size
= IconSize(KIconLoader::Dialog
);
66 m_title
->setPixmap(pix
.pixmap(size
, size
));
67 connect(m_engines
, SIGNAL(activated(QString
)), this, SLOT(showEngine(QString
)));
68 connect(m_sourceRequesterButton
, SIGNAL(clicked(bool)), this, SLOT(requestSource()));
69 m_data
->setModel(m_dataModel
);
70 m_data
->setWordWrap(true);
72 m_searchLine
->setTreeView(m_data
);
73 m_searchLine
->setClickMessage(i18n("Search"));
76 m_engines
->setFocus();
78 setButtons(KDialog::Close
| KDialog::User1
| KDialog::User2
);
79 setButtonText(KDialog::User1
, i18n("Collapse All"));
80 setButtonText(KDialog::User2
, i18n("Expand All"));
81 connect(this, SIGNAL(user1Clicked()), m_data
, SLOT(collapseAll()));
82 connect(this, SIGNAL(user2Clicked()), m_data
, SLOT(expandAll()));
83 enableButton(KDialog::User1
, false);
84 enableButton(KDialog::User2
, false);
86 addAction(KStandardAction::quit(qApp
, SLOT(quit()), this));
88 connect(m_data
, SIGNAL(customContextMenuRequested(QPoint
)),
89 this, SLOT(showDataContextMenu(QPoint
)));
90 m_data
->setContextMenuPolicy(Qt::CustomContextMenu
);
93 EngineExplorer::~EngineExplorer()
97 void EngineExplorer::setApp(const QString
&app
)
101 if (m_engines
->count() > 0) {
106 void EngineExplorer::setEngine(const QString
&engine
)
108 //find the engine in the combo box
109 int index
= m_engines
->findText(engine
);
111 kDebug() << QString("Engine %1 found!").arg(engine
);
112 m_engines
->setCurrentIndex(index
);
117 void EngineExplorer::setInterval(const int interval
)
119 m_updateInterval
->setValue(interval
);
122 void EngineExplorer::dataUpdated(const QString
& source
, const Plasma::DataEngine::Data
& data
)
124 QList
<QStandardItem
*> items
= m_dataModel
->findItems(source
, 0);
126 if (items
.count() < 1) {
130 QStandardItem
* parent
= items
.first();
132 while (parent
->hasChildren()) {
133 parent
->removeRow(0);
136 showData(parent
, data
);
139 void EngineExplorer::listEngines()
142 QStringList engines
= m_engineManager
->listAllEngines(m_app
);
144 m_engines
->addItems(engines
);
145 m_engines
->setCurrentIndex(-1);
148 void EngineExplorer::showEngine(const QString
& name
)
150 m_sourceRequester
->setEnabled(false);
151 m_sourceRequesterButton
->setEnabled(false);
152 enableButton(KDialog::User1
, false);
153 enableButton(KDialog::User2
, false);
154 m_dataModel
->clear();
155 m_dataModel
->setColumnCount(4);
157 headers
<< i18n("DataSource") << i18n("Key") << i18n("Value") << i18n("Type");
158 m_dataModel
->setHorizontalHeaderLabels(headers
);
162 if (!m_engineName
.isEmpty()) {
163 m_engineManager
->unloadEngine(m_engineName
);
167 if (m_engineName
.isEmpty()) {
172 m_engine
= m_engineManager
->loadEngine(m_engineName
);
174 m_engineName
.clear();
179 QStringList sources
= m_engine
->sources();
181 //kDebug() << "showing engine " << m_engine->objectName();
182 //kDebug() << "we have " << sources.count() << " data sources";
183 foreach (const QString
& source
, sources
) {
184 //kDebug() << "adding " << source;
188 m_sourceRequesterButton
->setEnabled(true);
189 m_updateInterval
->setEnabled(true);
190 m_sourceRequester
->setEnabled(true);
191 m_sourceRequester
->setFocus();
192 connect(m_engine
, SIGNAL(sourceAdded(QString
)), this, SLOT(addSource(QString
)));
193 connect(m_engine
, SIGNAL(sourceRemoved(QString
)), this, SLOT(removeSource(QString
)));
197 void EngineExplorer::addSource(const QString
& source
)
199 QStandardItem
* parent
= new QStandardItem(source
);
200 m_dataModel
->appendRow(parent
);
202 //kDebug() << "getting data for source " << source;
203 Plasma::DataEngine::Data data
= m_engine
->query(source
);
204 showData(parent
, data
);
206 if (!m_requestingSource
|| m_sourceRequester
->text() != source
) {
207 m_engine
->connectSource(source
, this);
213 enableButton(KDialog::User1
, true);
214 enableButton(KDialog::User2
, true);
217 void EngineExplorer::removeSource(const QString
& source
)
219 QList
<QStandardItem
*> items
= m_dataModel
->findItems(source
, 0);
221 if (items
.count() < 1) {
225 foreach (QStandardItem
* item
, items
) {
226 m_dataModel
->removeRow(item
->row());
230 m_engine
->disconnectSource(source
, this);
234 void EngineExplorer::requestSource()
236 requestSource(m_sourceRequester
->text());
239 void EngineExplorer::requestSource(const QString
&source
)
241 if (!m_engine
|| source
.isEmpty()) {
245 kDebug() << "request source" << source
;
246 m_requestingSource
= true;
247 m_engine
->connectSource(source
, this, (uint
)m_updateInterval
->value());
248 m_requestingSource
= false;
251 void EngineExplorer::showDataContextMenu(const QPoint
&point
)
253 QModelIndex index
= m_data
->indexAt(point
);
254 if (index
.isValid()) {
255 if (index
.parent().isValid()) {
256 index
= index
.parent();
259 if (index
.column() != 0) {
260 index
= m_dataModel
->index(index
.row(), 0);
263 QString source
= index
.data().toString();
265 menu
.addTitle(source
);
266 QAction
*service
= menu
.addAction(i18n("Get associated service"));
267 QAction
*update
= menu
.addAction(i18n("Update source now"));
268 QAction
*remove
= menu
.addAction(i18n("Remove source"));
270 QAction
*activated
= menu
.exec(m_data
->viewport()->mapToGlobal(point
));
271 if (activated
== service
) {
272 ServiceViewer
*viewer
= new ServiceViewer(m_engine
, source
);
274 } else if (activated
== update
) {
275 m_engine
->connectSource(source
, this);
276 Plasma::DataEngine::Data data
= m_engine
->query(source
);
277 } else if (activated
== remove
) {
278 removeSource(source
);
283 QString
EngineExplorer::convertToString(const QVariant
&value
) const
285 switch (value
.type())
287 case QVariant::BitArray
: {
288 return i18np("<1 bit>", "<%1 bits>", value
.toBitArray().size());
290 case QVariant::Bitmap
: {
291 QBitmap bitmap
= value
.value
<QBitmap
>();
292 return QString("<%1x%2px - %3bpp>").arg(bitmap
.width()).arg(bitmap
.height()).arg(bitmap
.depth());
294 case QVariant::ByteArray
: {
295 // Return the array size if it is not displayable
296 if (value
.toString().isEmpty()) {
297 return i18np("<1 byte>", "<%1 bytes>", value
.toByteArray().size());
300 return value
.toString();
303 case QVariant::Image
: {
304 QImage image
= value
.value
<QImage
>();
305 return QString("<%1x%2px - %3bpp>").arg(image
.width()).arg(image
.height()).arg(image
.depth());
307 case QVariant::Line
: {
308 QLine line
= value
.toLine();
309 return QString("<x1:%1, y1:%2, x2:%3, y2:%4>").arg(line
.x1()).arg(line
.y1()).arg(line
.x2()).arg(line
.y2());
311 case QVariant::LineF
: {
312 QLineF lineF
= value
.toLineF();
313 return QString("<x1:%1, y1:%2, x2:%3, y2:%4>").arg(lineF
.x1()).arg(lineF
.y1()).arg(lineF
.x2()).arg(lineF
.y2());
315 case QVariant::Locale
: {
316 return QString("%1").arg(value
.toLocale().name());
318 case QVariant::Map
: {
319 return i18np("<1 item>", "<%1 items>", value
.toMap().size());
321 case QVariant::Pixmap
: {
322 QPixmap pixmap
= value
.value
<QPixmap
>();
323 return QString("<%1x%2px - %3bpp>").arg(pixmap
.width()).arg(pixmap
.height()).arg(pixmap
.depth());
325 case QVariant::Point
: {
326 QPoint point
= value
.toPoint();
327 return QString("<x:%1, y:%2>").arg(point
.x()).arg(point
.y());
329 case QVariant::PointF
: {
330 QPointF pointF
= value
.toPointF();
331 return QString("<x:%1, y:%2>").arg(pointF
.x()).arg(pointF
.y());
333 case QVariant::Rect
: {
334 QRect rect
= value
.toRect();
335 return QString("<x:%1, y:%2, w:%3, h:%4>").arg(rect
.x()).arg(rect
.y()).arg(rect
.width()).arg(rect
.height());
337 case QVariant::RectF
: {
338 QRectF rectF
= value
.toRectF();
339 return QString("<x:%1, y:%2, w:%3, h:%4>").arg(rectF
.x()).arg(rectF
.y()).arg(rectF
.width()).arg(rectF
.height());
341 case QVariant::RegExp
: {
342 return QString("%1").arg(value
.toRegExp().pattern());
344 case QVariant::Region
: {
345 QRect region
= value
.value
<QRegion
>().boundingRect();
346 return QString("<x:%1, y:%2, w:%3, h:%4>").arg(region
.x()).arg(region
.y()).arg(region
.width()).arg(region
.height());
348 case QVariant::Size
: {
349 QSize size
= value
.toSize();
350 return QString("<w:%1, h:%2>").arg(size
.width()).arg(size
.height());
352 case QVariant::SizeF
: {
353 QSizeF sizeF
= value
.toSizeF();
354 return QString("<w:%1, h:%2>").arg(sizeF
.width()).arg(sizeF
.height());
356 case QVariant::Url
: {
357 return QString("%1").arg(value
.toUrl().toString());
361 if (QLatin1String(value
.typeName()) == "Soprano::Node") {
362 Soprano::Node node
= value
.value
<Soprano::Node
>();
363 if (node
.isLiteral()) {
364 return convertToString(node
.literal().variant());
365 } else if (node
.isResource()) {
366 return node
.uri().toString();
367 } else if (node
.isBlank()) {
368 return QString("_:%1").arg(node
.identifier());
372 Plasma::DataEngine::Data data
= value
.value
<Plasma::DataEngine::Data
>();
373 if (!data
.isEmpty()) {
375 QHashIterator
<QString
, QVariant
> it(data
);
377 while (it
.hasNext()) {
379 result
<< (it
.key() + ": " + it
.value().toString());
382 return result
.join("\n");
383 } else if (value
.canConvert(QVariant::String
)) {
384 if (value
.toString().isEmpty()) {
385 return i18nc("The user did a query to a dataengine and it returned empty data", "<empty>");
388 return value
.toString();
392 return i18nc("A the dataengine returned something that the humble view on the engineexplorer can't display, like a picture", "<not displayable>");
397 void EngineExplorer::showData(QStandardItem
* parent
, Plasma::DataEngine::Data data
)
400 Plasma::DataEngine::DataIterator
it(data
);
401 // parent->insertRows(0, data.count());
402 // parent->setColumnCount(3);
403 while (it
.hasNext()) {
405 parent
->setChild(rowCount
, 1, new QStandardItem(it
.key()));
406 if (it
.value().canConvert(QVariant::List
)) {
407 foreach(const QVariant
&var
, it
.value().toList()) {
408 QStandardItem
*item
= new QStandardItem(convertToString(var
));
409 item
->setToolTip(item
->text());
410 parent
->setChild(rowCount
, 2, item
);
411 parent
->setChild(rowCount
, 3, new QStandardItem(var
.typeName()));
416 QStandardItem
*item
= new QStandardItem(convertToString(it
.value()));
417 item
->setToolTip(item
->text());
418 parent
->setChild(rowCount
, 2, item
);
419 parent
->setChild(rowCount
, 3, new QStandardItem(it
.value().typeName()));
425 void EngineExplorer::updateTitle()
428 m_title
->setPixmap(KIcon("plasma").pixmap(IconSize(KIconLoader::Dialog
)));
429 m_title
->setText(i18n("Plasma DataEngine Explorer"));
433 m_title
->setText(ki18ncp("The name of the engine followed by the number of data sources",
434 "%1 Engine - 1 data source", "%1 Engine - %2 data sources")
435 .subs(KStringHandler::capwords(m_engine
->name()))
436 .subs(m_sourceCount
).toString());
437 if (m_engine
->icon().isEmpty()) {
438 m_title
->setPixmap(KIcon("plasma").pixmap(IconSize(KIconLoader::Dialog
)));
440 //m_title->setPixmap(KIcon("alarmclock").pixmap(IconSize(KIconLoader::Dialog)));
441 m_title
->setPixmap(KIcon(m_engine
->icon()).pixmap(IconSize(KIconLoader::Dialog
)));
445 #include "engineexplorer.moc"