File indexing completed on 2024-05-19 05:42:26
0001 // ct_lvtqtw_errorview.cpp -*-C++-*- 0002 0003 /* 0004 // Copyright 2023 Codethink Ltd <codethink@codethink.co.uk> 0005 // SPDX-License-Identifier: Apache-2.0 0006 // 0007 // Licensed under the Apache License, Version 2.0 (the "License"); 0008 // you may not use this file except in compliance with the License. 0009 // You may obtain a copy of the License at 0010 // 0011 // http://www.apache.org/licenses/LICENSE-2.0 0012 // 0013 // Unless required by applicable law or agreed to in writing, software 0014 // distributed under the License is distributed on an "AS IS" BASIS, 0015 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 0016 // See the License for the specific language governing permissions and 0017 // limitations under the License. 0018 */ 0019 #include <ct_lvtqtw_errorview.h> 0020 0021 #include <ui_ct_lvtqtw_errorview.h> 0022 0023 #include <ct_lvtmdl_errorsmodel.h> 0024 #include <ct_lvtmdl_simpletextmodel.h> 0025 0026 #include <ct_lvtqtd_removedelegate.h> 0027 0028 #include <QAction> 0029 #include <QApplication> 0030 #include <QClipboard> 0031 #include <QHeaderView> 0032 #include <QItemSelectionModel> 0033 #include <QMenu> 0034 #include <QSettings> 0035 0036 namespace Codethink::lvtqtw { 0037 0038 struct ErrorView::Private { 0039 Codethink::lvtmdl::ErrorModelFilter filterModel; 0040 Codethink::lvtmdl::SimpleTextModel ignoreGroupModel; 0041 0042 // We don't own the debug model, it should be created before the mainwindow 0043 // to not lose debug information. We only hold the pointer to it. it should 0044 // always be valid, after being set, untill the destruction of this widget. 0045 Codethink::lvtmdl::ErrorsModel *model = nullptr; 0046 0047 // TODO: Maybe move this to a QComboBox class 0048 QString currentEditedTextOnCategoryCombobox; 0049 }; 0050 0051 ErrorView::ErrorView(QWidget *parent): 0052 QWidget(parent), ui(std::make_unique<Ui::ErrorView>()), d(std::make_unique<ErrorView::Private>()) 0053 { 0054 ui->setupUi(this); 0055 0056 ui->tableView->setModel(&d->filterModel); 0057 ui->tableView->horizontalHeader()->setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu); 0058 0059 ui->comboBox->setModel(&d->ignoreGroupModel); 0060 0061 auto *delegate = new lvtqtd::RemoveDelegate(); 0062 ui->comboBox->view()->setMouseTracking(true); 0063 ui->comboBox->view()->setItemDelegate(delegate); 0064 ui->comboBox->setInsertPolicy(QComboBox::InsertAtBottom); 0065 ui->comboBox->lineEdit()->setPlaceholderText(tr("Ignored Categories")); 0066 0067 d->ignoreGroupModel.setStorageGroup("DebugIgnoreGroups"); 0068 0069 d->filterModel.setFilterCompilerMessages(ui->btnCompilerMessages->isChecked()); 0070 d->filterModel.setFilterParseMessages(ui->btnParseMessages->isChecked()); 0071 d->filterModel.setIgnoreCategoriesModel(&d->ignoreGroupModel); 0072 0073 connect(ui->btnCompilerMessages, 0074 &QToolButton::toggled, 0075 &d->filterModel, 0076 &Codethink::lvtmdl::ErrorModelFilter::setFilterCompilerMessages); 0077 connect(ui->btnParseMessages, 0078 &QToolButton::toggled, 0079 &d->filterModel, 0080 &Codethink::lvtmdl::ErrorModelFilter::setFilterParseMessages); 0081 connect(ui->tableView->horizontalHeader(), 0082 &QWidget::customContextMenuRequested, 0083 this, 0084 &ErrorView::createColumnVisibilityMenu); 0085 connect(ui->filterLine, &QLineEdit::textChanged, &d->filterModel, &lvtmdl::ErrorModelFilter::setFilterString); 0086 connect(ui->invertFilterBtn, &QCheckBox::stateChanged, this, [this] { 0087 d->filterModel.setInvertMessageFilter(ui->invertFilterBtn->isChecked()); 0088 }); 0089 0090 // The QComboBox loses the text as soon as there's a editingFinished, so we need to store the string 0091 // being edited, to use it later on. 0092 connect(ui->comboBox->lineEdit(), &QLineEdit::textEdited, this, [this] { 0093 d->currentEditedTextOnCategoryCombobox = ui->comboBox->lineEdit()->text(); 0094 }); 0095 0096 connect(ui->comboBox->lineEdit(), &QLineEdit::editingFinished, this, [this] { 0097 if (!d->currentEditedTextOnCategoryCombobox.isEmpty()) { 0098 d->ignoreGroupModel.addString(d->currentEditedTextOnCategoryCombobox); 0099 } 0100 d->currentEditedTextOnCategoryCombobox = QString(); 0101 }); 0102 0103 ui->tableView->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); 0104 ui->btnCompilerMessages->setIcon(QIcon(":/icons/critical")); 0105 ui->btnParseMessages->setIcon(QIcon(":/icons/info")); 0106 0107 auto *copyAction = new QAction(); 0108 copyAction->setShortcut(QKeySequence::Copy); 0109 copyAction->setShortcutContext(Qt::ShortcutContext::WidgetWithChildrenShortcut); 0110 addAction(copyAction); 0111 connect(copyAction, &QAction::triggered, this, [this] { 0112 auto rows = ui->tableView->selectionModel()->selectedRows(); 0113 0114 QString result; 0115 for (const QModelIndex& idx : rows) { 0116 result += idx.data(Qt::ToolTipRole).toString(); 0117 } 0118 0119 qApp->clipboard()->setText(result); 0120 }); 0121 } 0122 0123 ErrorView::~ErrorView() 0124 { 0125 saveColumnVisibilityState(); 0126 } 0127 0128 void ErrorView::setModel(lvtmdl::ErrorsModel *model) 0129 { 0130 if (d->model) { 0131 disconnect(d->model, &QAbstractItemModel::rowsRemoved, ui->tableView, nullptr); 0132 disconnect(d->model, &QAbstractItemModel::rowsInserted, ui->tableView, nullptr); 0133 } 0134 0135 d->filterModel.setSourceModel(model); 0136 d->model = model; 0137 0138 connect(d->model, &QAbstractItemModel::rowsRemoved, ui->tableView, &QTableView::scrollToBottom); 0139 connect(d->model, &QAbstractItemModel::rowsInserted, ui->tableView, &QTableView::scrollToBottom); 0140 0141 loadColumnVisibilityState(); 0142 } 0143 0144 void ErrorView::saveColumnVisibilityState() 0145 { 0146 QSettings settings; 0147 settings.beginGroup("DebugTable"); 0148 0149 const int columnCount = ui->tableView->model()->columnCount(); 0150 for (int i = 0; i < columnCount; i++) { 0151 settings.setValue(QStringLiteral("column_%1_visible").arg(i), !ui->tableView->isColumnHidden(i)); 0152 } 0153 } 0154 0155 void ErrorView::loadColumnVisibilityState() 0156 { 0157 QSettings settings; 0158 settings.beginGroup("DebugTable"); 0159 0160 const int columnCount = ui->tableView->model()->columnCount(); 0161 for (int i = 0; i < columnCount; i++) { 0162 const bool visible = settings.value(QStringLiteral("column_%1_visible").arg(i), true).toBool(); 0163 ui->tableView->setColumnHidden(i, !visible); 0164 } 0165 } 0166 0167 void ErrorView::createColumnVisibilityMenu(const QPoint& pos) 0168 { 0169 QMenu menu; 0170 const int columnCount = ui->tableView->model()->columnCount(); 0171 for (int i = 0; i < columnCount; i++) { 0172 const QString textAt = ui->tableView->model()->headerData(i, Qt::Orientation::Horizontal).toString(); 0173 QAction *toggleVisibility = menu.addAction(textAt); 0174 toggleVisibility->setCheckable(true); 0175 toggleVisibility->setChecked(!ui->tableView->isColumnHidden(i)); 0176 connect(toggleVisibility, &QAction::toggled, this, [this, i] { 0177 ui->tableView->setColumnHidden(i, !ui->tableView->isColumnHidden(i)); 0178 }); 0179 } 0180 menu.exec(ui->tableView->horizontalHeader()->mapToGlobal(pos)); 0181 } 0182 0183 } // namespace Codethink::lvtqtw