Commit b87861f9 authored by Leandro Melo's avatar Leandro Melo
Browse files

Snippets: Add more use-cases

- Restored removed built-in snippets.
- Revert a built-in snippet.
- Reset the snippets collection.
parent 22c9b652
...@@ -80,7 +80,7 @@ public: ...@@ -80,7 +80,7 @@ public:
private: private:
bool m_isRemoved; bool m_isRemoved;
bool m_isModified; bool m_isModified;
QString m_id; QString m_id; // Only built-in snippets have an id.
QString m_trigger; QString m_trigger;
QString m_content; QString m_content;
QString m_complement; QString m_complement;
......
...@@ -221,10 +221,14 @@ int SnippetsCollection::totalSnippets(Snippet::Group group) const ...@@ -221,10 +221,14 @@ int SnippetsCollection::totalSnippets(Snippet::Group group) const
void SnippetsCollection::clear() void SnippetsCollection::clear()
{ {
for (Snippet::Group group = Snippet::Cpp; group < Snippet::GroupSize; ++group) { for (Snippet::Group group = Snippet::Cpp; group < Snippet::GroupSize; ++group)
m_snippets[group].clear(); clear(group);
m_activeSnippetsEnd[group] = m_snippets[group].end(); }
}
void SnippetsCollection::clear(Snippet::Group group)
{
m_snippets[group].clear();
m_activeSnippetsEnd[group] = m_snippets[group].end();
} }
void SnippetsCollection::updateActiveSnippetsEnd(Snippet::Group group) void SnippetsCollection::updateActiveSnippetsEnd(Snippet::Group group)
...@@ -234,6 +238,41 @@ void SnippetsCollection::updateActiveSnippetsEnd(Snippet::Group group) ...@@ -234,6 +238,41 @@ void SnippetsCollection::updateActiveSnippetsEnd(Snippet::Group group)
removedSnippetPred); 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<Snippet> 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<Snippet> &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<Snippet> &builtInSnippets = readXML(m_builtInSnippetsPath + m_snippetsFileName);
foreach (const Snippet &snippet, builtInSnippets)
if (group == snippet.group())
insertSnippet(snippet, snippet.group());
}
void SnippetsCollection::reload() void SnippetsCollection::reload()
{ {
clear(); clear();
...@@ -268,10 +307,8 @@ void SnippetsCollection::synchronize() ...@@ -268,10 +307,8 @@ void SnippetsCollection::synchronize()
const int size = totalSnippets(group); const int size = totalSnippets(group);
for (int i = 0; i < size; ++i) { for (int i = 0; i < size; ++i) {
const Snippet &current = snippet(i, group); const Snippet &current = snippet(i, group);
if (!current.isBuiltIn() || if (!current.isBuiltIn() || current.isRemoved() || current.isModified())
(current.isBuiltIn() && (current.isRemoved() || current.isModified()))) {
writeSnippetXML(current, &writer); writeSnippetXML(current, &writer);
}
} }
} }
writer.writeEndElement(); writer.writeEndElement();
...@@ -296,7 +333,7 @@ void SnippetsCollection::writeSnippetXML(const Snippet &snippet, QXmlStreamWrite ...@@ -296,7 +333,7 @@ void SnippetsCollection::writeSnippetXML(const Snippet &snippet, QXmlStreamWrite
writer->writeEndElement(); writer->writeEndElement();
} }
QList<Snippet> SnippetsCollection::readXML(const QString &fileName) QList<Snippet> SnippetsCollection::readXML(const QString &fileName, const QString &snippetId)
{ {
QList<Snippet> snippets; QList<Snippet> snippets;
QFile file(fileName); QFile file(fileName);
...@@ -307,31 +344,36 @@ QList<Snippet> SnippetsCollection::readXML(const QString &fileName) ...@@ -307,31 +344,36 @@ QList<Snippet> SnippetsCollection::readXML(const QString &fileName)
while (xml.readNextStartElement()) { while (xml.readNextStartElement()) {
if (xml.name() == kSnippet) { if (xml.name() == kSnippet) {
const QXmlStreamAttributes &atts = xml.attributes(); 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()); if (!snippetId.isEmpty())
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; break;
} } else {
xml.skipCurrentElement();
} }
} else { } else {
xml.skipCurrentElement(); xml.skipCurrentElement();
} }
} }
} else {
xml.skipCurrentElement();
} }
} }
if (xml.hasError()) if (xml.hasError())
......
...@@ -76,10 +76,14 @@ public: ...@@ -76,10 +76,14 @@ public:
Hint computeReplacementHint(int index, const Snippet &snippet, Snippet::Group group); Hint computeReplacementHint(int index, const Snippet &snippet, Snippet::Group group);
void removeSnippet(int index, 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); void setSnippetContent(int index, Snippet::Group group, const QString &content);
const Snippet &snippet(int index, Snippet::Group group) const; 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 totalActiveSnippets(Snippet::Group group) const;
int totalSnippets(Snippet::Group group) const; int totalSnippets(Snippet::Group group) const;
...@@ -89,9 +93,10 @@ public: ...@@ -89,9 +93,10 @@ public:
private: private:
void clear(); void clear();
void clear(Snippet::Group group);
void updateActiveSnippetsEnd(Snippet::Group group); void updateActiveSnippetsEnd(Snippet::Group group);
static QList<Snippet> readXML(const QString &fileName); static QList<Snippet> readXML(const QString &fileName, const QString &snippetId = QString());
static void writeSnippetXML(const Snippet &snippet, QXmlStreamWriter *writer); static void writeSnippetXML(const Snippet &snippet, QXmlStreamWriter *writer);
static const QLatin1String kSnippet; static const QLatin1String kSnippet;
...@@ -103,9 +108,15 @@ private: ...@@ -103,9 +108,15 @@ private:
static const QLatin1String kRemoved; static const QLatin1String kRemoved;
static const QLatin1String kModified; 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<QList<Snippet> > m_snippets; QVector<QList<Snippet> > m_snippets;
QVector<QList<Snippet>::iterator> m_activeSnippetsEnd; QVector<QList<Snippet>::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_builtInSnippetsPath;
QString m_userSnippetsPath; QString m_userSnippetsPath;
QString m_snippetsFileName; QString m_snippetsFileName;
......
...@@ -75,8 +75,12 @@ public: ...@@ -75,8 +75,12 @@ public:
void removeSnippet(const QModelIndex &modelIndex); void removeSnippet(const QModelIndex &modelIndex);
const Snippet &snippetAt(const QModelIndex &modelIndex) const; const Snippet &snippetAt(const QModelIndex &modelIndex) const;
void setSnippetContent(const QModelIndex &modelIndex, const QString &content); void setSnippetContent(const QModelIndex &modelIndex, const QString &content);
void revertBuitInSnippet(const QModelIndex &modelIndex);
void restoreRemovedBuiltInSnippets();
void resetSnippets();
private: private:
void replaceSnippet(const Snippet &snippet, const QModelIndex &modelIndex);
static bool isValidTrigger(const QString &s); static bool isValidTrigger(const QString &s);
Snippet::Group m_activeGroup; Snippet::Group m_activeGroup;
...@@ -130,8 +134,7 @@ QVariant SnippetsTableModel::data(const QModelIndex &modelIndex, int role) const ...@@ -130,8 +134,7 @@ QVariant SnippetsTableModel::data(const QModelIndex &modelIndex, int role) const
bool SnippetsTableModel::setData(const QModelIndex &modelIndex, const QVariant &value, int role) bool SnippetsTableModel::setData(const QModelIndex &modelIndex, const QVariant &value, int role)
{ {
if (modelIndex.isValid() && role == Qt::EditRole) { if (modelIndex.isValid() && role == Qt::EditRole) {
const int row = modelIndex.row(); Snippet snippet(m_collection->snippet(modelIndex.row(), m_activeGroup));
Snippet snippet(m_collection->snippet(row, m_activeGroup));
if (modelIndex.column() == 0) { if (modelIndex.column() == 0) {
const QString &s = value.toString(); const QString &s = value.toString();
if (!isValidTrigger(s)) { if (!isValidTrigger(s)) {
...@@ -145,21 +148,7 @@ bool SnippetsTableModel::setData(const QModelIndex &modelIndex, const QVariant & ...@@ -145,21 +148,7 @@ bool SnippetsTableModel::setData(const QModelIndex &modelIndex, const QVariant &
snippet.setComplement(value.toString()); snippet.setComplement(value.toString());
} }
const SnippetsCollection::Hint &hint = replaceSnippet(snippet, modelIndex);
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();
}
return true; return true;
} }
return false; return false;
...@@ -217,6 +206,47 @@ void SnippetsTableModel::setSnippetContent(const QModelIndex &modelIndex, const ...@@ -217,6 +206,47 @@ void SnippetsTableModel::setSnippetContent(const QModelIndex &modelIndex, const
m_collection->setSnippetContent(modelIndex.row(), m_activeGroup, content); 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) bool SnippetsTableModel::isValidTrigger(const QString &s)
{ {
if (s.isEmpty()) if (s.isEmpty())
...@@ -248,10 +278,13 @@ private slots: ...@@ -248,10 +278,13 @@ private slots:
void markSnippetsCollection(); void markSnippetsCollection();
void addSnippet(); void addSnippet();
void removeSnippet(); void removeSnippet();
void revertBuiltInSnippet();
void restoreRemovedBuiltInSnippets();
void resetAllSnippets();
void selectSnippet(const QModelIndex &parent, int row); void selectSnippet(const QModelIndex &parent, int row);
void selectMovedSnippet(const QModelIndex &, int, int, const QModelIndex &, int row); void selectMovedSnippet(const QModelIndex &, int, int, const QModelIndex &, int row);
void previewSnippet(const QModelIndex &modelIndex); void setSnippetContent();
void updateSnippetContent(); void updateCurrentSnippetDependent(const QModelIndex &modelIndex = QModelIndex());
private: private:
SnippetEditor *currentEditor() const; SnippetEditor *currentEditor() const;
...@@ -314,17 +347,19 @@ void SnippetsSettingsPagePrivate::configureUi(QWidget *w) ...@@ -314,17 +347,19 @@ void SnippetsSettingsPagePrivate::configureUi(QWidget *w)
decorateEditor(editorAt(Snippet::Qml), Snippet::Qml); decorateEditor(editorAt(Snippet::Qml), Snippet::Qml);
decorateEditor(editorAt(Snippet::PlainText), Snippet::PlainText); decorateEditor(editorAt(Snippet::PlainText), Snippet::PlainText);
m_ui.revertButton->setEnabled(false);
QTextStream(&m_keywords) << m_displayName; QTextStream(&m_keywords) << m_displayName;
loadSettings(); loadSettings();
loadSnippetGroup(m_ui.groupCombo->currentIndex()); loadSnippetGroup(m_ui.groupCombo->currentIndex());
connect(editorAt(Snippet::Cpp), SIGNAL(snippetContentChanged()), connect(editorAt(Snippet::Cpp), SIGNAL(snippetContentChanged()),
this, SLOT(updateSnippetContent())); this, SLOT(setSnippetContent()));
connect(editorAt(Snippet::Qml), SIGNAL(snippetContentChanged()), connect(editorAt(Snippet::Qml), SIGNAL(snippetContentChanged()),
this, SLOT(updateSnippetContent())); this, SLOT(setSnippetContent()));
connect(editorAt(Snippet::PlainText), SIGNAL(snippetContentChanged()), connect(editorAt(Snippet::PlainText), SIGNAL(snippetContentChanged()),
this, SLOT(updateSnippetContent())); this, SLOT(setSnippetContent()));
connect(m_model, SIGNAL(rowsInserted(QModelIndex, int, int)), connect(m_model, SIGNAL(rowsInserted(QModelIndex, int, int)),
this, SLOT(selectSnippet(QModelIndex,int))); this, SLOT(selectSnippet(QModelIndex,int)));
...@@ -338,12 +373,18 @@ void SnippetsSettingsPagePrivate::configureUi(QWidget *w) ...@@ -338,12 +373,18 @@ void SnippetsSettingsPagePrivate::configureUi(QWidget *w)
this, SLOT(markSnippetsCollection())); this, SLOT(markSnippetsCollection()));
connect(m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), connect(m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
this, SLOT(markSnippetsCollection())); 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.groupCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(loadSnippetGroup(int)));
connect(m_ui.addButton, SIGNAL(clicked()), this, SLOT(addSnippet())); connect(m_ui.addButton, SIGNAL(clicked()), this, SLOT(addSnippet()));
connect(m_ui.removeButton, SIGNAL(clicked()), this, SLOT(removeSnippet())); 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)), 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) void SnippetsSettingsPagePrivate::decorateEditor(SnippetEditor *editor, Snippet::Group group)
...@@ -427,6 +468,21 @@ void SnippetsSettingsPagePrivate::removeSnippet() ...@@ -427,6 +468,21 @@ void SnippetsSettingsPagePrivate::removeSnippet()
m_model->removeSnippet(modelIndex); 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) void SnippetsSettingsPagePrivate::selectSnippet(const QModelIndex &parent, int row)
{ {
QModelIndex topLeft = m_model->index(row, 0, parent); QModelIndex topLeft = m_model->index(row, 0, parent);
...@@ -449,14 +505,22 @@ void SnippetsSettingsPagePrivate::selectMovedSnippet(const QModelIndex &, ...@@ -449,14 +505,22 @@ void SnippetsSettingsPagePrivate::selectMovedSnippet(const QModelIndex &,
else else
modelIndex = m_model->index(destinationRow, 0, destinationParent); modelIndex = m_model->index(destinationRow, 0, destinationParent);
m_ui.snippetsTable->scrollTo(modelIndex); 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(); const QModelIndex &modelIndex = m_ui.snippetsTable->selectionModel()->currentIndex();
if (modelIndex.isValid()) { if (modelIndex.isValid()) {
......
...@@ -79,6 +79,27 @@ ...@@ -79,6 +79,27 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QPushButton" name="revertButton">
<property name="text">
<string>Revert Built-in</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="restoreRemovedButton">
<property name="text">
<string>Restore Removed Built-ins</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="resetAllButton">
<property name="text">
<string>Reset All</string>
</property>
</widget>
</item>
<item> <item>
<spacer name="verticalSpacer"> <spacer name="verticalSpacer">
<property name="orientation"> <property name="orientation">
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment