# # # add_file "src/view/ChangeLogEdit.cpp" # content [1c068b2fb8e467c4a0a6e13f5854a3717cf2f738] # # add_file "src/view/ChangeLogEdit.h" # content [3c9c904f9016a9854b761f4d38dc288c66bf1458] # # patch "guitone.pro" # from [ed4f11a395873f7e56d5a2fce27975ee0229529b] # to [b4ea319a62403a9ea00c7c7b36ceabf8ea257044] # # patch "res/forms/commit_revision.ui" # from [dabc12f4e7480671991e65797beb5bb131749e8a] # to [470e5fbd3fe58caff240d35dac1ce475dd64dc61] # # patch "res/forms/preferences.ui" # from [0eb67ed1e2105cbb7ec303fcc3ca6ea10ba24c38] # to [d6c764259d715f6f92b86cb8da6a7191114fb62c] # # patch "src/GuitoneDriver.cpp" # from [c34e02d541545930cfa94b66e1f0ab71665f10b7] # to [425b1ad3ec9d37453807d17761df4cafd4f45dd0] # # patch "src/model/GetRevision.cpp" # from [5fb8d261fa465925f9ab9b61e9f9f6b06ffe9fe6] # to [95014c1468ada6b5e60ed31407eec63f1a50975b] # # patch "src/model/GetRevision.h" # from [77d9a435709a6ec72e7b5d2fd25286135a3cc3d6] # to [4a9baf972e663e6034bd88bb4809ef84f39686e1] # # patch "src/view/dialogs/CommitRevision.cpp" # from [4972994d53c31cbd7276f5bb9f3eea56497dbcec] # to [91edc558e873b06025c97375fdabcfa3fe4c369a] # # patch "src/view/dialogs/Preferences.cpp" # from [636f7a602361ad7a73b17a4a80645bfee7393739] # to [36ea0bf13de6bbf6e5478a37d9bf75e243a0c1cd] # ============================================================ --- src/view/ChangeLogEdit.cpp 1c068b2fb8e467c4a0a6e13f5854a3717cf2f738 +++ src/view/ChangeLogEdit.cpp 1c068b2fb8e467c4a0a6e13f5854a3717cf2f738 @@ -0,0 +1,141 @@ +/*************************************************************************** + * Copyright (C) 2008 by Thomas Keller * + * address@hidden * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + ***************************************************************************/ + +#include "ChangeLogEdit.h" +#include "vocab.h" + +#include +#include + +ChangeLogEdit::ChangeLogEdit(QWidget * parent) + : QTextEdit(parent), completionEnabled(false) +{ + completer = new QCompleter(); + completer->setWidget(this); + completer->setCompletionMode(QCompleter::PopupCompletion); + completer->setCaseSensitivity(Qt::CaseInsensitive); + completer->setModelSorting(QCompleter::CaseInsensitivelySortedModel); + completer->setWrapAround(false); + + connect( + completer, SIGNAL(activated(const QString &)), + this, SLOT(insertCompletion(const QString &)) + ); +} + +ChangeLogEdit::~ChangeLogEdit() +{ + delete completer; +} + +void ChangeLogEdit::setCompleterStrings(const QStringList & strings) +{ + if (completer->model()) + { + delete completer->model(); + } + + if (strings.size() > 0) + { + completer->setModel(new QStringListModel(strings, completer)); + completionEnabled = true; + } +} + +void ChangeLogEdit::insertCompletion(const QString & completion) +{ + QTextCursor tc = textCursor(); + int extra = completion.length() - completer->completionPrefix().length(); + + tc.movePosition(QTextCursor::Left); + tc.movePosition(QTextCursor::EndOfWord); + tc.insertText(completion.right(extra)); + + setTextCursor(tc); +} + +QString ChangeLogEdit::textUnderCursor() const +{ + QTextCursor tc = textCursor(); + tc.select(QTextCursor::WordUnderCursor); + return tc.selectedText(); +} + +void ChangeLogEdit::keyPressEvent(QKeyEvent * e) +{ + if (!completionEnabled) + { + QTextEdit::keyPressEvent(e); + return; + } + + if (completer->popup()->isVisible()) + { + // The following keys are forwarded by the completer to the widget + switch (e->key()) + { + case Qt::Key_Enter: + case Qt::Key_Return: + case Qt::Key_Escape: + case Qt::Key_Tab: + case Qt::Key_Backtab: + // let the completer do default behavior + e->ignore(); + return; + default: + break; + } + } + + bool isShortcut = (e->modifiers() & Qt::ControlModifier) && + e->key() == Qt::Key_E; + + // dont process the shortcut when we have a completer + if (!isShortcut) + QTextEdit::keyPressEvent(e); + + const bool ctrlOrShift = e->modifiers() & (Qt::ControlModifier | Qt::ShiftModifier); + + static QString eow("address@hidden&*()_+{}|:\"<>?,./;'[]\\-="); // end of word + bool hasModifier = (e->modifiers() != Qt::NoModifier) && !ctrlOrShift; + + QString completionPrefix = textUnderCursor(); + + if (!isShortcut && ( + hasModifier || + e->text().isEmpty() || + completionPrefix.length() < 3 || + eow.contains(e->text().right(1)) + )) + { + completer->popup()->hide(); + return; + } + + if (completionPrefix != completer->completionPrefix()) { + completer->setCompletionPrefix(completionPrefix); + completer->popup()->setCurrentIndex(completer->completionModel()->index(0, 0)); + } + + QRect cr = cursorRect(); + cr.setWidth(completer->popup()->sizeHintForColumn(0) + + completer->popup()->verticalScrollBar()->sizeHint().width()); + + // pop it up! + completer->complete(cr); +} ============================================================ --- src/view/ChangeLogEdit.h 3c9c904f9016a9854b761f4d38dc288c66bf1458 +++ src/view/ChangeLogEdit.h 3c9c904f9016a9854b761f4d38dc288c66bf1458 @@ -0,0 +1,49 @@ +/*************************************************************************** + * Copyright (C) 2008 by Thomas Keller * + * address@hidden * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + ***************************************************************************/ + +#ifndef CHANGE_LOG_EDIT_H +#define CHANGE_LOG_EDIT_H + +#include +#include +#include + +class ChangeLogEdit : public QTextEdit +{ + Q_OBJECT +public: + ChangeLogEdit(QWidget *); + ~ChangeLogEdit(); + +public slots: + void setCompleterStrings(const QStringList &); + +protected: + void keyPressEvent(QKeyEvent *); + +private slots: + void insertCompletion(const QString &); + +private: + QString textUnderCursor() const; + + QCompleter * completer; + bool completionEnabled; +}; + +#endif ============================================================ --- guitone.pro ed4f11a395873f7e56d5a2fce27975ee0229529b +++ guitone.pro b4ea319a62403a9ea00c7c7b36ceabf8ea257044 @@ -27,6 +27,7 @@ HEADERS = src/view/TreeView.h \ src/view/InventoryViewDelegate.h \ src/view/AttributesView.h \ src/view/DiffStatusView.h \ + src/view/ChangeLogEdit.h \ src/view/MenuBar.h \ src/view/DatabaseMenuBar.h \ src/view/WorkspaceMenuBar.h \ @@ -104,6 +105,7 @@ SOURCES += src/view/TreeView.cpp \ src/view/InventoryViewDelegate.cpp \ src/view/AttributesView.cpp \ src/view/DiffStatusView.cpp \ + src/view/ChangeLogEdit.cpp \ src/view/MenuBar.cpp \ src/view/DatabaseMenuBar.cpp \ src/view/WorkspaceMenuBar.cpp \ ============================================================ --- res/forms/commit_revision.ui dabc12f4e7480671991e65797beb5bb131749e8a +++ res/forms/commit_revision.ui 470e5fbd3fe58caff240d35dac1ce475dd64dc61 @@ -5,363 +5,185 @@ 0 0 - 468 - 565 + 417 + 509 Commit revision - - - 6 - - - 9 - - - 9 - - - 9 - - - 9 - + - - - 6 + + + Qt::Vertical - - 0 - - - 0 - - - 0 - - - 0 - - - - - Changes to commit - - - - 6 - - - 9 - - - 9 - - - 9 - - - 9 - - - - - 6 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 6 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Display changes against parent - - - - - - - - - - - - true - - - QAbstractItemView::SingleSelection - - - false - - - false - - - - - - - Double-click on a patch to open the diff dialog. - - - - - - - 6 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - - - - - Changelog entry - - - - 6 - - - 9 - - - 9 - - - 9 - - - 9 - - - - - 6 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - 6 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Previous changelog entries - - - - - - - - - - - - - - - - - 6 - - - 0 - - - 0 - - - 0 - - - 0 - + + + Changes to commit + + - - - use alternative branch - - + + + + + Display changes against parent + + + + + + + - - - Qt::Horizontal + + + true - - - 40 - 20 - + + QAbstractItemView::SingleSelection - - - - - + false - - - 0 - 0 - + + false - - - 200 - 0 - - - - - - - - 6 - - - 0 - - - 0 - - - 0 - - - 0 - - + - use alternative author + Double-click on a patch to open the diff dialog. + + + + + Changelog entry + + - - - Qt::Horizontal - - - - 16 - 20 - - - + - - - false - - - - 0 - 0 - - - - - 200 - 0 - - - + + + + + Previous changelog entries + + + + + + + + + + + + + + + + use alternative branch + + - + Qt::Horizontal - - QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok + + + 40 + 20 + + + + + + + false + + + + 0 + 0 + + + + + 200 + 0 + + + + + + + + use alternative author + + + + + + + Qt::Horizontal + + + + 16 + 20 + + + + + + + + false + + + + 0 + 0 + + + + + 200 + 0 + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + @@ -370,6 +192,17 @@ QTreeView
TreeView.h
+ + ChangeLogEdit + QTextEdit +
ChangeLogEdit.h
+
+ + Splitter + QSplitter +
Splitter.h
+ 1 +
============================================================ --- res/forms/preferences.ui 0eb67ed1e2105cbb7ec303fcc3ca6ea10ba24c38 +++ res/forms/preferences.ui d6c764259d715f6f92b86cb8da6a7191114fb62c @@ -5,12 +5,12 @@ 0 0 - 399 - 445 + 446 + 481 - + 0 0 @@ -22,7 +22,8 @@ Preferences - :/icons/guitone.png + + :/icons/guitone.png:/icons/guitone.png false @@ -33,21 +34,6 @@ - - 6 - - - 0 - - - 0 - - - 0 - - - 0 - @@ -131,7 +117,7 @@ Qt::Horizontal - + 40 20 @@ -149,8 +135,8 @@ Miscellaneous - - + + check for updates on application launch @@ -160,7 +146,7 @@ - + read workspace incrementally (faster for big directory trees) @@ -170,65 +156,44 @@ - - + + - ask before opening executable files and files with the -following extensions (comma-separated list): + disable auto-completion in commit dialog - true + false - - - - Qt::Horizontal + + + + ask before opening executable files and files with +the following extensions (comma-separated list): - - QSizePolicy::Fixed + + true - - - 20 - 20 - - - + - + - - - 6 - - - 0 - - - 0 - - - 0 - - - 0 - + Qt::Horizontal - + - 131 - 31 + 0 + 0 @@ -263,7 +228,7 @@ following extensions (comma-separated li cancelButton - + ============================================================ --- src/GuitoneDriver.cpp c34e02d541545930cfa94b66e1f0ab71665f10b7 +++ src/GuitoneDriver.cpp 425b1ad3ec9d37453807d17761df4cafd4f45dd0 @@ -150,15 +150,19 @@ void GuitoneDriver::processCommands() QGenericArgument genArgs[10]; for (int i=0; i #include #include +#include GetRevision::GetRevision(QObject * parent) : QAbstractItemModel(parent), AutomateCommand(0) @@ -365,3 +366,43 @@ QString GetRevision::getCurrentParentRev return currentParentRevision; } +QStringList GetRevision::getPathsForCompletion() const +{ + QSet paths; + QMapIterator > it(revision.changesAgainstParent); + + while (it.hasNext()) + { + it.next(); + foreach (Change ch, it.value()) + { + QStringList fullPaths; + switch (ch.type) + { + case Rename: + fullPaths.push_back(ch.stanza.at(1).vals.at(0)); + case AddDir: + case AddFile: + case Patch: + case Delete: + fullPaths.push_back(ch.stanza.at(0).vals.at(0)); + break; + default: + // ignore attribute changes + break; + } + + foreach (QString path, fullPaths) + { + if (path.isEmpty()) continue; + paths.insert(path); + } + } + } + + QStringList pathList = paths.toList(); + qSort(pathList.begin(), pathList.end()); + + return pathList; +} + ============================================================ --- src/model/GetRevision.h 77d9a435709a6ec72e7b5d2fd25286135a3cc3d6 +++ src/model/GetRevision.h 4a9baf972e663e6034bd88bb4809ef84f39686e1 @@ -153,6 +153,7 @@ public: QMap > getChangedFiles() const; QString getRevisionText() const; QString getCurrentParentRevision() const; + QStringList getPathsForCompletion() const; public slots: void readDatabaseRevision(const DatabaseFile &, const QString &); ============================================================ --- src/view/dialogs/CommitRevision.cpp 4972994d53c31cbd7276f5bb9f3eea56497dbcec +++ src/view/dialogs/CommitRevision.cpp 91edc558e873b06025c97375fdabcfa3fe4c369a @@ -46,11 +46,6 @@ CommitRevision::CommitRevision(QWidget * ); connect( - previousChangelogEntryList, SIGNAL(currentIndexChanged(int)), - this, SLOT(setChangelogEntryFromList(int)) - ); - - connect( changesAgainstParent, SIGNAL(currentIndexChanged(const QString &)), revModel, SLOT(showChangesAgainstParent(const QString &)) ); @@ -70,6 +65,13 @@ void CommitRevision::readWorkspaceRevisi { revModel->readWorkspaceRevision(workspacePath, paths); + // while we're inserting items we don't want to receive these signals + // i.e. we don't want to pre-fill the changelog text + disconnect( + previousChangelogEntryList, SIGNAL(currentIndexChanged(int)), + this, SLOT(setChangelogEntryFromList(int)) + ); + QStringList entries = Settings::getItemList("ChangelogEntries"); QRegExp re("\\s+"); @@ -82,7 +84,12 @@ void CommitRevision::readWorkspaceRevisi shortened = shortened.left(40); previousChangelogEntryList->insertItem(i, shortened, QVariant(entry)); } - previousChangelogEntryList->insertItem(-1, tr("-- select --"), QVariant()); + previousChangelogEntryList->setCurrentIndex(-1); + + connect( + previousChangelogEntryList, SIGNAL(currentIndexChanged(int)), + this, SLOT(setChangelogEntryFromList(int)) + ); } void CommitRevision::setChangelogEntryFromList(int index) @@ -184,8 +191,6 @@ void CommitRevision::accept() selectedKey = key; } - - WorkspaceCommitter committer(workspacePath, revModel); if (!committer.run(selectedKey, branch, author, changelogEntry->toPlainText())) @@ -211,6 +216,11 @@ void CommitRevision::revisionRead() void CommitRevision::revisionRead() { changesAgainstParent->addItems(revModel->getParentRevisions()); + + if (!Settings::getBool("DisableChangelogAutoCompletion", false)) + { + changelogEntry->setCompleterStrings(revModel->getPathsForCompletion()); + } } void CommitRevision::readFailed(const QString & error) ============================================================ --- src/view/dialogs/Preferences.cpp 636f7a602361ad7a73b17a4a80645bfee7393739 +++ src/view/dialogs/Preferences.cpp 36ea0bf13de6bbf6e5478a37d9bf75e243a0c1cd @@ -64,6 +64,11 @@ Preferences::Preferences(QWidget * paren Qt::Checked : Qt::Unchecked ); + disableChangelogAutoCompletion->setCheckState( + Settings::getBool("DisableChangelogAutoCompletion", false) ? + Qt::Checked : Qt::Unchecked + ); + connect( selectMtnExecutable, SIGNAL(clicked()), this, SLOT(openFileBrowser())