File indexing completed on 2024-05-19 05:42:13
0001 // ct_lvtmdl_errorsmodel.h -*-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 0020 #include <ct_lvtmdl_errorsmodel.h> 0021 0022 #include <QDebug> 0023 #include <QFontMetrics> 0024 #include <QList> 0025 #include <QString> 0026 0027 using namespace Codethink::lvtmdl; 0028 0029 struct DataInfo { 0030 enum Type { 0031 e_ErrorKind, 0032 e_QualifiedName, 0033 e_FileName, 0034 e_ErrorString, 0035 }; 0036 0037 int errorKind; 0038 QString qualifiedName; 0039 QString filename; 0040 QString errorString; 0041 }; 0042 0043 struct ErrorsModel::Private { 0044 QList<DataInfo> messages; 0045 }; 0046 0047 ErrorsModel::ErrorsModel(): d(std::make_unique<ErrorsModel::Private>()) 0048 { 0049 } 0050 0051 ErrorsModel::~ErrorsModel() = default; 0052 0053 void ErrorsModel::reset() 0054 { 0055 beginResetModel(); 0056 d->messages.clear(); 0057 0058 // TODO: Retrieve errors from lvtldr 0059 // if (d->session) { 0060 // Transaction transaction(*d->session); 0061 // const auto errorMessages = d->session->find<lvtcdb::ErrorMessages>(); 0062 // for (auto& errorMessage : errorMessages.resultList()) { 0063 // d->messages.append(DataInfo{ 0064 // errorMessage->errorKind(), 0065 // QString::fromStdString(errorMessage->fullyQualifiedName()), 0066 // QString::fromStdString(errorMessage->fileName()), 0067 // QString::fromStdString(errorMessage->errorMessage()), 0068 // }); 0069 // } 0070 // } 0071 0072 endResetModel(); 0073 } 0074 0075 int ErrorsModel::rowCount(const QModelIndex& idx) const 0076 { 0077 Q_UNUSED(idx); 0078 return d->messages.count(); 0079 } 0080 0081 int ErrorsModel::columnCount(const QModelIndex& idx) const 0082 { 0083 Q_UNUSED(idx); 0084 return 4; 0085 } 0086 0087 QVariant ErrorsModel::headerData(int section, Qt::Orientation orientation, int role) const 0088 { 0089 if (orientation == Qt::Orientation::Vertical) { 0090 return {}; 0091 } 0092 0093 if (role != Qt::DisplayRole) { 0094 return {}; 0095 } 0096 0097 switch (section) { 0098 case DataInfo::Type::e_ErrorKind: 0099 return tr("Type"); 0100 case DataInfo::Type::e_QualifiedName: 0101 return tr("Qualified Name"); 0102 case DataInfo::Type::e_FileName: 0103 return tr("File"); 0104 case DataInfo::Type::e_ErrorString: 0105 return tr("Error Message"); 0106 } 0107 0108 return {}; 0109 } 0110 0111 QVariant ErrorsModel::data(const QModelIndex& idx, int role) const 0112 { 0113 if (role != Qt::DisplayRole && role != Qt::ToolTipRole && role != Qt::SizeHintRole) { 0114 return {}; 0115 } 0116 0117 const auto thisValue = d->messages.at(idx.row()); 0118 if (role == Qt::DisplayRole) { 0119 switch (idx.column()) { 0120 case DataInfo::Type::e_ErrorKind: 0121 return thisValue.errorKind == 0 ? tr("Compiler Messages") : tr("Parse Messages"); 0122 0123 case DataInfo::Type::e_ErrorString: 0124 return thisValue.errorString; 0125 case DataInfo::Type::e_FileName: 0126 return thisValue.filename; 0127 case DataInfo::Type::e_QualifiedName: 0128 return thisValue.qualifiedName; 0129 } 0130 } else if (role == Qt::ToolTipRole) { 0131 return thisValue.errorString; 0132 } 0133 0134 return {}; 0135 } 0136 0137 struct ErrorModelFilter::Private { 0138 bool filterCompilerMessages = false; 0139 bool filterParseMessages = false; 0140 bool invertStringFilter = false; 0141 QAbstractItemModel *ignoreCategoriesModel = nullptr; 0142 QString filterString; 0143 }; 0144 0145 ErrorModelFilter::ErrorModelFilter(): d(std::make_unique<ErrorModelFilter::Private>()) 0146 { 0147 } 0148 0149 ErrorModelFilter::~ErrorModelFilter() = default; 0150 0151 bool ErrorModelFilter::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const 0152 { 0153 Q_UNUSED(source_parent); 0154 0155 auto *currModel = qobject_cast<ErrorsModel *>(sourceModel()); 0156 0157 const QModelIndex idx = currModel->index(source_row, DataInfo::Type::e_ErrorKind); 0158 const QVariant data = currModel->data(idx, Qt::DisplayRole); 0159 const QString type = data.toString(); 0160 0161 if (d->filterCompilerMessages && type == tr("Compiler Messages")) { 0162 return false; 0163 } 0164 if (d->filterParseMessages && type == tr("Parse Messages")) { 0165 return false; 0166 } 0167 0168 if (d->filterString.size()) { 0169 const QModelIndex messageIdx = currModel->index(source_row, DataInfo::Type::e_ErrorString); 0170 const QString currMessage = currModel->data(messageIdx, Qt::DisplayRole).toString(); 0171 const bool lineContainsFilter = currMessage.contains(d->filterString); 0172 0173 if (d->invertStringFilter) { 0174 return !lineContainsFilter; 0175 } 0176 return lineContainsFilter; 0177 } 0178 0179 return true; 0180 } 0181 0182 bool ErrorModelFilter::lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const 0183 { 0184 Q_UNUSED(source_left); 0185 Q_UNUSED(source_right); 0186 return true; 0187 } 0188 0189 void ErrorModelFilter::setFilterCompilerMessages(bool filter) 0190 { 0191 if (d->filterCompilerMessages == filter) { 0192 return; 0193 } 0194 d->filterCompilerMessages = filter; 0195 invalidateFilter(); 0196 } 0197 0198 void ErrorModelFilter::setFilterParseMessages(bool filter) 0199 { 0200 if (d->filterParseMessages == filter) { 0201 return; 0202 } 0203 d->filterParseMessages = filter; 0204 invalidateFilter(); 0205 } 0206 0207 void ErrorModelFilter::setIgnoreCategoriesModel(QAbstractItemModel *model) 0208 { 0209 if (d->ignoreCategoriesModel) { 0210 disconnect(d->ignoreCategoriesModel, &QAbstractItemModel::rowsInserted, this, nullptr); 0211 disconnect(d->ignoreCategoriesModel, &QAbstractItemModel::rowsRemoved, this, nullptr); 0212 } 0213 0214 d->ignoreCategoriesModel = model; 0215 connect(model, &QAbstractItemModel::rowsInserted, this, [this] { 0216 invalidateFilter(); 0217 }); 0218 0219 connect(model, &QAbstractItemModel::rowsRemoved, this, [this] { 0220 invalidateFilter(); 0221 }); 0222 } 0223 0224 void ErrorModelFilter::setFilterString(const QString& str) 0225 { 0226 if (d->filterString == str) { 0227 return; 0228 } 0229 d->filterString = str; 0230 invalidateFilter(); 0231 } 0232 0233 void ErrorModelFilter::setInvertMessageFilter(bool value) 0234 { 0235 if (d->invertStringFilter == value) { 0236 return; 0237 } 0238 d->invertStringFilter = value; 0239 invalidateFilter(); 0240 }