File indexing completed on 2024-04-21 03:45:28

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