From 24b5a2a22c41eef100e3f67edf127930da518478 Mon Sep 17 00:00:00 2001 From: ivan tkachenko Date: Sun, 16 Jan 2022 02:34:25 +0300 Subject: [PATCH 01/15] engineexplorer: Port away from foreach macro It's deprecated and inefficient. --- engineexplorer/engineexplorer.cpp | 10 ++++++---- engineexplorer/ktreeviewsearchline.cpp | 22 +++++++++++----------- engineexplorer/modelviewer.cpp | 11 +++++++---- engineexplorer/serviceviewer.cpp | 4 ++-- 4 files changed, 26 insertions(+), 21 deletions(-) diff --git a/engineexplorer/engineexplorer.cpp b/engineexplorer/engineexplorer.cpp index cf38fdb9..2e3e0101 100644 --- a/engineexplorer/engineexplorer.cpp +++ b/engineexplorer/engineexplorer.cpp @@ -192,7 +192,8 @@ void EngineExplorer::showEngine(const QString &name) // qDebug() << "we have " << sources.count() << " data sources"; connect(m_engine, &Plasma::DataEngine::sourceAdded, this, &EngineExplorer::addSource); connect(m_engine, &Plasma::DataEngine::sourceRemoved, this, &EngineExplorer::removeSource); - foreach (const QString &source, m_engine->sources()) { + const QStringList &sources = m_engine->sources(); + for (const QString &source : sources) { // qDebug() << "adding " << source; addSource(source); } @@ -232,13 +233,13 @@ void EngineExplorer::addSource(const QString &source) void EngineExplorer::removeSource(const QString &source) { - QList items = m_dataModel->findItems(source, Qt::MatchExactly); + const QList items = m_dataModel->findItems(source, Qt::MatchExactly); if (items.count() < 1) { return; } - foreach (QStandardItem *item, items) { + for (QStandardItem *item : items) { m_dataModel->removeRow(item->row()); } @@ -442,7 +443,8 @@ int EngineExplorer::showData(QStandardItem *parent, Plasma::DataEngine::Data dat if (it.value().canConvert(QVariant::List) /* && ! it.value().type() == QVariant::StringList */) { bool first = true; - foreach (const QVariant &var, it.value().toList()) { + const auto &list = it.value().toList(); + for (const QVariant &var : list) { QStandardItem *item = new QStandardItem(convertToString(var)); if (!first) { parent->setChild(rowCount, 1, new QStandardItem(QString())); diff --git a/engineexplorer/ktreeviewsearchline.cpp b/engineexplorer/ktreeviewsearchline.cpp index d360721e..74c89593 100644 --- a/engineexplorer/ktreeviewsearchline.cpp +++ b/engineexplorer/ktreeviewsearchline.cpp @@ -72,17 +72,14 @@ void KTreeViewSearchLinePrivate::rowsInserted(QAbstractItemModel *model, const Q return; } - QTreeView *widget = nullptr; - foreach (QTreeView *tree, treeViews) - if (tree->model() == model) { - widget = tree; - break; - } - - if (!widget) { + const auto it = std::find_if(treeViews.cbegin(), treeViews.cend(), [=](QTreeView *tree) { + return tree->model() == model; + }); + if (it == treeViews.cend()) { return; } + QTreeView *widget = *it; for (int i = start; i <= end; ++i) { widget->setRowHidden(i, parentIndex, !parent->itemMatches(parentIndex, i, parent->text())); } @@ -302,8 +299,9 @@ void KTreeViewSearchLine::updateSearch(const QString &pattern) { d->search = pattern.isNull() ? text() : pattern; - foreach (QTreeView *treeView, d->treeViews) + for (QTreeView *treeView : std::as_const(d->treeViews)) { updateSearch(treeView); + } } void KTreeViewSearchLine::updateSearch(QTreeView *treeView) @@ -364,13 +362,15 @@ void KTreeViewSearchLine::setTreeView(QTreeView *treeView) void KTreeViewSearchLine::setTreeViews(const QList &treeViews) { - foreach (QTreeView *treeView, d->treeViews) + for (QTreeView *treeView : std::as_const(d->treeViews)) { disconnectTreeView(treeView); + } d->treeViews = treeViews; - foreach (QTreeView *treeView, d->treeViews) + for (QTreeView *treeView : std::as_const(d->treeViews)) { connectTreeView(treeView); + } d->checkColumns(); diff --git a/engineexplorer/modelviewer.cpp b/engineexplorer/modelviewer.cpp index 418b8e49..f53e869c 100644 --- a/engineexplorer/modelviewer.cpp +++ b/engineexplorer/modelviewer.cpp @@ -34,16 +34,19 @@ void Delegate::paint(QPainter *painter, const QStyleOptionViewItem &option, cons return; } + const QHash roleNames = index.model()->roleNames(); + const QList roles = roleNames.keys(); + QFontMetrics fm(option.font); int maxWidth = 0; - foreach (int role, index.model()->roleNames().keys()) { - const QString text = index.model()->roleNames().value(role) + QLatin1String(": "); + for (int role : roles) { + const QString text = roleNames.value(role) + QLatin1String(": "); maxWidth = qMax(maxWidth, fm.boundingRect(text).width()); } int i = 2; - foreach (int role, index.model()->roleNames().keys()) { - const QString text = index.model()->roleNames().value(role) + QLatin1String(": "); + for (int role : roles) { + const QString text = roleNames.value(role) + QLatin1String(": "); painter->drawText(option.rect.x() + maxWidth - fm.boundingRect(text).width(), option.rect.y() + i * fm.height(), text); if (index.data(role).canConvert()) { diff --git a/engineexplorer/serviceviewer.cpp b/engineexplorer/serviceviewer.cpp index 82b30f53..4ce9be1e 100644 --- a/engineexplorer/serviceviewer.cpp +++ b/engineexplorer/serviceviewer.cpp @@ -103,7 +103,7 @@ void ServiceViewer::updateOperations() if (!operations.isEmpty()) { enable = true; - foreach (const QString &operation, operations) { + for (const QString &operation : operations) { m_operations->addItem(operation); } } @@ -155,7 +155,7 @@ void ServiceViewer::operationSelected(const QString &operation) int i = 0; const QStringList keys = desc.keys(); m_operationDescription->setRowCount(keys.count()); - foreach (const QString &key, keys) { + for (const QString &key : keys) { QTableWidgetItem *item = new QTableWidgetItem(key); item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); m_operationDescription->setItem(i, 0, item); -- GitLab From 4739c5dc9978fed5ec56b15662225dfe8b5b3e1e Mon Sep 17 00:00:00 2001 From: ivan tkachenko Date: Sun, 16 Jan 2022 02:35:34 +0300 Subject: [PATCH 02/15] engineexplorer: Fix kf.i18n warning kf.i18n: "0 instead of 3 arguments to message {%1 service for %2 Da...} supplied before conversion." --- engineexplorer/serviceviewer.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engineexplorer/serviceviewer.ui b/engineexplorer/serviceviewer.ui index 8e21501f..6c94a78a 100644 --- a/engineexplorer/serviceviewer.ui +++ b/engineexplorer/serviceviewer.ui @@ -90,7 +90,7 @@ - %1 service for %2 DataEngine source %3 + Engine; Source; Service -- GitLab From 105c926345d5b5a403c7f148aa4421eec96e30ef Mon Sep 17 00:00:00 2001 From: ivan tkachenko Date: Sun, 16 Jan 2022 02:49:49 +0300 Subject: [PATCH 03/15] engineexplorer: Shorten UI label Since this is a user-facing string, and "Source" is not represented as a "DataSource", then "DataEngine" shall be simply "Engine". --- engineexplorer/serviceviewer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engineexplorer/serviceviewer.cpp b/engineexplorer/serviceviewer.cpp index 4ce9be1e..3e6f3984 100644 --- a/engineexplorer/serviceviewer.cpp +++ b/engineexplorer/serviceviewer.cpp @@ -72,7 +72,7 @@ ServiceViewer::ServiceViewer(Plasma::DataEngine *engine, const QString &source, setWindowTitle(i18nc("%1 is a Plasma service name", "%1 Service Explorer", serviceName)); QString title = i18nc("Source: name of the data, Service: writes data instead of fetching", - "DataEngine: %1; Source: %2; Service: %3", + "Engine: %1; Source: %2; Service: %3", engineName, m_source, serviceName); -- GitLab From ddd591962506dbb8bf97a573febac79f89889dca Mon Sep 17 00:00:00 2001 From: ivan tkachenko Date: Sun, 16 Jan 2022 05:03:30 +0300 Subject: [PATCH 04/15] engineexplorer: Fix logs --- engineexplorer/modelviewer.cpp | 2 +- engineexplorer/serviceviewer.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/engineexplorer/modelviewer.cpp b/engineexplorer/modelviewer.cpp index f53e869c..c8f4c25e 100644 --- a/engineexplorer/modelviewer.cpp +++ b/engineexplorer/modelviewer.cpp @@ -88,7 +88,7 @@ ModelViewer::ModelViewer(Plasma::DataEngine *engine, const QString &source, QWid if (m_engine->pluginInfo().isValid()) { engineName = KStringHandler::capwords(m_engine->pluginInfo().name()); } - qDebug() << "########### CALLING SERVICE FOR SOURCE: " << m_source; + qDebug() << "Requesting model for source:" << m_source; m_model = m_engine->modelForSource(m_source); if (m_model != nullptr) { diff --git a/engineexplorer/serviceviewer.cpp b/engineexplorer/serviceviewer.cpp index 3e6f3984..dd140fda 100644 --- a/engineexplorer/serviceviewer.cpp +++ b/engineexplorer/serviceviewer.cpp @@ -55,7 +55,7 @@ ServiceViewer::ServiceViewer(Plasma::DataEngine *engine, const QString &source, if (m_engine->pluginInfo().isValid()) { engineName = KStringHandler::capwords(m_engine->pluginInfo().name()); } - qDebug() << "########### CALLING SERVICE FOR SOURCE: " << m_source; + qDebug() << "Requesting service for source" << m_source; m_service = m_engine->serviceForSource(m_source); if (m_service != nullptr) { -- GitLab From 67893c9eefd6d94e4f1ec27f8b6c3edce5552b28 Mon Sep 17 00:00:00 2001 From: ivan tkachenko Date: Sun, 16 Jan 2022 03:50:52 +0300 Subject: [PATCH 05/15] engineexplorer: Switch from Java-style to STL iterators Unfortunately, couldn't use the for-range loops, because default iterator of QMap *dereferences to values only. --- engineexplorer/engineexplorer.cpp | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/engineexplorer/engineexplorer.cpp b/engineexplorer/engineexplorer.cpp index 2e3e0101..c62d5a82 100644 --- a/engineexplorer/engineexplorer.cpp +++ b/engineexplorer/engineexplorer.cpp @@ -344,9 +344,7 @@ QString EngineExplorer::convertToString(const QVariant &value) QVariantMap map = value.toMap(); QString str = i18np("<1 item>", "<%1 items>", map.size()); - QMapIterator it(map); - while (it.hasNext()) { - it.next(); + for (auto it = map.constBegin(); it != map.constEnd(); it++) { str += "\n" + it.key() + ": " + convertToString(it.value()); } @@ -410,10 +408,8 @@ QString EngineExplorer::convertToString(const QVariant &value) Plasma::DataEngine::Data data = value.value(); if (!data.isEmpty()) { QStringList result; - QMapIterator it(data); - while (it.hasNext()) { - it.next(); + for (auto it = data.constBegin(); it != data.constEnd(); it++) { result << (it.key() + ": " + convertToString(it.value())); } @@ -434,11 +430,8 @@ QString EngineExplorer::convertToString(const QVariant &value) int EngineExplorer::showData(QStandardItem *parent, Plasma::DataEngine::Data data) { int rowCount = 0; - Plasma::DataEngine::DataIterator it(data); - // parent->insertRows(0, data.count()); - // parent->setColumnCount(3); - while (it.hasNext()) { - it.next(); + + for (auto it = data.constBegin(); it != data.constEnd(); it++) { parent->setChild(rowCount, 1, new QStandardItem(it.key())); if (it.value().canConvert(QVariant::List) /* && ! it.value().type() == QVariant::StringList */) { -- GitLab From 2800a58c9e5a664b09085b906e95d470311cd5a0 Mon Sep 17 00:00:00 2001 From: ivan tkachenko Date: Sun, 16 Jan 2022 04:19:20 +0300 Subject: [PATCH 06/15] engineexplorer: Add tooltips to DataSource and Key columns They sometimes happen to be large enough not to fit, and unfortunately Qt does not handle that automatically. --- engineexplorer/engineexplorer.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/engineexplorer/engineexplorer.cpp b/engineexplorer/engineexplorer.cpp index c62d5a82..cf2c09ce 100644 --- a/engineexplorer/engineexplorer.cpp +++ b/engineexplorer/engineexplorer.cpp @@ -217,6 +217,7 @@ void EngineExplorer::addSource(const QString &source) } QStandardItem *parent = new QStandardItem(source); + parent->setToolTip(source); m_dataModel->appendRow(parent); // qDebug() << "getting data for source " << source; @@ -432,7 +433,10 @@ int EngineExplorer::showData(QStandardItem *parent, Plasma::DataEngine::Data dat int rowCount = 0; for (auto it = data.constBegin(); it != data.constEnd(); it++) { - parent->setChild(rowCount, 1, new QStandardItem(it.key())); + QStandardItem *keyItem = new QStandardItem(it.key()); + keyItem->setToolTip(it.key()); + parent->setChild(rowCount, 1, keyItem); + if (it.value().canConvert(QVariant::List) /* && ! it.value().type() == QVariant::StringList */) { bool first = true; -- GitLab From eb4d19d3cab9aff6c1549b4457e002836ded6cb9 Mon Sep 17 00:00:00 2001 From: ivan tkachenko Date: Sun, 16 Jan 2022 04:23:50 +0300 Subject: [PATCH 07/15] engineexplorer: Shuffle code a bit ...so that it makes more sense when reading it. --- engineexplorer/engineexplorer.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/engineexplorer/engineexplorer.cpp b/engineexplorer/engineexplorer.cpp index cf2c09ce..5db3e8d2 100644 --- a/engineexplorer/engineexplorer.cpp +++ b/engineexplorer/engineexplorer.cpp @@ -442,10 +442,10 @@ int EngineExplorer::showData(QStandardItem *parent, Plasma::DataEngine::Data dat bool first = true; const auto &list = it.value().toList(); for (const QVariant &var : list) { - QStandardItem *item = new QStandardItem(convertToString(var)); if (!first) { parent->setChild(rowCount, 1, new QStandardItem(QString())); } + QStandardItem *item = new QStandardItem(convertToString(var)); item->setToolTip(item->text()); parent->setChild(rowCount, 2, item); parent->setChild(rowCount, 3, new QStandardItem(var.typeName())); @@ -453,13 +453,9 @@ int EngineExplorer::showData(QStandardItem *parent, Plasma::DataEngine::Data dat ++rowCount; } } else { - QStandardItem *item; - if (it.value().canConvert()) { - item = new QStandardItem(it.value().value(), ""); - } else { - item = new QStandardItem(convertToString(it.value())); - } - + QStandardItem *item = (it.value().canConvert()) + ? new QStandardItem(it.value().value(), "") + : new QStandardItem(convertToString(it.value())); item->setToolTip(item->text()); parent->setChild(rowCount, 2, item); parent->setChild(rowCount, 3, new QStandardItem(it.value().typeName())); -- GitLab From fb4417acdc3276368029d599266274d9f6627e48 Mon Sep 17 00:00:00 2001 From: ivan tkachenko Date: Sat, 15 Jan 2022 23:03:35 +0300 Subject: [PATCH 08/15] engineexplorer: Swap Type and Value columns Even though it is possible to rearrange columns at runtime, it's often better to provide good defaults. And I feel like having Type on the left of Value is a good default. --- engineexplorer/engineexplorer.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/engineexplorer/engineexplorer.cpp b/engineexplorer/engineexplorer.cpp index 5db3e8d2..379f035c 100644 --- a/engineexplorer/engineexplorer.cpp +++ b/engineexplorer/engineexplorer.cpp @@ -166,7 +166,7 @@ void EngineExplorer::showEngine(const QString &name) m_dataModel->clear(); m_dataModel->setColumnCount(4); QStringList headers; - headers << i18n("DataSource") << i18n("Key") << i18n("Value") << i18n("Type"); + headers << i18n("DataSource") << i18n("Key") << i18n("Type") << i18n("Value"); m_dataModel->setHorizontalHeaderLabels(headers); m_engine = nullptr; m_sourceCount = 0; @@ -445,20 +445,20 @@ int EngineExplorer::showData(QStandardItem *parent, Plasma::DataEngine::Data dat if (!first) { parent->setChild(rowCount, 1, new QStandardItem(QString())); } + parent->setChild(rowCount, 2, new QStandardItem(var.typeName())); QStandardItem *item = new QStandardItem(convertToString(var)); item->setToolTip(item->text()); - parent->setChild(rowCount, 2, item); - parent->setChild(rowCount, 3, new QStandardItem(var.typeName())); + parent->setChild(rowCount, 3, item); first = false; ++rowCount; } } else { + parent->setChild(rowCount, 2, new QStandardItem(it.value().typeName())); QStandardItem *item = (it.value().canConvert()) ? new QStandardItem(it.value().value(), "") : new QStandardItem(convertToString(it.value())); item->setToolTip(item->text()); - parent->setChild(rowCount, 2, item); - parent->setChild(rowCount, 3, new QStandardItem(it.value().typeName())); + parent->setChild(rowCount, 3, item); ++rowCount; } } -- GitLab From e9e3808d94418e46749a3ab260b447d4e9ce0abc Mon Sep 17 00:00:00 2001 From: ivan tkachenko Date: Sun, 16 Jan 2022 05:52:45 +0300 Subject: [PATCH 09/15] engineexplorer: Display lists as expandable trees QVariantList and QStringList are now displayed as tree entries, with one row per element. Types of individual elements are now also displayed on their rows. Total list length is shown as its "Value" column. Test plan: - child items do not appear for non-list data. - context menu for expanded list rows is the same. - when items are removed from list-valued data, corresponding rows disappear from the table. --- engineexplorer/engineexplorer.cpp | 48 ++++++++++++++++++++----------- engineexplorer/engineexplorer.h | 1 + 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/engineexplorer/engineexplorer.cpp b/engineexplorer/engineexplorer.cpp index 379f035c..6c90c37b 100644 --- a/engineexplorer/engineexplorer.cpp +++ b/engineexplorer/engineexplorer.cpp @@ -118,6 +118,13 @@ void EngineExplorer::setInterval(const int interval) m_updateInterval->setValue(interval); } +void EngineExplorer::removeExtraRows(QStandardItem *parent, int preserve) +{ + if (parent->rowCount() > preserve) { + parent->removeRows(preserve, parent->rowCount() - preserve); + } +} + void EngineExplorer::dataUpdated(const QString &source, const Plasma::DataEngine::Data &data) { QList items = m_dataModel->findItems(source, Qt::MatchExactly); @@ -129,10 +136,7 @@ void EngineExplorer::dataUpdated(const QString &source, const Plasma::DataEngine QStandardItem *parent = items.first(); int rows = showData(parent, data); - - while (parent->rowCount() > rows) { - parent->removeRow(rows); - } + removeExtraRows(parent, rows); } void EngineExplorer::listEngines() @@ -276,7 +280,7 @@ void EngineExplorer::showDataContextMenu(const QPoint &point) { QModelIndex index = m_data->indexAt(point); if (index.isValid()) { - if (index.parent().isValid()) { + while (index.parent().isValid()) { index = index.parent(); } @@ -433,34 +437,44 @@ int EngineExplorer::showData(QStandardItem *parent, Plasma::DataEngine::Data dat int rowCount = 0; for (auto it = data.constBegin(); it != data.constEnd(); it++) { + // QTreeView only expands tree for children of column #zero. + QStandardItem *listRootItem = new QStandardItem(); + parent->setChild(rowCount, 0, listRootItem); + QStandardItem *keyItem = new QStandardItem(it.key()); keyItem->setToolTip(it.key()); parent->setChild(rowCount, 1, keyItem); - if (it.value().canConvert(QVariant::List) /* && ! it.value().type() == QVariant::StringList - */) { - bool first = true; + if (it.value().canConvert(QVariant::List)) { const auto &list = it.value().toList(); - for (const QVariant &var : list) { - if (!first) { - parent->setChild(rowCount, 1, new QStandardItem(QString())); - } - parent->setChild(rowCount, 2, new QStandardItem(var.typeName())); + + QStandardItem *listTypeItem = new QStandardItem(it.value().typeName()); + listTypeItem->setToolTip(listTypeItem->text()); + parent->setChild(rowCount, 2, listTypeItem); + parent->setChild(rowCount, 3, new QStandardItem(ki18ncp("Length of the list", "<%1 item>", "<%1 items>").subs(list.length()).toString())); + + int subRowCount = 0; + for (const auto &var : list) { + listRootItem->setChild(subRowCount, 1, new QStandardItem(QString::number(subRowCount))); + listRootItem->setChild(subRowCount, 2, new QStandardItem(var.typeName())); + QStandardItem *item = new QStandardItem(convertToString(var)); item->setToolTip(item->text()); - parent->setChild(rowCount, 3, item); - first = false; - ++rowCount; + listRootItem->setChild(subRowCount, 3, item); + + subRowCount++; } + removeExtraRows(listRootItem, subRowCount); } else { + removeExtraRows(listRootItem, 0); parent->setChild(rowCount, 2, new QStandardItem(it.value().typeName())); QStandardItem *item = (it.value().canConvert()) ? new QStandardItem(it.value().value(), "") : new QStandardItem(convertToString(it.value())); item->setToolTip(item->text()); parent->setChild(rowCount, 3, item); - ++rowCount; } + ++rowCount; } return rowCount; diff --git a/engineexplorer/engineexplorer.h b/engineexplorer/engineexplorer.h index 7f06f954..6e6804d5 100644 --- a/engineexplorer/engineexplorer.h +++ b/engineexplorer/engineexplorer.h @@ -56,6 +56,7 @@ private: int showData(QStandardItem *parent, Plasma::DataEngine::Data data); void updateTitle(); void enableButtons(bool enable); + void removeExtraRows(QStandardItem *parent, int preserve); Plasma::PluginLoader *m_engineManager; QStandardItemModel *m_dataModel; -- GitLab From fde509ef81503db70fbbfe02f32c481ade7f5b62 Mon Sep 17 00:00:00 2001 From: ivan tkachenko Date: Sun, 16 Jan 2022 17:57:17 +0300 Subject: [PATCH 10/15] engineexplorer: Replace canConvert(int) with template method Template method canConvert provides a nicer syntax. Also, QVariant:: data types are deprecated in favor of their QMetaType:: equivalent. --- engineexplorer/engineexplorer.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/engineexplorer/engineexplorer.cpp b/engineexplorer/engineexplorer.cpp index 6c90c37b..a98fa925 100644 --- a/engineexplorer/engineexplorer.cpp +++ b/engineexplorer/engineexplorer.cpp @@ -419,11 +419,12 @@ QString EngineExplorer::convertToString(const QVariant &value) } return result.join("\n"); - } else if (value.canConvert(QVariant::String)) { - if (value.toString().isEmpty()) { + } else if (value.canConvert()) { + QString str = value.toString(); + if (str.isEmpty()) { return i18nc("The user did a query to a dataengine and it returned empty data", ""); } else { - return value.toString(); + return str; } } @@ -445,7 +446,7 @@ int EngineExplorer::showData(QStandardItem *parent, Plasma::DataEngine::Data dat keyItem->setToolTip(it.key()); parent->setChild(rowCount, 1, keyItem); - if (it.value().canConvert(QVariant::List)) { + if (it.value().canConvert()) { const auto &list = it.value().toList(); QStandardItem *listTypeItem = new QStandardItem(it.value().typeName()); -- GitLab From 1d50a32cc0098f7478a71f313b832ab4a62f9da2 Mon Sep 17 00:00:00 2001 From: ivan tkachenko Date: Sun, 16 Jan 2022 18:36:02 +0300 Subject: [PATCH 11/15] engineexplorer: Prepare tree model code for recursion Currently QVariantList (and by extension QStringList) is the only supported container -- that hasn't changed yet. --- engineexplorer/engineexplorer.cpp | 74 +++++++++++++++++-------------- engineexplorer/engineexplorer.h | 2 + 2 files changed, 42 insertions(+), 34 deletions(-) diff --git a/engineexplorer/engineexplorer.cpp b/engineexplorer/engineexplorer.cpp index a98fa925..21ffb3e8 100644 --- a/engineexplorer/engineexplorer.cpp +++ b/engineexplorer/engineexplorer.cpp @@ -436,48 +436,54 @@ QString EngineExplorer::convertToString(const QVariant &value) int EngineExplorer::showData(QStandardItem *parent, Plasma::DataEngine::Data data) { int rowCount = 0; - for (auto it = data.constBegin(); it != data.constEnd(); it++) { - // QTreeView only expands tree for children of column #zero. - QStandardItem *listRootItem = new QStandardItem(); - parent->setChild(rowCount, 0, listRootItem); + showData(parent, rowCount++, it.key(), it.value()); + } + return rowCount; +} - QStandardItem *keyItem = new QStandardItem(it.key()); - keyItem->setToolTip(it.key()); - parent->setChild(rowCount, 1, keyItem); +void EngineExplorer::showData(QStandardItem *parent, int row, const QString &key, const QVariant &value) +{ + // QTreeView only expands tree for children of column #zero. + QStandardItem *current = new QStandardItem(); + parent->setChild(row, 0, current); - if (it.value().canConvert()) { - const auto &list = it.value().toList(); + QStandardItem *keyItem = new QStandardItem(key); + keyItem->setToolTip(key); + parent->setChild(row, 1, keyItem); - QStandardItem *listTypeItem = new QStandardItem(it.value().typeName()); - listTypeItem->setToolTip(listTypeItem->text()); - parent->setChild(rowCount, 2, listTypeItem); - parent->setChild(rowCount, 3, new QStandardItem(ki18ncp("Length of the list", "<%1 item>", "<%1 items>").subs(list.length()).toString())); + const char *typeName = value.typeName(); + int rowCount = 0; - int subRowCount = 0; - for (const auto &var : list) { - listRootItem->setChild(subRowCount, 1, new QStandardItem(QString::number(subRowCount))); - listRootItem->setChild(subRowCount, 2, new QStandardItem(var.typeName())); + if (value.canConvert()) { + const QVariantList list = value.toList(); + rowCount = showContainerData(parent, current, row, typeName, list); + } else { + parent->setChild(row, 2, new QStandardItem(typeName)); + // clang-format off + QStandardItem *item = value.canConvert() + ? new QStandardItem(value.value(), "") + : new QStandardItem(convertToString(value)); + // clang-format on + item->setToolTip(item->text()); + parent->setChild(row, 3, item); + // leave rowCount at value 0 + } + removeExtraRows(current, rowCount); +} - QStandardItem *item = new QStandardItem(convertToString(var)); - item->setToolTip(item->text()); - listRootItem->setChild(subRowCount, 3, item); +int EngineExplorer::showContainerData(QStandardItem *parent, QStandardItem *current, int row, const char *typeName, const QVariantList &list) +{ + QStandardItem *typeItem = new QStandardItem(typeName); + typeItem->setToolTip(typeItem->text()); + parent->setChild(row, 2, typeItem); + parent->setChild(row, 3, new QStandardItem(ki18ncp("Length of the list", "<%1 item>", "<%1 items>").subs(list.length()).toString())); - subRowCount++; - } - removeExtraRows(listRootItem, subRowCount); - } else { - removeExtraRows(listRootItem, 0); - parent->setChild(rowCount, 2, new QStandardItem(it.value().typeName())); - QStandardItem *item = (it.value().canConvert()) - ? new QStandardItem(it.value().value(), "") - : new QStandardItem(convertToString(it.value())); - item->setToolTip(item->text()); - parent->setChild(rowCount, 3, item); - } - ++rowCount; + int rowCount = 0; + for (const QVariant &var : list) { + showData(current, rowCount, QString::number(rowCount), var); + rowCount++; } - return rowCount; } diff --git a/engineexplorer/engineexplorer.h b/engineexplorer/engineexplorer.h index 6e6804d5..630377fc 100644 --- a/engineexplorer/engineexplorer.h +++ b/engineexplorer/engineexplorer.h @@ -54,6 +54,8 @@ private Q_SLOTS: private: void listEngines(); int showData(QStandardItem *parent, Plasma::DataEngine::Data data); + void showData(QStandardItem *parent, int row, const QString &key, const QVariant &value); + int showContainerData(QStandardItem *parent, QStandardItem *current, int row, const char *typeName, const QVariantList &list); void updateTitle(); void enableButtons(bool enable); void removeExtraRows(QStandardItem *parent, int preserve); -- GitLab From 78d8556a61913b20bd56a1149d5dd35c355dda64 Mon Sep 17 00:00:00 2001 From: ivan tkachenko Date: Sun, 16 Jan 2022 18:53:16 +0300 Subject: [PATCH 12/15] engineexplorer: Add tree recursion support for QVariantMap Now keys and values of a map will be exploded into the table, one row per pair. --- engineexplorer/engineexplorer.cpp | 17 +++++++++++++++++ engineexplorer/engineexplorer.h | 1 + 2 files changed, 18 insertions(+) diff --git a/engineexplorer/engineexplorer.cpp b/engineexplorer/engineexplorer.cpp index 21ffb3e8..07a7b14f 100644 --- a/engineexplorer/engineexplorer.cpp +++ b/engineexplorer/engineexplorer.cpp @@ -458,6 +458,9 @@ void EngineExplorer::showData(QStandardItem *parent, int row, const QString &key if (value.canConvert()) { const QVariantList list = value.toList(); rowCount = showContainerData(parent, current, row, typeName, list); + } else if (value.canConvert()) { + const QVariantMap map = value.toMap(); + rowCount = showContainerData(parent, current, row, typeName, map); } else { parent->setChild(row, 2, new QStandardItem(typeName)); // clang-format off @@ -487,6 +490,20 @@ int EngineExplorer::showContainerData(QStandardItem *parent, QStandardItem *curr return rowCount; } +int EngineExplorer::showContainerData(QStandardItem *parent, QStandardItem *current, int row, const char *typeName, const QVariantMap &map) +{ + QStandardItem *typeItem = new QStandardItem(typeName); + typeItem->setToolTip(typeItem->text()); + parent->setChild(row, 2, typeItem); + parent->setChild(row, 3, new QStandardItem(ki18ncp("Size of the map", "<%1 pair>", "<%1 pairs>").subs(map.size()).toString())); + + int rowCount = 0; + for (auto it = map.constBegin(); it != map.constEnd(); it++) { + showData(current, rowCount++, it.key(), it.value()); + } + return rowCount; +} + void EngineExplorer::updateTitle() { if (!m_engine || !m_engine->metadata().isValid()) { diff --git a/engineexplorer/engineexplorer.h b/engineexplorer/engineexplorer.h index 630377fc..742affb1 100644 --- a/engineexplorer/engineexplorer.h +++ b/engineexplorer/engineexplorer.h @@ -56,6 +56,7 @@ private: int showData(QStandardItem *parent, Plasma::DataEngine::Data data); void showData(QStandardItem *parent, int row, const QString &key, const QVariant &value); int showContainerData(QStandardItem *parent, QStandardItem *current, int row, const char *typeName, const QVariantList &list); + int showContainerData(QStandardItem *parent, QStandardItem *current, int row, const char *typeName, const QVariantMap &map); void updateTitle(); void enableButtons(bool enable); void removeExtraRows(QStandardItem *parent, int preserve); -- GitLab From 03caad7ffdce53b48b4ea97aea2ce35a499ff68a Mon Sep 17 00:00:00 2001 From: ivan tkachenko Date: Sun, 16 Jan 2022 19:19:01 +0300 Subject: [PATCH 13/15] engineexplorer: Add tree recursion support for QList This exotic type is being used by powermanagement data engine for its "Profile Holds" property, for example. --- engineexplorer/engineexplorer.cpp | 21 ++++++++++++++++++++- engineexplorer/engineexplorer.h | 1 + 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/engineexplorer/engineexplorer.cpp b/engineexplorer/engineexplorer.cpp index 07a7b14f..82c47a4a 100644 --- a/engineexplorer/engineexplorer.cpp +++ b/engineexplorer/engineexplorer.cpp @@ -455,7 +455,11 @@ void EngineExplorer::showData(QStandardItem *parent, int row, const QString &key const char *typeName = value.typeName(); int rowCount = 0; - if (value.canConvert()) { + if (value.userType() == qMetaTypeId>()) { + // this case is a bit special, and has to be handled before generic QVariantList + const QList list = value.value>(); + rowCount = showContainerData(parent, current, row, typeName, list); + } else if (value.canConvert()) { const QVariantList list = value.toList(); rowCount = showContainerData(parent, current, row, typeName, list); } else if (value.canConvert()) { @@ -475,6 +479,21 @@ void EngineExplorer::showData(QStandardItem *parent, int row, const QString &key removeExtraRows(current, rowCount); } +int EngineExplorer::showContainerData(QStandardItem *parent, QStandardItem *current, int row, const char *typeName, const QList &list) +{ + QStandardItem *typeItem = new QStandardItem(typeName); + typeItem->setToolTip(typeItem->text()); + parent->setChild(row, 2, typeItem); + parent->setChild(row, 3, new QStandardItem(ki18ncp("Length of the list", "<%1 item>", "<%1 items>").subs(list.length()).toString())); + + int rowCount = 0; + for (const QVariantMap &map : list) { + showData(current, rowCount, QString::number(rowCount), map); + rowCount++; + } + return rowCount; +} + int EngineExplorer::showContainerData(QStandardItem *parent, QStandardItem *current, int row, const char *typeName, const QVariantList &list) { QStandardItem *typeItem = new QStandardItem(typeName); diff --git a/engineexplorer/engineexplorer.h b/engineexplorer/engineexplorer.h index 742affb1..4074bf06 100644 --- a/engineexplorer/engineexplorer.h +++ b/engineexplorer/engineexplorer.h @@ -55,6 +55,7 @@ private: void listEngines(); int showData(QStandardItem *parent, Plasma::DataEngine::Data data); void showData(QStandardItem *parent, int row, const QString &key, const QVariant &value); + int showContainerData(QStandardItem *parent, QStandardItem *current, int row, const char *typeName, const QList &list); int showContainerData(QStandardItem *parent, QStandardItem *current, int row, const char *typeName, const QVariantList &list); int showContainerData(QStandardItem *parent, QStandardItem *current, int row, const char *typeName, const QVariantMap &map); void updateTitle(); -- GitLab From 562f7e61bf0af401b39cd25ce5e4a7e445c08e9d Mon Sep 17 00:00:00 2001 From: ivan tkachenko Date: Sun, 16 Jan 2022 19:32:31 +0300 Subject: [PATCH 14/15] engineexplorer: Replace magic column numbers with enum --- engineexplorer/engineexplorer.cpp | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/engineexplorer/engineexplorer.cpp b/engineexplorer/engineexplorer.cpp index 82c47a4a..79fb174e 100644 --- a/engineexplorer/engineexplorer.cpp +++ b/engineexplorer/engineexplorer.cpp @@ -29,6 +29,15 @@ Q_DECLARE_METATYPE(Plasma::DataEngine::Data) #include "serviceviewer.h" #include "titlecombobox.h" +enum { + ColumnDataSource = 0, + ColumnKey = 1, + ColumnType = 2, + ColumnValue = 3, + + ColumnCount, +}; + EngineExplorer::EngineExplorer(QWidget *parent) : QDialog(parent) , m_engine(nullptr) @@ -168,7 +177,7 @@ void EngineExplorer::showEngine(const QString &name) m_serviceRequesterButton->setEnabled(false); enableButtons(false); m_dataModel->clear(); - m_dataModel->setColumnCount(4); + m_dataModel->setColumnCount(ColumnCount); QStringList headers; headers << i18n("DataSource") << i18n("Key") << i18n("Type") << i18n("Value"); m_dataModel->setHorizontalHeaderLabels(headers); @@ -446,11 +455,11 @@ void EngineExplorer::showData(QStandardItem *parent, int row, const QString &key { // QTreeView only expands tree for children of column #zero. QStandardItem *current = new QStandardItem(); - parent->setChild(row, 0, current); + parent->setChild(row, ColumnDataSource, current); QStandardItem *keyItem = new QStandardItem(key); keyItem->setToolTip(key); - parent->setChild(row, 1, keyItem); + parent->setChild(row, ColumnKey, keyItem); const char *typeName = value.typeName(); int rowCount = 0; @@ -466,14 +475,14 @@ void EngineExplorer::showData(QStandardItem *parent, int row, const QString &key const QVariantMap map = value.toMap(); rowCount = showContainerData(parent, current, row, typeName, map); } else { - parent->setChild(row, 2, new QStandardItem(typeName)); + parent->setChild(row, ColumnType, new QStandardItem(typeName)); // clang-format off QStandardItem *item = value.canConvert() ? new QStandardItem(value.value(), "") : new QStandardItem(convertToString(value)); // clang-format on item->setToolTip(item->text()); - parent->setChild(row, 3, item); + parent->setChild(row, ColumnValue, item); // leave rowCount at value 0 } removeExtraRows(current, rowCount); @@ -483,8 +492,8 @@ int EngineExplorer::showContainerData(QStandardItem *parent, QStandardItem *curr { QStandardItem *typeItem = new QStandardItem(typeName); typeItem->setToolTip(typeItem->text()); - parent->setChild(row, 2, typeItem); - parent->setChild(row, 3, new QStandardItem(ki18ncp("Length of the list", "<%1 item>", "<%1 items>").subs(list.length()).toString())); + parent->setChild(row, ColumnType, typeItem); + parent->setChild(row, ColumnValue, new QStandardItem(ki18ncp("Length of the list", "<%1 item>", "<%1 items>").subs(list.length()).toString())); int rowCount = 0; for (const QVariantMap &map : list) { @@ -498,8 +507,8 @@ int EngineExplorer::showContainerData(QStandardItem *parent, QStandardItem *curr { QStandardItem *typeItem = new QStandardItem(typeName); typeItem->setToolTip(typeItem->text()); - parent->setChild(row, 2, typeItem); - parent->setChild(row, 3, new QStandardItem(ki18ncp("Length of the list", "<%1 item>", "<%1 items>").subs(list.length()).toString())); + parent->setChild(row, ColumnType, typeItem); + parent->setChild(row, ColumnValue, new QStandardItem(ki18ncp("Length of the list", "<%1 item>", "<%1 items>").subs(list.length()).toString())); int rowCount = 0; for (const QVariant &var : list) { @@ -513,8 +522,8 @@ int EngineExplorer::showContainerData(QStandardItem *parent, QStandardItem *curr { QStandardItem *typeItem = new QStandardItem(typeName); typeItem->setToolTip(typeItem->text()); - parent->setChild(row, 2, typeItem); - parent->setChild(row, 3, new QStandardItem(ki18ncp("Size of the map", "<%1 pair>", "<%1 pairs>").subs(map.size()).toString())); + parent->setChild(row, ColumnType, typeItem); + parent->setChild(row, ColumnValue, new QStandardItem(ki18ncp("Size of the map", "<%1 pair>", "<%1 pairs>").subs(map.size()).toString())); int rowCount = 0; for (auto it = map.constBegin(); it != map.constEnd(); it++) { -- GitLab From bb5bdc691d16c03849ece2cf6cb87c6cd8430cbb Mon Sep 17 00:00:00 2001 From: ivan tkachenko Date: Sun, 16 Jan 2022 20:03:24 +0300 Subject: [PATCH 15/15] engineexplorer: Unify first two columns (DataSource + Key) They looked weird and broken with those empty cells on the left. In every possible scenario only one of them is filled at a time. Also, without moving keys to the left indented column, hierarchical data looks especially plain and wrong. Width of the first column is also manually increased to be twice as wide as the stock value of 100, to accommodate long keys and deep nesting. --- engineexplorer/engineexplorer.cpp | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/engineexplorer/engineexplorer.cpp b/engineexplorer/engineexplorer.cpp index 79fb174e..c8c3b728 100644 --- a/engineexplorer/engineexplorer.cpp +++ b/engineexplorer/engineexplorer.cpp @@ -30,10 +30,9 @@ Q_DECLARE_METATYPE(Plasma::DataEngine::Data) #include "titlecombobox.h" enum { - ColumnDataSource = 0, - ColumnKey = 1, - ColumnType = 2, - ColumnValue = 3, + ColumnDataSourceAndKey = 0, + ColumnType = 1, + ColumnValue = 2, ColumnCount, }; @@ -178,9 +177,9 @@ void EngineExplorer::showEngine(const QString &name) enableButtons(false); m_dataModel->clear(); m_dataModel->setColumnCount(ColumnCount); - QStringList headers; - headers << i18n("DataSource") << i18n("Key") << i18n("Type") << i18n("Value"); + QStringList headers{i18n("DataSource/Key"), i18n("Type"), i18n("Value")}; m_dataModel->setHorizontalHeaderLabels(headers); + m_data->setColumnWidth(ColumnDataSourceAndKey, 200); m_engine = nullptr; m_sourceCount = 0; @@ -453,13 +452,11 @@ int EngineExplorer::showData(QStandardItem *parent, Plasma::DataEngine::Data dat void EngineExplorer::showData(QStandardItem *parent, int row, const QString &key, const QVariant &value) { + static_assert(ColumnDataSourceAndKey == 0); // QTreeView only expands tree for children of column #zero. - QStandardItem *current = new QStandardItem(); - parent->setChild(row, ColumnDataSource, current); - - QStandardItem *keyItem = new QStandardItem(key); - keyItem->setToolTip(key); - parent->setChild(row, ColumnKey, keyItem); + QStandardItem *current = new QStandardItem(key); + current->setToolTip(key); + parent->setChild(row, ColumnDataSourceAndKey, current); const char *typeName = value.typeName(); int rowCount = 0; -- GitLab