00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "engineexplorer.h"
00021
00022 #include <QApplication>
00023 #include <QStandardItemModel>
00024 #include <QVBoxLayout>
00025 #include <QHBoxLayout>
00026 #include <QSpinBox>
00027 #include <QBitArray>
00028 #include <QBitmap>
00029
00030 #include <KAction>
00031 #include <KIconLoader>
00032 #include <KIconTheme>
00033 #include <KMenu>
00034 #include <KStandardAction>
00035 #include <KStringHandler>
00036
00037 #ifdef FOUND_SOPRANO
00038 #include <Soprano/Node>
00039 Q_DECLARE_METATYPE(Soprano::Node)
00040 #endif // FOUND_SOPRANO
00041 Q_DECLARE_METATYPE(Plasma::DataEngine::Data)
00042
00043 #include <Plasma/DataEngineManager>
00044
00045 #include "serviceviewer.h"
00046 #include "titlecombobox.h"
00047
00048 EngineExplorer::EngineExplorer(QWidget* parent)
00049 : KDialog(parent),
00050 m_engine(0),
00051 m_sourceCount(0),
00052 m_requestingSource(false)
00053 {
00054 #ifdef FOUND_SOPRANO
00055 (void) qRegisterMetaType<Soprano::Node>();
00056 #endif
00057 setWindowTitle(i18n("Plasma Engine Explorer"));
00058 QWidget* mainWidget = new QWidget(this);
00059 setMainWidget(mainWidget);
00060 setupUi(mainWidget);
00061
00062 m_engineManager = Plasma::DataEngineManager::self();
00063 m_dataModel = new QStandardItemModel(this);
00064 KIcon pix("plasma");
00065 int size = IconSize(KIconLoader::Dialog);
00066 m_title->setPixmap(pix.pixmap(size, size));
00067 connect(m_engines, SIGNAL(activated(QString)), this, SLOT(showEngine(QString)));
00068 connect(m_sourceRequesterButton, SIGNAL(clicked(bool)), this, SLOT(requestSource()));
00069 m_data->setModel(m_dataModel);
00070 m_data->setWordWrap(true);
00071
00072 m_searchLine->setTreeView(m_data);
00073 m_searchLine->setClickMessage(i18n("Search"));
00074
00075 listEngines();
00076 m_engines->setFocus();
00077
00078 setButtons(KDialog::Close | KDialog::User1 | KDialog::User2);
00079 setButtonText(KDialog::User1, i18n("Collapse All"));
00080 setButtonText(KDialog::User2, i18n("Expand All"));
00081 connect(this, SIGNAL(user1Clicked()), m_data, SLOT(collapseAll()));
00082 connect(this, SIGNAL(user2Clicked()), m_data, SLOT(expandAll()));
00083 enableButton(KDialog::User1, false);
00084 enableButton(KDialog::User2, false);
00085
00086 addAction(KStandardAction::quit(qApp, SLOT(quit()), this));
00087
00088 connect(m_data, SIGNAL(customContextMenuRequested(QPoint)),
00089 this, SLOT(showDataContextMenu(QPoint)));
00090 m_data->setContextMenuPolicy(Qt::CustomContextMenu);
00091 }
00092
00093 EngineExplorer::~EngineExplorer()
00094 {
00095 }
00096
00097 void EngineExplorer::setApp(const QString &app)
00098 {
00099 m_app = app;
00100
00101 if (m_engines->count() > 0) {
00102 listEngines();
00103 }
00104 }
00105
00106 void EngineExplorer::setEngine(const QString &engine)
00107 {
00108
00109 int index = m_engines->findText(engine);
00110 if (index != -1) {
00111 kDebug() << QString("Engine %1 found!").arg(engine);
00112 m_engines->setCurrentIndex(index);
00113 showEngine(engine);
00114 }
00115 }
00116
00117 void EngineExplorer::setInterval(const int interval)
00118 {
00119 m_updateInterval->setValue(interval);
00120 }
00121
00122 void EngineExplorer::dataUpdated(const QString& source, const Plasma::DataEngine::Data& data)
00123 {
00124 QList<QStandardItem*> items = m_dataModel->findItems(source, 0);
00125
00126 if (items.count() < 1) {
00127 return;
00128 }
00129
00130 QStandardItem* parent = items.first();
00131
00132 while (parent->hasChildren()) {
00133 parent->removeRow(0);
00134 }
00135
00136 showData(parent, data);
00137 }
00138
00139 void EngineExplorer::listEngines()
00140 {
00141 m_engines->clear();
00142 QStringList engines = m_engineManager->listAllEngines(m_app);
00143 qSort(engines);
00144 m_engines->addItems(engines);
00145 m_engines->setCurrentIndex(-1);
00146 }
00147
00148 void EngineExplorer::showEngine(const QString& name)
00149 {
00150 m_sourceRequester->setEnabled(false);
00151 m_sourceRequesterButton->setEnabled(false);
00152 enableButton(KDialog::User1, false);
00153 enableButton(KDialog::User2, false);
00154 m_dataModel->clear();
00155 m_dataModel->setColumnCount(4);
00156 QStringList headers;
00157 headers << i18n("DataSource") << i18n("Key") << i18n("Value") << i18n("Type");
00158 m_dataModel->setHorizontalHeaderLabels(headers);
00159 m_engine = 0;
00160 m_sourceCount = 0;
00161
00162 if (!m_engineName.isEmpty()) {
00163 m_engineManager->unloadEngine(m_engineName);
00164 }
00165
00166 m_engineName = name;
00167 if (m_engineName.isEmpty()) {
00168 updateTitle();
00169 return;
00170 }
00171
00172 m_engine = m_engineManager->loadEngine(m_engineName);
00173 if (!m_engine) {
00174 m_engineName.clear();
00175 updateTitle();
00176 return;
00177 }
00178
00179 QStringList sources = m_engine->sources();
00180
00181
00182
00183 foreach (const QString& source, sources) {
00184
00185 addSource(source);
00186 }
00187
00188 m_sourceRequesterButton->setEnabled(true);
00189 m_updateInterval->setEnabled(true);
00190 m_sourceRequester->setEnabled(true);
00191 m_sourceRequester->setFocus();
00192 connect(m_engine, SIGNAL(sourceAdded(QString)), this, SLOT(addSource(QString)));
00193 connect(m_engine, SIGNAL(sourceRemoved(QString)), this, SLOT(removeSource(QString)));
00194 updateTitle();
00195 }
00196
00197 void EngineExplorer::addSource(const QString& source)
00198 {
00199 QStandardItem* parent = new QStandardItem(source);
00200 m_dataModel->appendRow(parent);
00201
00202
00203 Plasma::DataEngine::Data data = m_engine->query(source);
00204 showData(parent, data);
00205
00206 if (!m_requestingSource || m_sourceRequester->text() != source) {
00207 m_engine->connectSource(source, this);
00208 }
00209
00210 ++m_sourceCount;
00211 updateTitle();
00212
00213 enableButton(KDialog::User1, true);
00214 enableButton(KDialog::User2, true);
00215 }
00216
00217 void EngineExplorer::removeSource(const QString& source)
00218 {
00219 QList<QStandardItem*> items = m_dataModel->findItems(source, 0);
00220
00221 if (items.count() < 1) {
00222 return;
00223 }
00224
00225 foreach (QStandardItem* item, items) {
00226 m_dataModel->removeRow(item->row());
00227 }
00228
00229 --m_sourceCount;
00230 m_engine->disconnectSource(source, this);
00231 updateTitle();
00232 }
00233
00234 void EngineExplorer::requestSource()
00235 {
00236 requestSource(m_sourceRequester->text());
00237 }
00238
00239 void EngineExplorer::requestSource(const QString &source)
00240 {
00241 if (!m_engine || source.isEmpty()) {
00242 return;
00243 }
00244
00245 kDebug() << "request source" << source;
00246 m_requestingSource = true;
00247 m_engine->connectSource(source, this, (uint)m_updateInterval->value());
00248 m_requestingSource = false;
00249 }
00250
00251 void EngineExplorer::showDataContextMenu(const QPoint &point)
00252 {
00253 QModelIndex index = m_data->indexAt(point);
00254 if (index.isValid()) {
00255 if (index.parent().isValid()) {
00256 index = index.parent();
00257 }
00258
00259 if (index.column() != 0) {
00260 index = m_dataModel->index(index.row(), 0);
00261 }
00262
00263 QString source = index.data().toString();
00264 KMenu menu;
00265 menu.addTitle(source);
00266 QAction *service = menu.addAction(i18n("Get associated service"));
00267 QAction *update = menu.addAction(i18n("Update source now"));
00268 QAction *remove = menu.addAction(i18n("Remove source"));
00269
00270 QAction *activated = menu.exec(m_data->viewport()->mapToGlobal(point));
00271 if (activated == service) {
00272 ServiceViewer *viewer = new ServiceViewer(m_engine, source);
00273 viewer->show();
00274 } else if (activated == update) {
00275 m_engine->connectSource(source, this);
00276 Plasma::DataEngine::Data data = m_engine->query(source);
00277 } else if (activated == remove) {
00278 removeSource(source);
00279 }
00280 }
00281 }
00282
00283 QString EngineExplorer::convertToString(const QVariant &value) const
00284 {
00285 switch (value.type())
00286 {
00287 case QVariant::BitArray: {
00288 return i18np("<1 bit>", "<%1 bits>", value.toBitArray().size());
00289 }
00290 case QVariant::Bitmap: {
00291 QBitmap bitmap = value.value<QBitmap>();
00292 return QString("<%1x%2px - %3bpp>").arg(bitmap.width()).arg(bitmap.height()).arg(bitmap.depth());
00293 }
00294 case QVariant::ByteArray: {
00295
00296 if (value.toString().isEmpty()) {
00297 return i18np("<1 byte>", "<%1 bytes>", value.toByteArray().size());
00298 }
00299 else {
00300 return value.toString();
00301 }
00302 }
00303 case QVariant::Image: {
00304 QImage image = value.value<QImage>();
00305 return QString("<%1x%2px - %3bpp>").arg(image.width()).arg(image.height()).arg(image.depth());
00306 }
00307 case QVariant::Line: {
00308 QLine line = value.toLine();
00309 return QString("<x1:%1, y1:%2, x2:%3, y2:%4>").arg(line.x1()).arg(line.y1()).arg(line.x2()).arg(line.y2());
00310 }
00311 case QVariant::LineF: {
00312 QLineF lineF = value.toLineF();
00313 return QString("<x1:%1, y1:%2, x2:%3, y2:%4>").arg(lineF.x1()).arg(lineF.y1()).arg(lineF.x2()).arg(lineF.y2());
00314 }
00315 case QVariant::Locale: {
00316 return QString("%1").arg(value.toLocale().name());
00317 }
00318 case QVariant::Map: {
00319 return i18np("<1 item>", "<%1 items>", value.toMap().size());
00320 }
00321 case QVariant::Pixmap: {
00322 QPixmap pixmap = value.value<QPixmap>();
00323 return QString("<%1x%2px - %3bpp>").arg(pixmap.width()).arg(pixmap.height()).arg(pixmap.depth());
00324 }
00325 case QVariant::Point: {
00326 QPoint point = value.toPoint();
00327 return QString("<x:%1, y:%2>").arg(point.x()).arg(point.y());
00328 }
00329 case QVariant::PointF: {
00330 QPointF pointF = value.toPointF();
00331 return QString("<x:%1, y:%2>").arg(pointF.x()).arg(pointF.y());
00332 }
00333 case QVariant::Rect: {
00334 QRect rect = value.toRect();
00335 return QString("<x:%1, y:%2, w:%3, h:%4>").arg(rect.x()).arg(rect.y()).arg(rect.width()).arg(rect.height());
00336 }
00337 case QVariant::RectF: {
00338 QRectF rectF = value.toRectF();
00339 return QString("<x:%1, y:%2, w:%3, h:%4>").arg(rectF.x()).arg(rectF.y()).arg(rectF.width()).arg(rectF.height());
00340 }
00341 case QVariant::RegExp: {
00342 return QString("%1").arg(value.toRegExp().pattern());
00343 }
00344 case QVariant::Region: {
00345 QRect region = value.value<QRegion>().boundingRect();
00346 return QString("<x:%1, y:%2, w:%3, h:%4>").arg(region.x()).arg(region.y()).arg(region.width()).arg(region.height());
00347 }
00348 case QVariant::Size: {
00349 QSize size = value.toSize();
00350 return QString("<w:%1, h:%2>").arg(size.width()).arg(size.height());
00351 }
00352 case QVariant::SizeF: {
00353 QSizeF sizeF = value.toSizeF();
00354 return QString("<w:%1, h:%2>").arg(sizeF.width()).arg(sizeF.height());
00355 }
00356 case QVariant::Url: {
00357 return QString("%1").arg(value.toUrl().toString());
00358 }
00359 default: {
00360 #ifdef FOUND_SOPRANO
00361 if (QLatin1String(value.typeName()) == "Soprano::Node") {
00362 Soprano::Node node = value.value<Soprano::Node>();
00363 if (node.isLiteral()) {
00364 return convertToString(node.literal().variant());
00365 } else if (node.isResource()) {
00366 return node.uri().toString();
00367 } else if (node.isBlank()) {
00368 return QString("_:%1").arg(node.identifier());
00369 }
00370 }
00371 #endif
00372 Plasma::DataEngine::Data data = value.value<Plasma::DataEngine::Data>();
00373 if (!data.isEmpty()) {
00374 QStringList result;
00375 QHashIterator<QString, QVariant> it(data);
00376
00377 while (it.hasNext()) {
00378 it.next();
00379 result << (it.key() + ": " + it.value().toString());
00380 }
00381
00382 return result.join("\n");
00383 } else if (value.canConvert(QVariant::String)) {
00384 if (value.toString().isEmpty()) {
00385 return i18nc("The user did a query to a dataengine and it returned empty data", "<empty>");
00386 }
00387 else {
00388 return value.toString();
00389 }
00390 }
00391
00392 return i18nc("A the dataengine returned something that the humble view on the engineexplorer can't display, like a picture", "<not displayable>");
00393 }
00394 }
00395 }
00396
00397 void EngineExplorer::showData(QStandardItem* parent, Plasma::DataEngine::Data data)
00398 {
00399 int rowCount = 0;
00400 Plasma::DataEngine::DataIterator it(data);
00401
00402
00403 while (it.hasNext()) {
00404 it.next();
00405 parent->setChild(rowCount, 1, new QStandardItem(it.key()));
00406 if (it.value().canConvert(QVariant::List)) {
00407 foreach(const QVariant &var, it.value().toList()) {
00408 QStandardItem *item = new QStandardItem(convertToString(var));
00409 item->setToolTip(item->text());
00410 parent->setChild(rowCount, 2, item);
00411 parent->setChild(rowCount, 3, new QStandardItem(var.typeName()));
00412 ++rowCount;
00413 }
00414 }
00415 else {
00416 QStandardItem *item = new QStandardItem(convertToString(it.value()));
00417 item->setToolTip(item->text());
00418 parent->setChild(rowCount, 2, item);
00419 parent->setChild(rowCount, 3, new QStandardItem(it.value().typeName()));
00420 ++rowCount;
00421 }
00422 }
00423 }
00424
00425 void EngineExplorer::updateTitle()
00426 {
00427 if (!m_engine) {
00428 m_title->setPixmap(KIcon("plasma").pixmap(IconSize(KIconLoader::Dialog)));
00429 m_title->setText(i18n("Plasma DataEngine Explorer"));
00430 return;
00431 }
00432
00433 m_title->setText(ki18ncp("The name of the engine followed by the number of data sources",
00434 "%1 Engine - 1 data source", "%1 Engine - %2 data sources")
00435 .subs(KStringHandler::capwords(m_engine->name()))
00436 .subs(m_sourceCount).toString());
00437 if (m_engine->icon().isEmpty()) {
00438 m_title->setPixmap(KIcon("plasma").pixmap(IconSize(KIconLoader::Dialog)));
00439 } else {
00440
00441 m_title->setPixmap(KIcon(m_engine->icon()).pixmap(IconSize(KIconLoader::Dialog)));
00442 }
00443 }
00444
00445 #include "engineexplorer.moc"
00446