File indexing completed on 2024-11-10 05:11:09

0001 /*
0002  * Copyright 2018 by Marco Martin <mart@kde.org>
0003  *
0004  * Licensed under the Apache License, Version 2.0 (the "License");
0005  * you may not use this file except in compliance with the License.
0006  * You may obtain a copy of the License at
0007  *
0008  *    http://www.apache.org/licenses/LICENSE-2.0
0009  *
0010  * Unless required by applicable law or agreed to in writing, software
0011  * distributed under the License is distributed on an "AS IS" BASIS,
0012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013  * See the License for the specific language governing permissions and
0014  * limitations under the License.
0015  *
0016  */
0017 
0018 #include "activeskillsmodel.h"
0019 #include "delegatesmodel.h"
0020 #include "abstractdelegate.h"
0021 
0022 #include <QDebug>
0023 
0024 
0025 ActiveSkillsModel::ActiveSkillsModel(QObject *parent)
0026     : QAbstractListModel(parent)
0027 {
0028 }
0029 
0030 ActiveSkillsModel::~ActiveSkillsModel()
0031 {
0032     //TODO: delete everything
0033 }
0034 
0035 void ActiveSkillsModel::syncActiveIndex()
0036 {
0037     if (m_skills.isEmpty()) {
0038         m_activeIndex = -1;
0039         emit activeIndexChanged();
0040     }
0041 
0042     int index = -1;
0043     int i = 0;
0044     for (const auto &skill : m_skills) {
0045 
0046         if (skillAllowed(skill)) {
0047             index = i;
0048             break;
0049         }
0050         ++i;
0051     }
0052 
0053     if (m_activeIndex != index) {
0054         m_activeIndex = index;
0055         emit activeIndexChanged();
0056     }
0057 }
0058 
0059 int ActiveSkillsModel::activeIndex() const
0060 {
0061     return m_activeIndex;
0062 }
0063 
0064 
0065 QStringList ActiveSkillsModel::blackList() const
0066 {
0067     return m_blackList;
0068 }
0069 
0070 void ActiveSkillsModel::setBlackList(const QStringList &list)
0071 {
0072     if (list == m_blackList) {
0073         return;
0074     }
0075 
0076     m_blackList = list;
0077 
0078     // TODO: delete/create delegates?
0079     emit blackListChanged();
0080 }
0081 
0082 QStringList ActiveSkillsModel::whiteList() const
0083 {
0084     return m_whiteList;
0085 }
0086 
0087 void ActiveSkillsModel::setWhiteList(const QStringList &list)
0088 {
0089     if (list == m_whiteList) {
0090         return;
0091     }
0092 
0093     m_whiteList = list;
0094 
0095     emit whiteListChanged();
0096 }
0097 
0098 void ActiveSkillsModel::checkGuiActivation(const QString &skillId)
0099 {
0100     if (!skillAllowed(skillId)) {
0101         emit blacklistedSkillActivated(skillId);
0102         return;
0103     }
0104 
0105     if (activeSkills().isEmpty()) {
0106         return;
0107     }
0108 
0109     if (activeSkills().first() == skillId) {
0110         emit skillActivated(skillId);
0111     }
0112 }
0113 
0114 bool ActiveSkillsModel::skillAllowed(const QString skillId) const
0115 {
0116     return !m_blackList.contains(skillId) && (m_whiteList.isEmpty() || m_whiteList.contains(skillId));
0117 }
0118 
0119 void ActiveSkillsModel::insertSkills(int position, const QStringList &skillList)
0120 {
0121     if (position < 0 || position > m_skills.count()) {
0122         return;
0123     }
0124 
0125     QStringList filteredList;
0126 
0127     std::copy_if(skillList.begin(), skillList.end(),
0128                  std::back_inserter(filteredList),
0129                  [this](const QString &val)
0130                  {
0131                      return !m_skills.contains(val);
0132                  });
0133 
0134     if (filteredList.isEmpty()) {
0135         return;
0136     }
0137 
0138     beginInsertRows(QModelIndex(), position, position + filteredList.count() - 1);
0139 
0140     int i = 0;
0141     for (const auto &skillId : filteredList) {
0142         m_skills.insert(position + i, skillId);
0143         ++i;
0144     }
0145     //First syncactiveindex then endInserRows as it could make the view think we don't have any delegates for current skill
0146     syncActiveIndex();
0147     endInsertRows();
0148 
0149     //TODO: activate proper skills
0150     if (position == m_activeIndex) {
0151         checkGuiActivation(filteredList.first());
0152     }
0153 }
0154 
0155 QStringList ActiveSkillsModel::activeSkills() const
0156 {
0157     return m_skills;
0158 }
0159 
0160 QModelIndex ActiveSkillsModel::skillIndex(const QString &skillId)
0161 {
0162     const int row = m_skills.indexOf(skillId);
0163 
0164     if (row >= 0) {
0165         return index(row, 0, QModelIndex());
0166     }
0167 
0168     return QModelIndex();
0169 }
0170 
0171 DelegatesModel *ActiveSkillsModel::delegatesModelForSkill(const QString &skillId)
0172 {
0173 
0174     if (!skillAllowed(skillId)) {
0175         return nullptr;
0176     }
0177 
0178     if (!skillId.isEmpty() && !m_skills.contains(skillId)) {
0179         return nullptr;
0180     }
0181 
0182     DelegatesModel *model = m_delegatesModels.value(skillId);
0183     if (!model) {
0184         model = new DelegatesModel(this);
0185         m_delegatesModels[skillId] = model;
0186         const int row = m_skills.indexOf(skillId);
0187         emit dataChanged(index(row, 0), index(row, 0), {Delegates});
0188     }
0189 
0190     return model;
0191 }
0192 
0193 QHash<QString, DelegatesModel*> ActiveSkillsModel::delegatesModels() const
0194 {
0195     return m_delegatesModels;
0196 }
0197 
0198 bool ActiveSkillsModel::moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild)
0199 {
0200     if (sourceParent.isValid() || destinationParent.isValid()) {
0201         return false;
0202     }
0203 
0204     if (count <= 0 || sourceRow == destinationChild || sourceRow < 0 || sourceRow >= m_skills.count() ||
0205         destinationChild < 0 || destinationChild >= m_skills.count() || count - destinationChild > m_skills.count() - sourceRow) {
0206         return false;
0207     }
0208     const int sourceLast = sourceRow + count - 1;
0209 
0210     //beginMoveRows wants indexes before the source rows are removed from the old order
0211     if (!beginMoveRows(sourceParent, sourceRow, sourceLast, destinationParent, destinationChild)) {
0212         return false;
0213     }
0214 
0215     if (sourceRow < destinationChild) {
0216         for (int i = count - 1; i >= 0; --i) {
0217             m_skills.move(sourceRow + i, destinationChild - count + i);
0218         }
0219     } else {
0220         for (int i = 0; i < count; ++i) {
0221             m_skills.move(sourceRow + i, destinationChild + i);
0222         }
0223     }
0224 
0225     endMoveRows();
0226 
0227     syncActiveIndex();
0228     if (destinationChild == m_activeIndex) {
0229         checkGuiActivation(m_skills.first());
0230     }
0231 
0232     return true;
0233 }
0234 
0235 bool ActiveSkillsModel::removeRows(int row, int count, const QModelIndex &parent)
0236 {
0237     if (row < 0 || count <= 0 || row + count > m_skills.count() || parent.isValid()) {
0238         return false;
0239     }
0240 
0241     beginRemoveRows(parent, row, row + count - 1);
0242     for (auto it = m_skills.begin() + row; it < m_skills.begin() + row + count; ++it) {
0243         DelegatesModel *model = m_delegatesModels.value(*it);
0244         if (model) {
0245             model->deleteLater();
0246             m_delegatesModels.remove(*it);
0247         }
0248     }
0249     m_skills.erase(m_skills.begin() + row, m_skills.begin() + row + count);
0250 
0251     endRemoveRows();
0252     syncActiveIndex();
0253     return true;
0254 }
0255 
0256 
0257 int ActiveSkillsModel::rowCount(const QModelIndex &parent) const
0258 {
0259     if (parent.isValid()) {
0260         return 0;
0261     }
0262     return m_skills.count();
0263 }
0264 
0265 QVariant ActiveSkillsModel::data(const QModelIndex &index, int role) const
0266 {
0267     if (!index.isValid()) {
0268         return QVariant();
0269     }
0270     const int row = index.row();
0271 
0272     if (row < 0 || row >= m_skills.count() || (role != SkillId && role != Delegates)) {
0273         return QVariant();
0274     }
0275 
0276     if (role == SkillId) {
0277         return m_skills[row];
0278     //Delegates
0279     } else {
0280         return QVariant::fromValue(m_delegatesModels.value(m_skills[row]));
0281     }
0282 }
0283 
0284 QHash<int, QByteArray> ActiveSkillsModel::roleNames() const
0285 {
0286     return {
0287         {SkillId, "skillId"},
0288         {Delegates, "delegates"}
0289     };
0290 }
0291