File indexing completed on 2022-09-27 12:31:10

0001 /*
0002     SPDX-FileCopyrightText: 2003-2008 Cies Breijs <cies AT kde DOT nl>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "inspector.h"
0008 
0009 #include "interpreter/translator.h"  // for getting the translated ArgumentSeparator
0010 
0011 #include <QBoxLayout>
0012 #include <QDebug>
0013 #include <QFontDatabase>
0014 #include <QHeaderView>
0015 #include <QTabWidget>
0016 #include <QTableWidget>
0017 #include <QTreeWidget>
0018 
0019 #include <KLocalizedString>
0020 
0021 
0022 Inspector::Inspector(QWidget *parent)
0023     : QFrame(parent)
0024 {
0025     mainLayout = new QHBoxLayout(this);
0026     mainLayout->setSpacing(0);
0027     mainLayout->setContentsMargins(0, 0, 0, 0);
0028     tabWidget  = new QTabWidget(this);
0029 
0030     variableTab    = new QWidget();
0031     variableLayout = new QHBoxLayout(variableTab);
0032     variableTable  = new QTableWidget(variableTab);
0033     variableTable->setAlternatingRowColors(true);
0034     variableLayout->addWidget(variableTable);
0035     tabWidget->addTab(variableTab, i18n("Variables"));
0036 
0037     functionTab    = new QWidget();
0038     functionLayout = new QHBoxLayout(functionTab);
0039     functionTable  = new QTableWidget(functionTab);
0040     functionTable->setAlternatingRowColors(true);
0041     functionLayout->addWidget(functionTable);
0042     tabWidget->addTab(functionTab, i18n("Functions"));
0043 
0044     treeTab    = new QWidget();
0045     treeLayout = new QHBoxLayout(treeTab);
0046     treeView   = new QTreeWidget(treeTab);
0047     treeView->header()->setVisible(false);
0048     treeLayout->addWidget(treeView);
0049     tabWidget->addTab(treeTab, i18n("Tree"));
0050 
0051     mainLayout->addWidget(tabWidget);
0052 
0053     // our syntax highlighter (this does not do any markings)
0054     highlighter = new Highlighter();
0055 
0056 //  // the maps used when marking table/tree items later
0057 //  variableMap = new QHash<QString, QTableWidgetItem*>();
0058 //  functionMap = new QHash<QString, QTableWidgetItem*>();
0059 //  treeMap = new QHash<TreeNode*, QTableWidgetItem*>();
0060 
0061     currentlyMarkedTreeItem = nullptr;
0062 
0063     disable();
0064 
0065     clear();
0066 }
0067 
0068 Inspector::~Inspector()
0069 {
0070     delete highlighter;
0071 }
0072 
0073 
0074 void Inspector::disable()
0075 {
0076     variableTable->setEnabled(false);
0077     functionTable->setEnabled(false);
0078     treeView->setEnabled(false);
0079     // enabling happened when the inspector gets filled with data
0080 }
0081 
0082 void Inspector::clear()
0083 {
0084     clearAllMarks();
0085 
0086     // Question: is the code duplication below enough
0087     // for a subclass-of-QTableWidget based approach?
0088 
0089     variableMap.clear();
0090     variableTableEmpty = true;
0091     variableTable->clear();
0092     QStringList headers;
0093     headers << i18n("name") << i18n("value") << i18n("type");
0094     variableTable->setColumnCount(3);
0095     variableTable->setHorizontalHeaderLabels(headers);
0096     variableTable->setSelectionMode(QAbstractItemView::SingleSelection);
0097     variableTable->setSelectionBehavior(QAbstractItemView::SelectRows);
0098     variableTable->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft);
0099     variableTable->verticalHeader()->setVisible(false);
0100     variableTable->setShowGrid(false);
0101     variableTable->setRowCount(1);
0102     QTableWidgetItem* emptyItem;
0103     emptyItem = new QTableWidgetItem(i18n("No variables"));
0104     variableTable->setItem(0, 0, emptyItem);
0105     variableTable->resizeColumnsToContents();
0106 
0107     functionMap.clear();
0108     functionTableEmpty = true;
0109     functionTable->clear();
0110     headers.clear();
0111     headers << i18n("name") << i18n("parameters");
0112     functionTable->setColumnCount(2);
0113     functionTable->setHorizontalHeaderLabels(headers);
0114     functionTable->setSelectionMode(QAbstractItemView::SingleSelection);
0115     functionTable->setSelectionBehavior(QAbstractItemView::SelectRows);
0116     functionTable->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft);
0117     functionTable->verticalHeader()->setVisible(false);
0118     functionTable->setShowGrid(false);
0119     functionTable->setRowCount(1);
0120     emptyItem = new QTableWidgetItem(i18n("No learned functions"));
0121     functionTable->setItem(0, 0, emptyItem);
0122     functionTable->resizeColumnsToContents();
0123 
0124     // Treeview gets cleared in updateTree()
0125     disable();
0126 }
0127 
0128 
0129 void Inspector::updateVariable(const QString& name, const Value& value)
0130 {
0131     // Check if the variable has already been added to the table
0132     int row = findVariable(name);
0133     if (row == -1) {
0134         // We are dealing with a new variable
0135         if (variableTableEmpty) {  // Check whether we have to add a new row
0136             variableTableEmpty = false;
0137         } else {
0138             variableTable->insertRow(0);
0139         }
0140         row = 0;
0141     }
0142 
0143     QTableWidgetItem* nameItem;
0144     nameItem = new QTableWidgetItem(name);
0145     nameItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
0146     QTextCharFormat* format = highlighter->formatForStatement(name);
0147     nameItem->setFont(format->font());
0148     nameItem->setForeground(format->foreground());
0149     variableTable->setItem(row, 0, nameItem);
0150     variableMap[name] = nameItem;
0151 
0152     QTableWidgetItem* valueItem;
0153     valueItem = new QTableWidgetItem(value.string());
0154     valueItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
0155 // TODO variable coloring when tokens are available in the inspector!
0156 //  format = highlighter->formatForStatement(value.string());
0157 //  valueItem->setFont(format->font());
0158 //  valueItem->setForeground(format->foreground());
0159 
0160     QTableWidgetItem* typeItem;
0161     switch (value.type()) {
0162         case Value::Empty: {
0163                         typeItem  = new QTableWidgetItem(i18nc("undefined type of a variable","empty"));
0164             QFont font = typeItem->font();
0165             font.setItalic(true);
0166             typeItem->setFont(font);
0167             }
0168             break;
0169         case Value::Bool:
0170             typeItem  = new QTableWidgetItem(i18n("boolean"));
0171             break;
0172         case Value::Number:
0173             typeItem  = new QTableWidgetItem(i18n("number"));
0174             break;
0175         case Value::String:
0176             typeItem  = new QTableWidgetItem(i18n("string"));
0177             break;
0178         default:
0179             // should never happen
0180             typeItem  = new QTableWidgetItem(QStringLiteral("ERROR! please report to KTurtle developers"));
0181             break;
0182     }
0183     typeItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
0184     variableTable->setItem(row, 1, valueItem);
0185     variableTable->setItem(row, 2, typeItem);
0186 
0187     variableTable->sortItems(0);
0188     variableTable->resizeColumnsToContents();
0189     variableTable->setEnabled(true);
0190 }
0191 
0192 void Inspector::updateFunction(const QString& name, const QStringList& parameters)
0193 {
0194     // When there is already a the 'Nothing to show' line re-use that one and don't add another
0195     if (functionTableEmpty) {
0196         functionTableEmpty = false;
0197     } else {
0198         functionTable->insertRow(0);
0199     }
0200 
0201     QTableWidgetItem* nameItem = new QTableWidgetItem(name);
0202     nameItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
0203     functionTable->setItem(0, 0, nameItem);
0204     functionMap[name] = nameItem;
0205 
0206     QTableWidgetItem* paramItem;
0207     if (parameters.empty()) {
0208         paramItem = new QTableWidgetItem(i18n("None"));
0209         QFont font = paramItem->font();
0210         font.setItalic(true);
0211         paramItem->setFont(font);
0212     } else {
0213         QString paramList = parameters.join(Translator::instance()->default2localized(QStringLiteral(",")));
0214         paramItem = new QTableWidgetItem(paramList);
0215     }
0216     
0217     paramItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
0218     functionTable->setItem(0, 1, paramItem);
0219     functionTable->sortItems(0);
0220     functionTable->resizeColumnsToContents();
0221     functionTable->setEnabled(true);
0222 }
0223 
0224 void Inspector::updateTree(TreeNode* rootNode)
0225 {
0226     treeMap.clear();
0227     treeView->clear();
0228     QTreeWidgetItem* rootItem = walkTree(rootNode);
0229     const auto rootItemChildren = rootItem->takeChildren();
0230     for (QTreeWidgetItem* item : rootItemChildren) {
0231         treeView->addTopLevelItem(item);
0232     }
0233     delete rootItem;
0234     treeView->expandAll();
0235     treeView->setEnabled(true);
0236 }
0237 
0238 QTreeWidgetItem* Inspector::walkTree(TreeNode* node)
0239 {
0240     QTreeWidgetItem* result = new QTreeWidgetItem();
0241     result->setText(0, node->token()->look());
0242     QTextCharFormat* format = highlighter->tokenToFormat(node->token());
0243     if (format) {
0244         result->setForeground(0, format->foreground());
0245         QFont font(QFontDatabase::systemFont(QFontDatabase::FixedFont));
0246         font.setBold(format->font().bold());
0247         result->setFont(0, font);
0248     }
0249     treeMap[node] = result;
0250     if (node->hasChildren()) {
0251         for (uint i = 0; i < node->childCount(); i++) {
0252             result->addChild(walkTree(node->child(i)));
0253         }
0254     }
0255     return result;
0256 }
0257 
0258 int Inspector::findVariable(const QString& name)
0259 {
0260     QTableWidgetItem* item = variableMap[name];
0261     if (!item) return -1;
0262     return item->row();
0263 
0264 // old implementation before we had a variableMap
0265 
0266 //  // This function will search for a specified variable and return the row number of this variable.
0267 //  QList<QTableWidgetItem*> matches = variableTable->findItems(name, Qt::MatchExactly);
0268 //  QList<QTableWidgetItem*>::iterator i;
0269 //  for (i = matches.begin(); i != matches.end(); ++i) {
0270 //      if ((*i)->column() == 0) // only check the first column
0271 //          return (*i)->row();
0272 //  }
0273 //  return -1;
0274 }
0275 
0276 void Inspector::markVariable(const QString& name)
0277 {
0278     Q_UNUSED(name);
0279     //qDebug() << variableMap[name]->row();
0280 }
0281 
0282 void Inspector::markFunction(const QString& name)
0283 {
0284     Q_UNUSED(name);
0285     //qDebug() << functionMap[name]->row();
0286 }
0287 
0288 void Inspector::markTreeNode(TreeNode* node)
0289 {
0290 //  //qDebug() << treeMap[node]->text(0);
0291     clearTreeMark();
0292     currentlyMarkedTreeItem = treeMap[node];
0293     previousTreeBackground = currentlyMarkedTreeItem->background(0);
0294     currentlyMarkedTreeItem->setBackground(0, QBrush(WORD_HIGHLIGHT_COLOR));
0295 }
0296 
0297 void Inspector::clearTreeMark()
0298 {
0299     if (!currentlyMarkedTreeItem) return;
0300     currentlyMarkedTreeItem->setBackground(0, previousTreeBackground);
0301     currentlyMarkedTreeItem = nullptr;
0302 }
0303 
0304 void Inspector::clearAllMarks()
0305 {
0306     clearTreeMark();
0307 }