File indexing completed on 2024-05-12 04:39:21
0001 /* 0002 SPDX-FileCopyrightText: 2018 Friedrich W. H. Kossebau <kossebau@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "checklistmodel.h" 0008 0009 // plugin 0010 #include <checkset.h> 0011 #include <debug.h> 0012 // KF 0013 #include <KLocalizedString> 0014 0015 0016 namespace { 0017 0018 Qt::CheckState checkState(ClangTidy::CheckGroup::EnabledState enabledState) 0019 { 0020 return 0021 (enabledState == ClangTidy::CheckGroup::EnabledInherited) ? Qt::PartiallyChecked : 0022 (enabledState == ClangTidy::CheckGroup::Disabled) ? Qt::Unchecked : 0023 /* else */ Qt::Checked; 0024 } 0025 0026 ClangTidy::CheckGroup::EnabledState enabledState(int checkState) 0027 { 0028 return 0029 (checkState == Qt::PartiallyChecked) ? ClangTidy::CheckGroup::EnabledInherited : 0030 (checkState == Qt::Unchecked) ? ClangTidy::CheckGroup::Disabled : 0031 /* else */ ClangTidy::CheckGroup::Enabled; 0032 } 0033 0034 } 0035 0036 namespace ClangTidy 0037 { 0038 0039 CheckListModel::CheckListModel(QObject* parent) 0040 : QAbstractItemModel(parent) 0041 { 0042 } 0043 0044 CheckListModel::~CheckListModel() = default; 0045 0046 QVariant CheckListModel::data(const QModelIndex& index, int role) const 0047 { 0048 if (!index.isValid() || 0049 (index.column() < NameColumnId) || (index.column() > CountColumnId)) { 0050 return QVariant(); 0051 } 0052 0053 auto* checkGroup = static_cast<const CheckGroup*>(index.internalPointer()); 0054 0055 // root? 0056 if (!checkGroup) { 0057 if (index.row() != 0) { 0058 return QVariant(); 0059 } 0060 if (role == HasExplicitEnabledStateRole) { 0061 return m_rootCheckGroup->hasSubGroupWithExplicitEnabledState(); 0062 } else { 0063 if (index.column() == NameColumnId) { 0064 if (role == Qt::DisplayRole) { 0065 return i18nc("@item", "All checks"); 0066 } else 0067 if (role == Qt::CheckStateRole) { 0068 return checkState(m_rootCheckGroup->groupEnabledState()); 0069 } else 0070 if (role == EffectiveEnabledStateRole) { 0071 return m_rootCheckGroup->effectiveGroupEnabledState(); 0072 } 0073 } else { 0074 if (role == Qt::DisplayRole) { 0075 const int enabledChecksCount = m_rootCheckGroup->enabledChecksCount(); 0076 if (enabledChecksCount > 0) { 0077 return enabledChecksCount; 0078 } 0079 } else 0080 if (role == Qt::TextAlignmentRole) { 0081 return static_cast<int>(Qt::AlignRight | Qt::AlignVCenter); 0082 } 0083 } 0084 } 0085 } else { 0086 const int childIndex = index.row(); 0087 if (childIndex < 0 || childCount(checkGroup) <= childIndex) { 0088 return QVariant(); 0089 } 0090 const int subGroupsCount = checkGroup->subGroups().count(); 0091 if (childIndex < subGroupsCount) { 0092 const int subGroupIndex = childIndex; 0093 if (role == HasExplicitEnabledStateRole) { 0094 auto* subGroup = checkGroup->subGroups().at(subGroupIndex); 0095 return subGroup->hasSubGroupWithExplicitEnabledState(); 0096 } else { 0097 if (index.column() == NameColumnId) { 0098 if (role == Qt::DisplayRole) { 0099 auto* subGroup = checkGroup->subGroups().at(subGroupIndex); 0100 return subGroup->wildCardText(); 0101 } else 0102 if (role == Qt::CheckStateRole) { 0103 auto* subGroup = checkGroup->subGroups().at(subGroupIndex); 0104 return checkState(subGroup->groupEnabledState()); 0105 } else 0106 if (role == EffectiveEnabledStateRole) { 0107 auto* subGroup = checkGroup->subGroups().at(subGroupIndex); 0108 return subGroup->effectiveGroupEnabledState(); 0109 } 0110 } else { 0111 if (role == Qt::DisplayRole) { 0112 auto* subGroup = checkGroup->subGroups().at(subGroupIndex); 0113 const int enabledChecksCount = subGroup->enabledChecksCount(); 0114 if (enabledChecksCount > 0) { 0115 return enabledChecksCount; 0116 } 0117 } else 0118 if (role == Qt::TextAlignmentRole) { 0119 return static_cast<int>(Qt::AlignRight | Qt::AlignVCenter); 0120 } 0121 } 0122 } 0123 } else { 0124 if (index.column() == NameColumnId) { 0125 const int checkIndex = childIndex - subGroupsCount; 0126 if (role == Qt::DisplayRole) { 0127 return checkGroup->checkNames().at(checkIndex); 0128 } else 0129 if (role == Qt::CheckStateRole) { 0130 return checkState(checkGroup->checkEnabledState(checkIndex)); 0131 } else 0132 if (role == EffectiveEnabledStateRole) { 0133 return checkGroup->effectiveCheckEnabledState(checkIndex); 0134 } 0135 } 0136 } 0137 } 0138 0139 return QVariant(); 0140 } 0141 0142 bool CheckListModel::setData(const QModelIndex& index, const QVariant& value, int role) 0143 { 0144 if (!index.isValid() || 0145 (role != Qt::CheckStateRole)) { 0146 return false; 0147 } 0148 0149 const auto enabledState = ::enabledState(value.toInt()); 0150 auto* checkGroup = static_cast<CheckGroup*>(index.internalPointer()); 0151 0152 // root? 0153 if (!checkGroup) { 0154 if (index.row() != 0) { 0155 return false; 0156 } 0157 0158 m_rootCheckGroup->setGroupEnabledState(enabledState); 0159 0160 m_isDefault = false; 0161 emitSubGroupDataChanged(index); 0162 emit enabledChecksChanged(); 0163 return true; 0164 } else { 0165 const int childIndex = index.row(); 0166 if (childIndex < 0 || childCount(checkGroup) <= childIndex) { 0167 return false; 0168 } 0169 0170 CheckGroup* changedSubGroup = nullptr; 0171 const int subGroupsCount = checkGroup->subGroups().count(); 0172 if (childIndex < subGroupsCount) { 0173 const int subGroupIndex = childIndex; 0174 auto* subGroup = checkGroup->subGroups().at(subGroupIndex); 0175 const auto oldEffectiveGroupEnabledState = subGroup->effectiveGroupEnabledState(); 0176 subGroup->setGroupEnabledState(enabledState); 0177 if (oldEffectiveGroupEnabledState != subGroup->effectiveGroupEnabledState()) { 0178 changedSubGroup = subGroup; 0179 } 0180 } else { 0181 const int checkIndex = childIndex - subGroupsCount; 0182 checkGroup->setCheckEnabledState(checkIndex, enabledState); 0183 } 0184 0185 m_isDefault = false; 0186 if (changedSubGroup) { 0187 emitSubGroupDataChanged(index); 0188 } else { 0189 emit dataChanged(index, index, {Qt::CheckStateRole}); 0190 } 0191 emit enabledChecksChanged(); 0192 return true; 0193 } 0194 0195 return false; 0196 } 0197 0198 int CheckListModel::columnCount(const QModelIndex& parent) const 0199 { 0200 Q_UNUSED(parent) 0201 return 2; 0202 } 0203 0204 int CheckListModel::rowCount(const QModelIndex& parent) const 0205 { 0206 if (!parent.isValid()) { 0207 return m_rootCheckGroup ? 1 : 0; 0208 } 0209 0210 auto* parentCheckGroup = static_cast<const CheckGroup*>(parent.internalPointer()); 0211 0212 if (!parentCheckGroup) { 0213 return childCount(m_rootCheckGroup.data()); 0214 } 0215 0216 // is subgroup? 0217 const int subGroupIndex = parent.row(); 0218 const auto& subGroups = parentCheckGroup->subGroups(); 0219 if (0 <= subGroupIndex && subGroupIndex < subGroups.count()) { 0220 return childCount(subGroups.at(subGroupIndex)); 0221 } 0222 0223 return 0; 0224 } 0225 0226 QModelIndex CheckListModel::parent(const QModelIndex& child) const 0227 { 0228 if (!child.isValid()) { 0229 return QModelIndex(); 0230 } 0231 0232 auto* childCheckGroup = static_cast<CheckGroup*>(child.internalPointer()); 0233 if (!childCheckGroup) { 0234 return QModelIndex(); 0235 } 0236 if (childCheckGroup == m_rootCheckGroup.data()) { 0237 return createIndex(0, 0, nullptr); 0238 } 0239 auto* parentCheckGroup = childCheckGroup->superGroup(); 0240 const auto& subGroups = parentCheckGroup->subGroups(); 0241 const int parentRow = subGroups.indexOf(childCheckGroup); 0242 return createIndex(parentRow, 0, parentCheckGroup); 0243 } 0244 0245 QModelIndex CheckListModel::index(int row, int column, const QModelIndex& parent) const 0246 { 0247 if ((column < NameColumnId) ||(column > CountColumnId) || 0248 (row < 0) || 0249 !m_rootCheckGroup) { 0250 return QModelIndex(); 0251 } 0252 0253 if (!parent.isValid()) { 0254 if (1 <= row) { 0255 return QModelIndex(); 0256 } 0257 return createIndex(row, column, nullptr); 0258 } 0259 0260 auto* superCheckGroup = checkGroup(parent); 0261 if (row >= childCount(superCheckGroup)) { 0262 return QModelIndex(); 0263 } 0264 0265 return createIndex(row, column, superCheckGroup); 0266 } 0267 0268 Qt::ItemFlags CheckListModel::flags(const QModelIndex& index) const 0269 { 0270 if (!index.isValid()) { 0271 return Qt::NoItemFlags; 0272 } 0273 0274 if (index.column() == CountColumnId) { 0275 return Qt::ItemIsEnabled | Qt::ItemIsSelectable; 0276 } 0277 0278 if (!m_isEditable) { 0279 return Qt::ItemIsEnabled | Qt::ItemIsSelectable; 0280 } 0281 0282 auto* checkGroup = static_cast<const CheckGroup*>(index.internalPointer()); 0283 0284 // root? 0285 if (!checkGroup) { 0286 return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable; 0287 } 0288 0289 return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsUserTristate; 0290 } 0291 0292 int CheckListModel::childCount(const CheckGroup* checkGroup) const 0293 { 0294 return checkGroup->subGroups().count() + checkGroup->checkNames().count(); 0295 } 0296 0297 CheckGroup* CheckListModel::checkGroup(const QModelIndex& index) const 0298 { 0299 auto* superCheckGroup = static_cast<CheckGroup*>(index.internalPointer()); 0300 if (!superCheckGroup) { 0301 return m_rootCheckGroup.data(); 0302 } 0303 0304 const int subGroupIndex = index.row(); 0305 const auto& subGroups = superCheckGroup->subGroups(); 0306 Q_ASSERT(0 <= subGroupIndex && subGroupIndex < subGroups.count()); 0307 return subGroups.at(subGroupIndex); 0308 } 0309 0310 0311 void CheckListModel::setCheckSet(const CheckSet* checkSet) 0312 { 0313 beginResetModel(); 0314 0315 m_checkSet = checkSet; 0316 0317 m_rootCheckGroup.reset(CheckGroup::fromPlainList(m_checkSet->all())); 0318 0319 if (m_isDefault) { 0320 m_rootCheckGroup->setEnabledChecks(m_checkSet->defaults()); 0321 } 0322 0323 endResetModel(); 0324 } 0325 0326 0327 QStringList CheckListModel::enabledChecks() const 0328 { 0329 if (m_isDefault) { 0330 return QStringList(); 0331 } 0332 0333 return m_rootCheckGroup->enabledChecksRules(); 0334 } 0335 0336 void CheckListModel::setEnabledChecks(const QStringList& enabledChecks) 0337 { 0338 beginResetModel(); 0339 0340 if (enabledChecks.isEmpty() && m_checkSet) { 0341 m_rootCheckGroup->setEnabledChecks(m_checkSet->defaults()); 0342 m_isDefault = true; 0343 } else { 0344 m_rootCheckGroup->setEnabledChecks(enabledChecks); 0345 m_isDefault = false; 0346 } 0347 0348 endResetModel(); 0349 } 0350 0351 void CheckListModel::setEditable(bool editable) 0352 { 0353 if (m_isEditable == editable) { 0354 return; 0355 } 0356 0357 beginResetModel(); 0358 m_isEditable = editable; 0359 endResetModel(); 0360 } 0361 0362 void CheckListModel::emitSubGroupDataChanged(const QModelIndex& subGroupIndex) 0363 { 0364 // first group itself 0365 emit dataChanged(subGroupIndex, subGroupIndex, {Qt::CheckStateRole}); 0366 const auto countIndex = subGroupIndex.sibling(subGroupIndex.row(), CountColumnId); 0367 emit dataChanged(countIndex, countIndex, {Qt::DisplayRole}); 0368 0369 auto* checkGroup = this->checkGroup(subGroupIndex); 0370 const int subGroupsCount = checkGroup->subGroups().count(); 0371 0372 // subgroups 0373 for (int i = 0; i < subGroupsCount; ++i) { 0374 const auto subSubGroupInxex = index(i, NameColumnId, subGroupIndex); 0375 emitSubGroupDataChanged(subSubGroupInxex); 0376 } 0377 0378 // checks 0379 const int checksCount = checkGroup->checkNames().count(); 0380 if (checksCount > 0) { 0381 const int firstChecksRow = subGroupsCount; 0382 const int lastChecksRow = firstChecksRow + checksCount - 1; 0383 const auto firstCheckIndex = index(firstChecksRow, NameColumnId, subGroupIndex); 0384 const auto lastCheckIndex = index(lastChecksRow, NameColumnId, subGroupIndex); 0385 emit dataChanged(firstCheckIndex, lastCheckIndex, {Qt::CheckStateRole}); 0386 } 0387 } 0388 0389 } 0390 0391 #include "moc_checklistmodel.cpp"