#include "codesnippeteditormodel.h" #include "common/strhash.h" #include "common/unused.h" #include "iconmanager.h" #include #define SETTER(X, Y) \ if (!isValidRowIndex(row) || X == Y) \ return; \ \ X = Y; \ emitDataChanged(row); #define GETTER(X, Y) \ if (!isValidRowIndex(row)) \ return Y; \ \ return X; CodeSnippetEditorModel::CodeSnippetEditorModel(QObject* parent) : QAbstractListModel(parent) { } void CodeSnippetEditorModel::clearModified() { beginResetModel(); for (Snippet*& snip : snippetList) snip->modified = false; listModified = false; originalSnippetList = snippetList; endResetModel(); } bool CodeSnippetEditorModel::isModified() const { if (snippetList != originalSnippetList) return true; for (Snippet* snip : snippetList) { if (snip->modified) return true; } return false; } bool CodeSnippetEditorModel::isModified(int row) const { GETTER(snippetList[row]->modified, false); } void CodeSnippetEditorModel::setModified(int row, bool modified) { SETTER(snippetList[row]->modified, modified); } bool CodeSnippetEditorModel::isValid() const { for (Snippet* snip : snippetList) { if (!snip->valid) return false; } return true; } bool CodeSnippetEditorModel::isValid(int row) const { GETTER(snippetList[row]->valid, false); } void CodeSnippetEditorModel::setValid(int row, bool valid) { SETTER(snippetList[row]->valid, valid); } void CodeSnippetEditorModel::setCode(int row, const QString& code) { SETTER(snippetList[row]->data.code, code); } QString CodeSnippetEditorModel::getCode(int row) const { GETTER(snippetList[row]->data.code, QString()); } void CodeSnippetEditorModel::setName(int row, const QString& newName) { SETTER(snippetList[row]->data.name, newName); } QString CodeSnippetEditorModel::getName(int row) const { GETTER(snippetList[row]->data.name, QString()); } void CodeSnippetEditorModel::setHotkey(int row, const QKeySequence& value) { SETTER(snippetList[row]->data.hotkey, value.toString()); } QKeySequence CodeSnippetEditorModel::getHotkey(int row) const { GETTER(QKeySequence(snippetList[row]->data.hotkey), QKeySequence()); } void CodeSnippetEditorModel::setData(const QList& snippets) { beginResetModel(); for (Snippet*& snippetPtr : snippetList) delete snippetPtr; snippetList.clear(); for (CodeSnippetManager::CodeSnippet* snip : snippets) snippetList << new Snippet(snip); listModified = false; originalSnippetList = snippetList; endResetModel(); } void CodeSnippetEditorModel::addSnippet(CodeSnippetManager::CodeSnippet* snippet) { int row = snippetList.size(); beginInsertRows(QModelIndex(), row, row); snippetList << new Snippet(snippet); listModified = true; endInsertRows(); } void CodeSnippetEditorModel::deleteSnippet(int row) { if (!isValidRowIndex(row)) return; beginRemoveRows(QModelIndex(), row, row); delete snippetList[row]; snippetList.removeAt(row); listModified = true; endRemoveRows(); } QList CodeSnippetEditorModel::generateSnippets() const { QList results; for (Snippet* snip: snippetList) results << new CodeSnippetManager::CodeSnippet(snip->data); return results; } QStringList CodeSnippetEditorModel::getSnippetNames() const { QStringList names; for (Snippet* snip : snippetList) names << snip->data.name; return names; } void CodeSnippetEditorModel::validateNames() { StrHash> counter; int row = 0; for (Snippet*& snip : snippetList) { snip->valid &= true; counter[snip->data.name] << row++; } QHashIterator> cntIt = counter.iterator(); while (cntIt.hasNext()) { cntIt.next(); if (cntIt.value().size() > 1) { for (int cntRow : cntIt.value()) setValid(cntRow, false); } } QModelIndex idx; for (int i = 0; i < snippetList.size(); i++) { idx = index(i); emit dataChanged(idx, idx); } } bool CodeSnippetEditorModel::isAllowedName(int rowToSkip, const QString& nameToValidate) { QStringList names = getSnippetNames(); names.removeAt(rowToSkip); return !names.contains(nameToValidate, Qt::CaseInsensitive); } bool CodeSnippetEditorModel::isAllowedHotkey(int rowToSkip, const QKeySequence& hotkeyToValidate) { QList keys; for (Snippet*& snip : snippetList) keys << snip->data.hotkey; keys.removeAt(rowToSkip); return !keys.contains(hotkeyToValidate); } bool CodeSnippetEditorModel::isValidRowIndex(int row) const { return (row >= 0 && row < snippetList.size()); } int CodeSnippetEditorModel::moveUp(int row) { if (row <= 0 || row >= snippetList.size()) return row; snippetList.move(row, row - 1); return row - 1; } int CodeSnippetEditorModel::moveDown(int row) { if (row < 0 || row + 1 >= snippetList.size()) return row; snippetList.move(row, row + 1); return row + 1; } int CodeSnippetEditorModel::rowCount(const QModelIndex& parent) const { UNUSED(parent); return snippetList.size(); } QVariant CodeSnippetEditorModel::data(const QModelIndex& index, int role) const { if (!index.isValid() || !isValidRowIndex(index.row())) return QVariant(); if (role == Qt::DisplayRole) { Snippet* sn = snippetList[index.row()]; return sn->data.name; } if (role == Qt::DecorationRole) { QIcon icon = ICONS.CODE_SNIPPET; if (!snippetList[index.row()]->valid) icon = Icon::merge(icon, Icon::ERROR); return icon; } return QVariant(); } void CodeSnippetEditorModel::emitDataChanged(int row) { QModelIndex idx = index(row); emit dataChanged(idx, idx); } CodeSnippetEditorModel::Snippet::Snippet() { } CodeSnippetEditorModel::Snippet::Snippet(CodeSnippetManager::CodeSnippet* other) { data = CodeSnippetManager::CodeSnippet(*other); originalName = data.name; }