From b87861f9b487cc26dd9030604dee0af98afdff4c Mon Sep 17 00:00:00 2001 From: Leandro Melo Date: Wed, 24 Nov 2010 11:04:24 +0100 Subject: [PATCH] Snippets: Add more use-cases - Restored removed built-in snippets. - Revert a built-in snippet. - Reset the snippets collection. --- src/plugins/texteditor/snippets/snippet.h | 2 +- .../texteditor/snippets/snippetscollection.cpp | 94 ++++++++++++----- .../texteditor/snippets/snippetscollection.h | 13 ++- .../texteditor/snippets/snippetssettingspage.cpp | 116 ++++++++++++++++----- .../texteditor/snippets/snippetssettingspage.ui | 21 ++++ 5 files changed, 192 insertions(+), 54 deletions(-) diff --git a/src/plugins/texteditor/snippets/snippet.h b/src/plugins/texteditor/snippets/snippet.h index d9d6c42245..984da3e7f9 100644 --- a/src/plugins/texteditor/snippets/snippet.h +++ b/src/plugins/texteditor/snippets/snippet.h @@ -80,7 +80,7 @@ public: private: bool m_isRemoved; bool m_isModified; - QString m_id; + QString m_id; // Only built-in snippets have an id. QString m_trigger; QString m_content; QString m_complement; diff --git a/src/plugins/texteditor/snippets/snippetscollection.cpp b/src/plugins/texteditor/snippets/snippetscollection.cpp index 1aad27644c..731f062603 100644 --- a/src/plugins/texteditor/snippets/snippetscollection.cpp +++ b/src/plugins/texteditor/snippets/snippetscollection.cpp @@ -221,10 +221,14 @@ int SnippetsCollection::totalSnippets(Snippet::Group group) const void SnippetsCollection::clear() { - for (Snippet::Group group = Snippet::Cpp; group < Snippet::GroupSize; ++group) { - m_snippets[group].clear(); - m_activeSnippetsEnd[group] = m_snippets[group].end(); - } + for (Snippet::Group group = Snippet::Cpp; group < Snippet::GroupSize; ++group) + clear(group); +} + +void SnippetsCollection::clear(Snippet::Group group) +{ + m_snippets[group].clear(); + m_activeSnippetsEnd[group] = m_snippets[group].end(); } void SnippetsCollection::updateActiveSnippetsEnd(Snippet::Group group) @@ -234,6 +238,41 @@ void SnippetsCollection::updateActiveSnippetsEnd(Snippet::Group group) removedSnippetPred); } +void SnippetsCollection::restoreRemovedSnippets(Snippet::Group group) +{ + // The version restored contains the last modifications (if any) by the user. + // Reverting the snippet can still bring it to the original version. + QVector toRestore(std::distance(m_activeSnippetsEnd[group], m_snippets[group].end())); + qCopy(m_activeSnippetsEnd[group], m_snippets[group].end(), toRestore.begin()); + m_snippets[group].erase(m_activeSnippetsEnd[group], m_snippets[group].end()); + foreach (Snippet snippet, toRestore) { + snippet.setIsRemoved(false); + insertSnippet(snippet, group); + } +} + +Snippet SnippetsCollection::revertedSnippet(int index, Snippet::Group group) const +{ + const Snippet &candidate = snippet(index, group); + Q_ASSERT(candidate.isBuiltIn()); + + const QList &builtIn = + readXML(m_builtInSnippetsPath + m_snippetsFileName, candidate.id()); + if (builtIn.size() == 1) + return builtIn.at(0); + return Snippet(); +} + +void SnippetsCollection::reset(Snippet::Group group) +{ + clear(group); + + const QList &builtInSnippets = readXML(m_builtInSnippetsPath + m_snippetsFileName); + foreach (const Snippet &snippet, builtInSnippets) + if (group == snippet.group()) + insertSnippet(snippet, snippet.group()); +} + void SnippetsCollection::reload() { clear(); @@ -268,10 +307,8 @@ void SnippetsCollection::synchronize() const int size = totalSnippets(group); for (int i = 0; i < size; ++i) { const Snippet ¤t = snippet(i, group); - if (!current.isBuiltIn() || - (current.isBuiltIn() && (current.isRemoved() || current.isModified()))) { + if (!current.isBuiltIn() || current.isRemoved() || current.isModified()) writeSnippetXML(current, &writer); - } } } writer.writeEndElement(); @@ -296,7 +333,7 @@ void SnippetsCollection::writeSnippetXML(const Snippet &snippet, QXmlStreamWrite writer->writeEndElement(); } -QList SnippetsCollection::readXML(const QString &fileName) +QList SnippetsCollection::readXML(const QString &fileName, const QString &snippetId) { QList snippets; QFile file(fileName); @@ -307,31 +344,36 @@ QList SnippetsCollection::readXML(const QString &fileName) while (xml.readNextStartElement()) { if (xml.name() == kSnippet) { const QXmlStreamAttributes &atts = xml.attributes(); + const QString &id = atts.value(kId).toString(); + if (snippetId.isEmpty() || snippetId == id) { + Snippet snippet(id); + snippet.setTrigger(atts.value(kTrigger).toString()); + snippet.setComplement(atts.value(kComplement).toString()); + snippet.setGroup(toSnippetGroup(atts.value(kGroup).toString())); + snippet.setIsRemoved(toBool(atts.value(kRemoved).toString())); + snippet.setIsModified(toBool(atts.value(kModified).toString())); + + QString content; + while (!xml.atEnd()) { + xml.readNext(); + if (xml.isCharacters()) { + content += xml.text(); + } else if (xml.isEndElement()) { + snippet.setContent(content); + snippets.append(snippet); + break; + } + } - Snippet snippet(atts.value(kId).toString()); - snippet.setTrigger(atts.value(kTrigger).toString()); - snippet.setComplement(atts.value(kComplement).toString()); - snippet.setGroup(toSnippetGroup(atts.value(kGroup).toString())); - snippet.setIsRemoved(toBool(atts.value(kRemoved).toString())); - snippet.setIsModified(toBool(atts.value(kModified).toString())); - - QString content; - while (!xml.atEnd()) { - xml.readNext(); - if (xml.isCharacters()) { - content += xml.text(); - } else if (xml.isEndElement()) { - snippet.setContent(content); - snippets.append(snippet); + if (!snippetId.isEmpty()) break; - } + } else { + xml.skipCurrentElement(); } } else { xml.skipCurrentElement(); } } - } else { - xml.skipCurrentElement(); } } if (xml.hasError()) diff --git a/src/plugins/texteditor/snippets/snippetscollection.h b/src/plugins/texteditor/snippets/snippetscollection.h index 64fd300443..4282ea7af6 100644 --- a/src/plugins/texteditor/snippets/snippetscollection.h +++ b/src/plugins/texteditor/snippets/snippetscollection.h @@ -76,10 +76,14 @@ public: Hint computeReplacementHint(int index, const Snippet &snippet, Snippet::Group group); void removeSnippet(int index, Snippet::Group group); + void restoreRemovedSnippets(Snippet::Group group); void setSnippetContent(int index, Snippet::Group group, const QString &content); const Snippet &snippet(int index, Snippet::Group group) const; + Snippet revertedSnippet(int index, Snippet::Group group) const; + + void reset(Snippet::Group group); int totalActiveSnippets(Snippet::Group group) const; int totalSnippets(Snippet::Group group) const; @@ -89,9 +93,10 @@ public: private: void clear(); + void clear(Snippet::Group group); void updateActiveSnippetsEnd(Snippet::Group group); - static QList readXML(const QString &fileName); + static QList readXML(const QString &fileName, const QString &snippetId = QString()); static void writeSnippetXML(const Snippet &snippet, QXmlStreamWriter *writer); static const QLatin1String kSnippet; @@ -103,9 +108,15 @@ private: static const QLatin1String kRemoved; static const QLatin1String kModified; + // Snippets for each group are kept in a list. However, not all of them are necessarily + // active. Specifically, removed built-in snippets are kept as the last ones (for each + // group there is a iterator that marks the logical end). QVector > m_snippets; QVector::iterator> m_activeSnippetsEnd; + // Built-in snippets are specified in an XML embedded as a resource. Snippets created/ + // modified/removed by the user are stored in another XML created dynamically in the + // user's folder. QString m_builtInSnippetsPath; QString m_userSnippetsPath; QString m_snippetsFileName; diff --git a/src/plugins/texteditor/snippets/snippetssettingspage.cpp b/src/plugins/texteditor/snippets/snippetssettingspage.cpp index 156b42aca8..f73fe64673 100644 --- a/src/plugins/texteditor/snippets/snippetssettingspage.cpp +++ b/src/plugins/texteditor/snippets/snippetssettingspage.cpp @@ -75,8 +75,12 @@ public: void removeSnippet(const QModelIndex &modelIndex); const Snippet &snippetAt(const QModelIndex &modelIndex) const; void setSnippetContent(const QModelIndex &modelIndex, const QString &content); + void revertBuitInSnippet(const QModelIndex &modelIndex); + void restoreRemovedBuiltInSnippets(); + void resetSnippets(); private: + void replaceSnippet(const Snippet &snippet, const QModelIndex &modelIndex); static bool isValidTrigger(const QString &s); Snippet::Group m_activeGroup; @@ -130,8 +134,7 @@ QVariant SnippetsTableModel::data(const QModelIndex &modelIndex, int role) const bool SnippetsTableModel::setData(const QModelIndex &modelIndex, const QVariant &value, int role) { if (modelIndex.isValid() && role == Qt::EditRole) { - const int row = modelIndex.row(); - Snippet snippet(m_collection->snippet(row, m_activeGroup)); + Snippet snippet(m_collection->snippet(modelIndex.row(), m_activeGroup)); if (modelIndex.column() == 0) { const QString &s = value.toString(); if (!isValidTrigger(s)) { @@ -145,21 +148,7 @@ bool SnippetsTableModel::setData(const QModelIndex &modelIndex, const QVariant & snippet.setComplement(value.toString()); } - const SnippetsCollection::Hint &hint = - m_collection->computeReplacementHint(row, snippet, m_activeGroup); - if (modelIndex.row() == hint.index()) { - m_collection->replaceSnippet(row, snippet, m_activeGroup, hint); - emit dataChanged(modelIndex, modelIndex); - } else { - if (row < hint.index()) - // Rows will be moved down. - beginMoveRows(QModelIndex(), row, row, QModelIndex(), hint.index() + 1); - else - beginMoveRows(QModelIndex(), row, row, QModelIndex(), hint.index()); - m_collection->replaceSnippet(row, snippet, m_activeGroup, hint); - endMoveRows(); - } - + replaceSnippet(snippet, modelIndex); return true; } return false; @@ -217,6 +206,47 @@ void SnippetsTableModel::setSnippetContent(const QModelIndex &modelIndex, const m_collection->setSnippetContent(modelIndex.row(), m_activeGroup, content); } +void SnippetsTableModel::revertBuitInSnippet(const QModelIndex &modelIndex) +{ + const Snippet &snippet = m_collection->revertedSnippet(modelIndex.row(), m_activeGroup); + if (snippet.id().isEmpty()) { + QMessageBox::critical(0, tr("Error"), tr("Error reverting snippet.")); + return; + } + replaceSnippet(snippet, modelIndex); +} + +void SnippetsTableModel::restoreRemovedBuiltInSnippets() +{ + m_collection->restoreRemovedSnippets(m_activeGroup); + reset(); +} + +void SnippetsTableModel::resetSnippets() +{ + m_collection->reset(m_activeGroup); + reset(); +} + +void SnippetsTableModel::replaceSnippet(const Snippet &snippet, const QModelIndex &modelIndex) +{ + const int row = modelIndex.row(); + const SnippetsCollection::Hint &hint = + m_collection->computeReplacementHint(row, snippet, m_activeGroup); + if (modelIndex.row() == hint.index()) { + m_collection->replaceSnippet(row, snippet, m_activeGroup, hint); + emit dataChanged(modelIndex, modelIndex); + } else { + if (row < hint.index()) + // Rows will be moved down. + beginMoveRows(QModelIndex(), row, row, QModelIndex(), hint.index() + 1); + else + beginMoveRows(QModelIndex(), row, row, QModelIndex(), hint.index()); + m_collection->replaceSnippet(row, snippet, m_activeGroup, hint); + endMoveRows(); + } +} + bool SnippetsTableModel::isValidTrigger(const QString &s) { if (s.isEmpty()) @@ -248,10 +278,13 @@ private slots: void markSnippetsCollection(); void addSnippet(); void removeSnippet(); + void revertBuiltInSnippet(); + void restoreRemovedBuiltInSnippets(); + void resetAllSnippets(); void selectSnippet(const QModelIndex &parent, int row); void selectMovedSnippet(const QModelIndex &, int, int, const QModelIndex &, int row); - void previewSnippet(const QModelIndex &modelIndex); - void updateSnippetContent(); + void setSnippetContent(); + void updateCurrentSnippetDependent(const QModelIndex &modelIndex = QModelIndex()); private: SnippetEditor *currentEditor() const; @@ -314,17 +347,19 @@ void SnippetsSettingsPagePrivate::configureUi(QWidget *w) decorateEditor(editorAt(Snippet::Qml), Snippet::Qml); decorateEditor(editorAt(Snippet::PlainText), Snippet::PlainText); + m_ui.revertButton->setEnabled(false); + QTextStream(&m_keywords) << m_displayName; loadSettings(); loadSnippetGroup(m_ui.groupCombo->currentIndex()); connect(editorAt(Snippet::Cpp), SIGNAL(snippetContentChanged()), - this, SLOT(updateSnippetContent())); + this, SLOT(setSnippetContent())); connect(editorAt(Snippet::Qml), SIGNAL(snippetContentChanged()), - this, SLOT(updateSnippetContent())); + this, SLOT(setSnippetContent())); connect(editorAt(Snippet::PlainText), SIGNAL(snippetContentChanged()), - this, SLOT(updateSnippetContent())); + this, SLOT(setSnippetContent())); connect(m_model, SIGNAL(rowsInserted(QModelIndex, int, int)), this, SLOT(selectSnippet(QModelIndex,int))); @@ -338,12 +373,18 @@ void SnippetsSettingsPagePrivate::configureUi(QWidget *w) this, SLOT(markSnippetsCollection())); connect(m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(markSnippetsCollection())); + connect(m_model, SIGNAL(modelReset()), this, SLOT(updateCurrentSnippetDependent())); + connect(m_model, SIGNAL(modelReset()), this, SLOT(markSnippetsCollection())); connect(m_ui.groupCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(loadSnippetGroup(int))); connect(m_ui.addButton, SIGNAL(clicked()), this, SLOT(addSnippet())); connect(m_ui.removeButton, SIGNAL(clicked()), this, SLOT(removeSnippet())); + connect(m_ui.resetAllButton, SIGNAL(clicked()), this, SLOT(resetAllSnippets())); + connect(m_ui.restoreRemovedButton, SIGNAL(clicked()), + this, SLOT(restoreRemovedBuiltInSnippets())); + connect(m_ui.revertButton, SIGNAL(clicked()), this, SLOT(revertBuiltInSnippet())); connect(m_ui.snippetsTable->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), - this, SLOT(previewSnippet(QModelIndex))); + this, SLOT(updateCurrentSnippetDependent(QModelIndex))); } void SnippetsSettingsPagePrivate::decorateEditor(SnippetEditor *editor, Snippet::Group group) @@ -427,6 +468,21 @@ void SnippetsSettingsPagePrivate::removeSnippet() m_model->removeSnippet(modelIndex); } +void SnippetsSettingsPagePrivate::restoreRemovedBuiltInSnippets() +{ + m_model->restoreRemovedBuiltInSnippets(); +} + +void SnippetsSettingsPagePrivate::revertBuiltInSnippet() +{ + m_model->revertBuitInSnippet(m_ui.snippetsTable->selectionModel()->currentIndex()); +} + +void SnippetsSettingsPagePrivate::resetAllSnippets() +{ + m_model->resetSnippets(); +} + void SnippetsSettingsPagePrivate::selectSnippet(const QModelIndex &parent, int row) { QModelIndex topLeft = m_model->index(row, 0, parent); @@ -449,14 +505,22 @@ void SnippetsSettingsPagePrivate::selectMovedSnippet(const QModelIndex &, else modelIndex = m_model->index(destinationRow, 0, destinationParent); m_ui.snippetsTable->scrollTo(modelIndex); + currentEditor()->setPlainText(m_model->snippetAt(modelIndex).content()); } -void SnippetsSettingsPagePrivate::previewSnippet(const QModelIndex &modelIndex) +void SnippetsSettingsPagePrivate::updateCurrentSnippetDependent(const QModelIndex &modelIndex) { - currentEditor()->setPlainText(m_model->snippetAt(modelIndex).content()); + if (modelIndex.isValid()) { + const Snippet &snippet = m_model->snippetAt(modelIndex); + currentEditor()->setPlainText(snippet.content()); + m_ui.revertButton->setEnabled(snippet.isBuiltIn()); + } else { + currentEditor()->clear(); + m_ui.revertButton->setEnabled(false); + } } -void SnippetsSettingsPagePrivate::updateSnippetContent() +void SnippetsSettingsPagePrivate::setSnippetContent() { const QModelIndex &modelIndex = m_ui.snippetsTable->selectionModel()->currentIndex(); if (modelIndex.isValid()) { diff --git a/src/plugins/texteditor/snippets/snippetssettingspage.ui b/src/plugins/texteditor/snippets/snippetssettingspage.ui index df9917d9d9..e95fa7afc7 100644 --- a/src/plugins/texteditor/snippets/snippetssettingspage.ui +++ b/src/plugins/texteditor/snippets/snippetssettingspage.ui @@ -80,6 +80,27 @@ + + + Revert Built-in + + + + + + + Restore Removed Built-ins + + + + + + + Reset All + + + + Qt::Vertical -- 2.11.0