summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libs/cplusplus/pp-engine.cpp4
-rw-r--r--src/libs/utils/basevalidatinglineedit.h11
-rw-r--r--src/libs/utils/classnamevalidatinglineedit.cpp7
-rw-r--r--src/libs/utils/filenamevalidatinglineedit.h8
-rw-r--r--src/libs/utils/filewizardpage.cpp14
-rw-r--r--src/libs/utils/filewizardpage.h18
-rw-r--r--src/libs/utils/filewizardpage.ui66
-rw-r--r--src/libs/utils/newclasswidget.h21
-rw-r--r--src/libs/utils/pathchooser.h12
-rw-r--r--src/libs/utils/process_stub_win.c1
-rw-r--r--src/libs/utils/submiteditorwidget.cpp107
-rw-r--r--src/libs/utils/submiteditorwidget.h12
-rw-r--r--src/plugins/bookmarks/bookmarkmanager.cpp3
-rw-r--r--src/plugins/cmakeprojectmanager/makestep.cpp1
-rw-r--r--src/plugins/coreplugin/dialogs/settingsdialog.cpp51
-rw-r--r--src/plugins/coreplugin/dialogs/settingsdialog.h7
-rw-r--r--src/plugins/coreplugin/editormanager/editormanager.cpp50
-rw-r--r--src/plugins/coreplugin/editormanager/editormanager.h2
-rw-r--r--src/plugins/coreplugin/welcomemode.cpp1
-rw-r--r--src/plugins/cppeditor/cppeditor.cpp3
-rw-r--r--src/plugins/debugger/debuggeractions.cpp5
-rw-r--r--src/plugins/debugger/debuggeractions.h1
-rw-r--r--src/plugins/debugger/debuggerplugin.cpp5
-rw-r--r--src/plugins/debugger/gdboptionpage.ui20
-rw-r--r--src/plugins/debugger/watchhandler.cpp3
-rw-r--r--src/plugins/debugger/watchhandler.h2
-rw-r--r--src/plugins/debugger/watchwindow.cpp20
-rw-r--r--src/plugins/fakevim/fakevimconstants.h7
-rw-r--r--src/plugins/fakevim/fakevimhandler.cpp138
-rw-r--r--src/plugins/genericprojectmanager/genericproject.cpp71
-rw-r--r--src/plugins/genericprojectmanager/genericproject.h14
-rw-r--r--src/plugins/genericprojectmanager/genericprojectmanager.cpp12
-rw-r--r--src/plugins/genericprojectmanager/genericprojectnodes.cpp8
-rw-r--r--src/plugins/genericprojectmanager/genericprojectnodes.h6
-rw-r--r--src/plugins/genericprojectmanager/genericprojectwizard.cpp35
-rw-r--r--src/plugins/genericprojectmanager/genericprojectwizard.h26
-rw-r--r--src/plugins/git/gitplugin.cpp19
-rw-r--r--src/plugins/git/gitplugin.h1
-rw-r--r--src/plugins/git/gitsubmitpanel.ui57
-rw-r--r--src/plugins/perforce/perforceplugin.cpp35
-rw-r--r--src/plugins/perforce/perforceplugin.h3
-rw-r--r--src/plugins/projectexplorer/environment.cpp12
-rw-r--r--src/plugins/projectexplorer/environment.h2
-rw-r--r--src/plugins/projectexplorer/toolchain.cpp12
-rw-r--r--src/plugins/projectexplorer/toolchain.h1
-rw-r--r--src/plugins/qt4projectmanager/qt4nodes.h9
-rw-r--r--src/plugins/qt4projectmanager/qt4project.h6
-rw-r--r--src/plugins/qt4projectmanager/qt4runconfiguration.cpp5
-rw-r--r--src/plugins/qt4projectmanager/qtversionmanager.cpp5
-rw-r--r--src/plugins/subversion/subversionplugin.cpp21
-rw-r--r--src/plugins/subversion/subversionplugin.h1
-rw-r--r--src/plugins/texteditor/basetexteditor.cpp25
-rw-r--r--src/plugins/texteditor/basetexteditor.h3
-rw-r--r--src/plugins/texteditor/basetexteditor_p.h1
-rw-r--r--src/plugins/texteditor/linenumberfilter.cpp3
-rw-r--r--src/plugins/vcsbase/nicknamedialog.cpp270
-rw-r--r--src/plugins/vcsbase/nicknamedialog.h83
-rw-r--r--src/plugins/vcsbase/nicknamedialog.ui117
-rw-r--r--src/plugins/vcsbase/vcsbase.pro17
-rw-r--r--src/plugins/vcsbase/vcsbaseconstants.h1
-rw-r--r--src/plugins/vcsbase/vcsbaseeditor.cpp3
-rw-r--r--src/plugins/vcsbase/vcsbaseplugin.cpp11
-rw-r--r--src/plugins/vcsbase/vcsbaseplugin.h6
-rw-r--r--src/plugins/vcsbase/vcsbasesettings.cpp78
-rw-r--r--src/plugins/vcsbase/vcsbasesettings.h66
-rw-r--r--src/plugins/vcsbase/vcsbasesettingspage.cpp145
-rw-r--r--src/plugins/vcsbase/vcsbasesettingspage.h86
-rw-r--r--src/plugins/vcsbase/vcsbasesettingspage.ui116
-rw-r--r--src/plugins/vcsbase/vcsbasesubmiteditor.cpp191
-rw-r--r--src/plugins/vcsbase/vcsbasesubmiteditor.h21
70 files changed, 1868 insertions, 336 deletions
diff --git a/src/libs/cplusplus/pp-engine.cpp b/src/libs/cplusplus/pp-engine.cpp
index 95effec40c..1fee419252 100644
--- a/src/libs/cplusplus/pp-engine.cpp
+++ b/src/libs/cplusplus/pp-engine.cpp
@@ -1,5 +1,4 @@
-/**************************************************************************
-**
+/**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
@@ -51,6 +50,7 @@
#include <Lexer.h>
#include <Token.h>
#include <Literals.h>
+#include <cctype>
#include <QtDebug>
#include <algorithm>
diff --git a/src/libs/utils/basevalidatinglineedit.h b/src/libs/utils/basevalidatinglineedit.h
index 9dd8f8ec56..a57d04b49a 100644
--- a/src/libs/utils/basevalidatinglineedit.h
+++ b/src/libs/utils/basevalidatinglineedit.h
@@ -39,7 +39,8 @@ namespace Utils {
struct BaseValidatingLineEditPrivate;
-/* Base class for validating line edits that performs validation in a virtual
+/**
+ * Base class for validating line edits that performs validation in a virtual
* validate() function to be implemented in derived classes.
* When invalid, the text color will turn red and a tooltip will
* contain the error message. This approach is less intrusive than a
@@ -47,9 +48,10 @@ struct BaseValidatingLineEditPrivate;
*
* The widget has a concept of an "initialText" which can be something like
* "<Enter name here>". This results in state 'DisplayingInitialText', which
- * is not valid, but is not marked red. */
-
-class QWORKBENCH_UTILS_EXPORT BaseValidatingLineEdit : public QLineEdit {
+ * is not valid, but is not marked red.
+ */
+class QWORKBENCH_UTILS_EXPORT BaseValidatingLineEdit : public QLineEdit
+{
Q_OBJECT
Q_DISABLE_COPY(BaseValidatingLineEdit)
Q_PROPERTY(QString initialText READ initialText WRITE setInitialText DESIGNABLE true)
@@ -97,4 +99,5 @@ private:
} // namespace Utils
} // namespace Core
+
#endif // BASEVALIDATINGLINEEDIT_H
diff --git a/src/libs/utils/classnamevalidatinglineedit.cpp b/src/libs/utils/classnamevalidatinglineedit.cpp
index 86f86a124d..64d2031a57 100644
--- a/src/libs/utils/classnamevalidatinglineedit.cpp
+++ b/src/libs/utils/classnamevalidatinglineedit.cpp
@@ -84,8 +84,11 @@ bool ClassNameValidatingLineEdit::validate(const QString &value, QString *errorM
if (errorMessage)
*errorMessage = tr("The class name must not contain namespace delimiters.");
return false;
- }
- if (!m_d->m_nameRegexp.exactMatch(value)) {
+ } else if (value.isEmpty()) {
+ if (errorMessage)
+ *errorMessage = tr("Please enter a class name.");
+ return false;
+ } else if (!m_d->m_nameRegexp.exactMatch(value)) {
if (errorMessage)
*errorMessage = tr("The class name contains invalid characters.");
return false;
diff --git a/src/libs/utils/filenamevalidatinglineedit.h b/src/libs/utils/filenamevalidatinglineedit.h
index cf37757175..60145bdf4c 100644
--- a/src/libs/utils/filenamevalidatinglineedit.h
+++ b/src/libs/utils/filenamevalidatinglineedit.h
@@ -35,6 +35,10 @@
namespace Core {
namespace Utils {
+/**
+ * A control that let's the user choose a file name, based on a QLineEdit. Has
+ * some validation logic for embedding into QWizardPage.
+ */
class QWORKBENCH_UTILS_EXPORT FileNameValidatingLineEdit : public BaseValidatingLineEdit
{
Q_OBJECT
@@ -47,6 +51,10 @@ public:
bool allowDirectories = false,
QString *errorMessage = 0);
+ /**
+ * Sets whether entering directories is allowed. This will enable the user
+ * to enter slashes in the filename. Default is off.
+ */
bool allowDirectories() const;
void setAllowDirectories(bool v);
diff --git a/src/libs/utils/filewizardpage.cpp b/src/libs/utils/filewizardpage.cpp
index 59f1bbc56b..3fb0b79b8c 100644
--- a/src/libs/utils/filewizardpage.cpp
+++ b/src/libs/utils/filewizardpage.cpp
@@ -30,10 +30,6 @@
#include "filewizardpage.h"
#include "ui_filewizardpage.h"
-#include <QtCore/QDebug>
-#include <QtCore/QDir>
-#include <QtGui/QMessageBox>
-
namespace Core {
namespace Utils {
@@ -103,6 +99,16 @@ bool FileWizardPage::isComplete() const
return m_d->m_complete;
}
+void FileWizardPage::setNameLabel(const QString &label)
+{
+ m_d->m_ui.nameLabel->setText(label);
+}
+
+void FileWizardPage::setPathLabel(const QString &label)
+{
+ m_d->m_ui.pathLabel->setText(label);
+}
+
void FileWizardPage::slotValidChanged()
{
const bool newComplete = m_d->m_ui.pathChooser->isValid() && m_d->m_ui.nameLineEdit->isValid();
diff --git a/src/libs/utils/filewizardpage.h b/src/libs/utils/filewizardpage.h
index 657ec4f4ef..b41839e0bf 100644
--- a/src/libs/utils/filewizardpage.h
+++ b/src/libs/utils/filewizardpage.h
@@ -39,10 +39,15 @@ namespace Utils {
struct FileWizardPagePrivate;
-/* Standard wizard page for a single file letting the user choose name
- * and path. Sets the "FileNames" QWizard field. */
-
-class QWORKBENCH_UTILS_EXPORT FileWizardPage : public QWizardPage {
+/**
+ * Standard wizard page for a single file letting the user choose name
+ * and path. Sets the "FileNames" QWizard field.
+ *
+ * The name and path labels can be changed. By default they are simply "Name:"
+ * and "Path:".
+ */
+class QWORKBENCH_UTILS_EXPORT FileWizardPage : public QWizardPage
+{
Q_OBJECT
Q_DISABLE_COPY(FileWizardPage)
Q_PROPERTY(QString path READ path WRITE setPath DESIGNABLE true)
@@ -56,7 +61,10 @@ public:
virtual bool isComplete() const;
- // Validate a base name entry field (potentially containing extension)
+ void setNameLabel(const QString &label);
+ void setPathLabel(const QString &label);
+
+ // Validate a base name entry field (potentially containing extension)
static bool validateBaseName(const QString &name, QString *errorMessage = 0);
signals:
diff --git a/src/libs/utils/filewizardpage.ui b/src/libs/utils/filewizardpage.ui
index 2e614c6f55..98d0873128 100644
--- a/src/libs/utils/filewizardpage.ui
+++ b/src/libs/utils/filewizardpage.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>400</width>
- <height>300</height>
+ <width>196</width>
+ <height>68</height>
</rect>
</property>
<property name="windowTitle">
@@ -16,52 +16,26 @@
<property name="title">
<string>Choose the location</string>
</property>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <widget class="QWidget" name="widget" native="true">
- <layout class="QFormLayout" name="formLayout">
- <property name="fieldGrowthPolicy">
- <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
- </property>
- <item row="0" column="0">
- <widget class="QLabel" name="nameLabel">
- <property name="text">
- <string>Name:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="Core::Utils::FileNameValidatingLineEdit" name="nameLineEdit"/>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="pathLabel">
- <property name="text">
- <string>Path:</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="Core::Utils::PathChooser" name="pathChooser" native="true"/>
- </item>
- </layout>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
+ <layout class="QFormLayout" name="formLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="nameLabel">
+ <property name="text">
+ <string>Name:</string>
</property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>201</height>
- </size>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="Core::Utils::FileNameValidatingLineEdit" name="nameLineEdit"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="pathLabel">
+ <property name="text">
+ <string>Path:</string>
</property>
- </spacer>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="Core::Utils::PathChooser" name="pathChooser" native="true"/>
</item>
</layout>
</widget>
diff --git a/src/libs/utils/newclasswidget.h b/src/libs/utils/newclasswidget.h
index 15b21fcb0e..674adf6c84 100644
--- a/src/libs/utils/newclasswidget.h
+++ b/src/libs/utils/newclasswidget.h
@@ -43,11 +43,12 @@ namespace Utils {
struct NewClassWidgetPrivate;
-/* NewClassWidget: Utility widget for 'New Class' wizards. Prompts the user
+/**
+ * NewClassWidget: Utility widget for 'New Class' wizards. Prompts the user
* to enter a class name (optionally derived from some base class) and file
* names for header, source and form files. Has some smart logic to derive
- * the file names from the class name. */
-
+ * the file names from the class name.
+ */
class QWORKBENCH_UTILS_EXPORT NewClassWidget : public QWidget
{
Q_DISABLE_COPY(NewClassWidget)
@@ -115,8 +116,10 @@ public slots:
void setFormInputCheckable(bool v);
void setFormInputChecked(bool v);
- /* The name passed into the new class widget will be reformatted to be a
- * valid class name. */
+ /**
+ * The name passed into the new class widget will be reformatted to be a
+ * valid class name.
+ */
void setClassName(const QString &suggestedName);
void setBaseClassName(const QString &);
void setPath(const QString &path);
@@ -127,13 +130,15 @@ public slots:
void setAllowDirectories(bool v);
void setLowerCaseFiles(bool v);
- /* Suggest a class name from the base class by stripping the leading 'Q'
+ /**
+ * Suggest a class name from the base class by stripping the leading 'Q'
* character. This will happen automagically if the base class combo
- * changes until the class line edited is manually edited. */
+ * changes until the class line edited is manually edited.
+ */
void suggestClassNameFromBase();
public slots:
- // Trigger an update (after changing settings)
+ /** Trigger an update (after changing settings) */
void triggerUpdateFileNames();
private slots:
diff --git a/src/libs/utils/pathchooser.h b/src/libs/utils/pathchooser.h
index 99f2330371..04607ef700 100644
--- a/src/libs/utils/pathchooser.h
+++ b/src/libs/utils/pathchooser.h
@@ -39,10 +39,10 @@ namespace Utils {
struct PathChooserPrivate;
-/* A Control that let's the user choose a path, consisting of a QLineEdit and
- * a "Browse" button. Has some validation logic for embedding into
- * QWizardPage. */
-
+/**
+ * A control that let's the user choose a path, consisting of a QLineEdit and
+ * a "Browse" button. Has some validation logic for embedding into QWizardPage.
+ */
class QWORKBENCH_UTILS_EXPORT PathChooser : public QWidget
{
Q_DISABLE_COPY(PathChooser)
@@ -74,12 +74,12 @@ public:
QString path() const;
- // Returns the suggested label title when used in a form layout
+ /** Returns the suggested label title when used in a form layout. */
static QString label();
virtual bool validatePath(const QString &path, QString *errorMessage = 0);
- // Return the home directory, which needs some fixing under Windows.
+ /** Return the home directory, which needs some fixing under Windows. */
static QString homePath();
private:
diff --git a/src/libs/utils/process_stub_win.c b/src/libs/utils/process_stub_win.c
index 3d99a68539..0ca484eb75 100644
--- a/src/libs/utils/process_stub_win.c
+++ b/src/libs/utils/process_stub_win.c
@@ -34,6 +34,7 @@
#define _WIN32_WINNT 0x0501 /* WinXP, needed for DebugActiveProcessStop() */
#include <windows.h>
+#include <shellapi.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
diff --git a/src/libs/utils/submiteditorwidget.cpp b/src/libs/utils/submiteditorwidget.cpp
index a047682b81..b9c8259020 100644
--- a/src/libs/utils/submiteditorwidget.cpp
+++ b/src/libs/utils/submiteditorwidget.cpp
@@ -33,8 +33,15 @@
#include <QtCore/QDebug>
#include <QtCore/QPointer>
#include <QtCore/QTimer>
+#include <QtCore/QSignalMapper>
#include <QtGui/QPushButton>
+#include <QtGui/QMenu>
+#include <QtGui/QLineEdit>
+#include <QtGui/QFormLayout>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QToolButton>
+#include <QtGui/QSpacerItem>
enum { debug = 0 };
@@ -104,8 +111,12 @@ QList<int> selectedRows(const QAbstractItemView *view)
}
// ----------- SubmitEditorWidgetPrivate
+
struct SubmitEditorWidgetPrivate
{
+ // A pair of position/action to extend context menus
+ typedef QPair<int, QPointer<QAction> > AdditionalContextMenuAction;
+
SubmitEditorWidgetPrivate();
Ui::SubmitEditorWidget m_ui;
@@ -113,13 +124,22 @@ struct SubmitEditorWidgetPrivate
bool m_filesChecked;
int m_fileNameColumn;
int m_activatedRow;
+
+ QList<AdditionalContextMenuAction> descriptionEditContextMenuActions;
+ QFormLayout *m_fieldLayout;
+ // Field entries (label, line edits)
+ typedef QPair<QString, QLineEdit*> FieldEntry;
+ QList<FieldEntry> m_fieldEntries;
+ QSignalMapper *m_fieldSignalMapper;
};
SubmitEditorWidgetPrivate::SubmitEditorWidgetPrivate() :
m_filesSelected(false),
m_filesChecked(false),
m_fileNameColumn(1),
- m_activatedRow(-1)
+ m_activatedRow(-1),
+ m_fieldLayout(0),
+ m_fieldSignalMapper(0)
{
}
@@ -128,6 +148,10 @@ SubmitEditorWidget::SubmitEditorWidget(QWidget *parent) :
m_d(new SubmitEditorWidgetPrivate)
{
m_d->m_ui.setupUi(this);
+ m_d->m_ui.description->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(m_d->m_ui.description, SIGNAL(customContextMenuRequested(QPoint)),
+ this, SLOT(editorCustomContextMenuRequested(QPoint)));
+
// File List
m_d->m_ui.fileView->setSelectionMode(QAbstractItemView::ExtendedSelection);
m_d->m_ui.fileView->setRootIsDecorated(false);
@@ -212,7 +236,18 @@ QString SubmitEditorWidget::trimmedDescriptionText() const
QString SubmitEditorWidget::descriptionText() const
{
- return m_d->m_ui.description->toPlainText();
+ QString rc = m_d->m_ui.description->toPlainText();
+ // append field entries
+ foreach(const SubmitEditorWidgetPrivate::FieldEntry &fe, m_d->m_fieldEntries) {
+ const QString fieldText = fe.second->text().trimmed();
+ if (!fieldText.isEmpty()) {
+ rc += fe.first;
+ rc += QLatin1Char(' ');
+ rc += fieldText;
+ rc += QLatin1Char('\n');
+ }
+ }
+ return rc;
}
void SubmitEditorWidget::setDescriptionText(const QString &text)
@@ -381,6 +416,74 @@ void SubmitEditorWidget::insertTopWidget(QWidget *w)
m_d->m_ui.vboxLayout->insertWidget(0, w);
}
+void SubmitEditorWidget::addDescriptionEditContextMenuAction(QAction *a)
+{
+ m_d->descriptionEditContextMenuActions.push_back(SubmitEditorWidgetPrivate::AdditionalContextMenuAction(-1, a));
+}
+
+void SubmitEditorWidget::insertDescriptionEditContextMenuAction(int pos, QAction *a)
+{
+ m_d->descriptionEditContextMenuActions.push_back(SubmitEditorWidgetPrivate::AdditionalContextMenuAction(pos, a));
+}
+
+void SubmitEditorWidget::editorCustomContextMenuRequested(const QPoint &pos)
+{
+ QMenu *menu = m_d->m_ui.description->createStandardContextMenu();
+ // Extend
+ foreach (const SubmitEditorWidgetPrivate::AdditionalContextMenuAction &a, m_d->descriptionEditContextMenuActions) {
+ if (a.second) {
+ if (a.first >= 0) {
+ menu->insertAction(menu->actions().at(a.first), a.second);
+ } else {
+ menu->addAction(a.second);
+ }
+ }
+ }
+ menu->exec(m_d->m_ui.description->mapToGlobal(pos));
+ delete menu;
+}
+
+QLineEdit *SubmitEditorWidget::addField(const QString &label, bool hasDialogButton)
+{
+ // Insert the form layout below the editor
+ if (!m_d->m_fieldLayout) {
+ QHBoxLayout *outerLayout = new QHBoxLayout;
+ m_d->m_fieldLayout = new QFormLayout;
+ outerLayout->addLayout(m_d->m_fieldLayout);
+ outerLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Ignored));
+ QBoxLayout *descrLayout = qobject_cast<QBoxLayout*>(m_d->m_ui.descriptionBox->layout());
+ Q_ASSERT(descrLayout);
+ descrLayout->addLayout(outerLayout);
+ }
+ if (hasDialogButton && !m_d->m_fieldSignalMapper) {
+ m_d->m_fieldSignalMapper = new QSignalMapper;
+ connect(m_d->m_fieldSignalMapper, SIGNAL(mapped(int)), this, SIGNAL(fieldDialogRequested(int)));
+ }
+ // Add a field row consisting of label and line edit
+ QLineEdit *lineEdit = new QLineEdit;
+ QHBoxLayout *fieldLayout = new QHBoxLayout;
+ fieldLayout->addWidget(lineEdit);
+ if (hasDialogButton) {
+ QToolButton *dialogButton = new QToolButton;
+ dialogButton->setText(tr("..."));
+ connect(dialogButton, SIGNAL(clicked()), m_d->m_fieldSignalMapper, SLOT(map()));
+ m_d->m_fieldSignalMapper->setMapping(dialogButton, m_d->m_fieldEntries.size());
+ fieldLayout->addWidget(dialogButton);
+ }
+ QToolButton *clearButton = new QToolButton;
+ clearButton->setText(tr("Clear"));
+ connect(clearButton, SIGNAL(clicked()), lineEdit, SLOT(clear()));
+ fieldLayout->addWidget(clearButton);
+ m_d->m_fieldLayout->addRow(label, fieldLayout);
+ m_d->m_fieldEntries.push_back(SubmitEditorWidgetPrivate::FieldEntry(label, lineEdit));
+ return lineEdit;
+}
+
+QLineEdit *SubmitEditorWidget::fieldLineEdit(int i) const
+{
+ return m_d->m_fieldEntries.at(i).second;
+}
+
} // namespace Utils
} // namespace Core
diff --git a/src/libs/utils/submiteditorwidget.h b/src/libs/utils/submiteditorwidget.h
index 74dd56d006..e77da4379e 100644
--- a/src/libs/utils/submiteditorwidget.h
+++ b/src/libs/utils/submiteditorwidget.h
@@ -41,6 +41,7 @@ class QListWidgetItem;
class QAction;
class QAbstractItemModel;
class QModelIndex;
+class QLineEdit;
QT_END_NAMESPACE
namespace Core {
@@ -104,10 +105,20 @@ public:
QPlainTextEdit *descriptionEdit() const;
+ void addDescriptionEditContextMenuAction(QAction *a);
+ void insertDescriptionEditContextMenuAction(int pos, QAction *a);
+
+ // Fields are additional fields consisting of a Label and a Line Edit.
+ // A field dialog is wired to a button labeled "..." that pops up a chooser
+ // resulting in text being set
+ QLineEdit *addField(const QString &label, bool hasDialogButton);
+ QLineEdit *fieldLineEdit(int i) const;
+
signals:
void diffSelected(const QStringList &);
void fileSelectionChanged(bool someFileSelected);
void fileCheckStateChanged(bool someFileChecked);
+ void fieldDialogRequested(int);
protected:
virtual void changeEvent(QEvent *e);
@@ -120,6 +131,7 @@ private slots:
void updateActions();
void updateSubmitAction();
void updateDiffAction();
+ void editorCustomContextMenuRequested(const QPoint &);
private:
bool hasSelection() const;
diff --git a/src/plugins/bookmarks/bookmarkmanager.cpp b/src/plugins/bookmarks/bookmarkmanager.cpp
index 4954cad38e..6e079a23e7 100644
--- a/src/plugins/bookmarks/bookmarkmanager.cpp
+++ b/src/plugins/bookmarks/bookmarkmanager.cpp
@@ -501,7 +501,7 @@ void BookmarkManager::documentPrevNext(bool next)
}
Core::EditorManager *em = Core::EditorManager::instance();
- em->addCurrentPositionToNavigationHistory(true);
+ em->addCurrentPositionToNavigationHistory();
if (next) {
if (nextLine == -1)
editor->gotoLine(firstLine);
@@ -513,7 +513,6 @@ void BookmarkManager::documentPrevNext(bool next)
else
editor->gotoLine(prevLine);
}
- em->addCurrentPositionToNavigationHistory();
}
void BookmarkManager::next()
diff --git a/src/plugins/cmakeprojectmanager/makestep.cpp b/src/plugins/cmakeprojectmanager/makestep.cpp
index d7544b62e5..8417e842af 100644
--- a/src/plugins/cmakeprojectmanager/makestep.cpp
+++ b/src/plugins/cmakeprojectmanager/makestep.cpp
@@ -202,7 +202,6 @@ void MakeStep::removeDirectory(const QString &dir)
m_openDirectories.remove(dir);
}
-
CMakeProject *MakeStep::project() const
{
return m_pro;
diff --git a/src/plugins/coreplugin/dialogs/settingsdialog.cpp b/src/plugins/coreplugin/dialogs/settingsdialog.cpp
index 5e0cac944e..195325bceb 100644
--- a/src/plugins/coreplugin/dialogs/settingsdialog.cpp
+++ b/src/plugins/coreplugin/dialogs/settingsdialog.cpp
@@ -30,18 +30,37 @@
#include "settingsdialog.h"
#include <extensionsystem/pluginmanager.h>
+#include "icore.h"
+#include <QtCore/QSettings>
#include <QtGui/QHeaderView>
#include <QtGui/QPushButton>
+namespace {
+ struct PageData {
+ int index;
+ QString category;
+ QString id;
+ };
+}
+
+Q_DECLARE_METATYPE(::PageData);
+
using namespace Core;
using namespace Core::Internal;
-SettingsDialog::SettingsDialog(QWidget *parent, const QString &initialCategory,
- const QString &initialPage)
+SettingsDialog::SettingsDialog(QWidget *parent, const QString &categoryId,
+ const QString &pageId)
: QDialog(parent), m_applied(false)
{
setupUi(this);
+ QString initialCategory = categoryId;
+ QString initialPage = pageId;
+ if (initialCategory.isEmpty() && initialPage.isEmpty()) {
+ QSettings *settings = ICore::instance()->settings();
+ initialCategory = settings->value("General/LastPreferenceCategory", QVariant(QString())).toString();
+ initialPage = settings->value("General/LastPreferencePage", QVariant(QString())).toString();
+ }
buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
connect(buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), this, SLOT(apply()));
@@ -50,7 +69,7 @@ SettingsDialog::SettingsDialog(QWidget *parent, const QString &initialCategory,
pageTree->header()->setVisible(false);
connect(pageTree, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
- this, SLOT(pageSelected(QTreeWidgetItem *)));
+ this, SLOT(pageSelected()));
QMap<QString, QTreeWidgetItem *> categories;
@@ -59,9 +78,14 @@ SettingsDialog::SettingsDialog(QWidget *parent, const QString &initialCategory,
int index = 0;
foreach (IOptionsPage *page, pages) {
+ PageData pageData;
+ pageData.index = index;
+ pageData.category = page->category();
+ pageData.id = page->id();
+
QTreeWidgetItem *item = new QTreeWidgetItem;
item->setText(0, page->trName());
- item->setData(0, Qt::UserRole, index);
+ item->setData(0, Qt::UserRole, qVariantFromValue(pageData));
QStringList categoriesId = page->category().split(QLatin1Char('|'));
QStringList trCategories = page->trCategory().split(QLatin1Char('|'));
@@ -71,7 +95,7 @@ SettingsDialog::SettingsDialog(QWidget *parent, const QString &initialCategory,
if (!categories.contains(currentCategory)) {
treeitem = new QTreeWidgetItem(pageTree);
treeitem->setText(0, trCategories.at(0));
- treeitem->setData(0, Qt::UserRole, index);
+ treeitem->setData(0, Qt::UserRole, qVariantFromValue(pageData));
categories.insert(currentCategory, treeitem);
}
@@ -81,7 +105,7 @@ SettingsDialog::SettingsDialog(QWidget *parent, const QString &initialCategory,
treeitem = new QTreeWidgetItem(categories.value(currentCategory));
currentCategory += QLatin1Char('|') + categoriesId.at(catCount);
treeitem->setText(0, trCategories.at(catCount));
- treeitem->setData(0, Qt::UserRole, index);
+ treeitem->setData(0, Qt::UserRole, qVariantFromValue(pageData));
categories.insert(currentCategory, treeitem);
} else {
currentCategory += QLatin1Char('|') + categoriesId.at(catCount);
@@ -114,10 +138,13 @@ SettingsDialog::~SettingsDialog()
{
}
-void SettingsDialog::pageSelected(QTreeWidgetItem *)
+void SettingsDialog::pageSelected()
{
QTreeWidgetItem *item = pageTree->currentItem();
- int index = item->data(0, Qt::UserRole).toInt();
+ PageData data = item->data(0, Qt::UserRole).value<PageData>();
+ int index = data.index;
+ m_currentCategory = data.category;
+ m_currentPage = data.id;
stackedPages->setCurrentIndex(index);
}
@@ -151,3 +178,11 @@ bool SettingsDialog::execDialog()
exec();
return m_applied;
}
+
+void SettingsDialog::done(int val)
+{
+ QSettings *settings = ICore::instance()->settings();
+ settings->setValue("General/LastPreferenceCategory", m_currentCategory);
+ settings->setValue("General/LastPreferencePage", m_currentPage);
+ QDialog::done(val);
+}
diff --git a/src/plugins/coreplugin/dialogs/settingsdialog.h b/src/plugins/coreplugin/dialogs/settingsdialog.h
index 36c7d8a1a6..88f0a7a5ab 100644
--- a/src/plugins/coreplugin/dialogs/settingsdialog.h
+++ b/src/plugins/coreplugin/dialogs/settingsdialog.h
@@ -53,8 +53,11 @@ public:
// at least once
bool execDialog();
+public slots:
+ void done(int);
+
private slots:
- void pageSelected(QTreeWidgetItem *cat);
+ void pageSelected();
void accept();
void reject();
void apply();
@@ -62,6 +65,8 @@ private slots:
private:
QList<Core::IOptionsPage*> m_pages;
bool m_applied;
+ QString m_currentCategory;
+ QString m_currentPage;
};
} // namespace Internal
diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp
index 6cfec71e0f..8badefeb9a 100644
--- a/src/plugins/coreplugin/editormanager/editormanager.cpp
+++ b/src/plugins/coreplugin/editormanager/editormanager.cpp
@@ -190,7 +190,7 @@ EditorManagerPrivate::EditorManagerPrivate(ICore *core, QWidget *parent) :
m_goBackAction(new QAction(EditorManager::tr("Go back"), parent)),
m_goForwardAction(new QAction(EditorManager::tr("Go forward"), parent)),
m_openInExternalEditorAction(new QAction(EditorManager::tr("Open in External Editor"), parent)),
- currentNavigationHistoryPosition(-1),
+ currentNavigationHistoryPosition(0),
m_windowPopup(0),
m_coreListener(0)
{
@@ -473,15 +473,11 @@ void EditorManager::setCurrentEditor(IEditor *editor, bool ignoreNavigationHisto
setCurrentView(0);
if (m_d->m_currentEditor == editor)
return;
- if (m_d->m_currentEditor)
- updateCurrentPositionInNavigationHistory();
+ if (m_d->m_currentEditor && !ignoreNavigationHistory)
+ addCurrentPositionToNavigationHistory();
m_d->m_currentEditor = editor;
if (editor) {
- bool addToHistory = (!ignoreNavigationHistory);
- if (addToHistory)
- addCurrentPositionToNavigationHistory(true);
-
if (SplitterOrView *splitterOrView = m_d->m_splitter->findView(editor))
splitterOrView->view()->setCurrentEditor(editor);
}
@@ -723,8 +719,8 @@ bool EditorManager::closeEditors(const QList<IEditor*> editorsToClose, bool askA
}
}
-
emit editorsClosed(acceptedEditors);
+
foreach (IEditor *editor, acceptedEditors) {
delete editor;
}
@@ -1362,7 +1358,7 @@ QList<IEditor*> EditorManager::editorHistory() const
return m_d->m_editorHistory;
}
-void EditorManager::addCurrentPositionToNavigationHistory(bool compress)
+void EditorManager::addCurrentPositionToNavigationHistory(const QByteArray &saveState, bool compress)
{
IEditor *editor = currentEditor();
if (!editor)
@@ -1371,20 +1367,25 @@ void EditorManager::addCurrentPositionToNavigationHistory(bool compress)
return;
QString fileName = editor->file()->fileName();
- QByteArray state = editor->saveState();
+ QByteArray state;
+ if (saveState.isNull()) {
+ state = editor->saveState();
+ } else {
+ state = saveState;
+ }
// cut existing
int firstIndexToRemove;
- if (compress && m_d->currentNavigationHistoryPosition >= 0) {
+ if (compress && m_d->currentNavigationHistoryPosition > 0) {
EditorManagerPrivate::EditLocation *previousLocation =
- m_d->m_navigationHistory.at(m_d->currentNavigationHistoryPosition);
+ m_d->m_navigationHistory.at(m_d->currentNavigationHistoryPosition-1);
if ((previousLocation->editor && editor == previousLocation->editor)
|| (!fileName.isEmpty() && previousLocation->fileName == fileName)) {
- firstIndexToRemove = m_d->currentNavigationHistoryPosition;
+ firstIndexToRemove = m_d->currentNavigationHistoryPosition-1;
} else {
- firstIndexToRemove = m_d->currentNavigationHistoryPosition+1;
+ firstIndexToRemove = m_d->currentNavigationHistoryPosition;
}
} else {
- firstIndexToRemove = m_d->currentNavigationHistoryPosition+1;
+ firstIndexToRemove = m_d->currentNavigationHistoryPosition;
}
if (firstIndexToRemove >= 0) {
for (int i = m_d->m_navigationHistory.size()-1; i >= firstIndexToRemove; --i) {
@@ -1400,17 +1401,26 @@ void EditorManager::addCurrentPositionToNavigationHistory(bool compress)
location->kind = editor->kind();
location->state = QVariant(state);
m_d->m_navigationHistory.append(location);
- m_d->currentNavigationHistoryPosition = m_d->m_navigationHistory.size()-1;
+ m_d->currentNavigationHistoryPosition = m_d->m_navigationHistory.size();
updateActions();
}
void EditorManager::updateCurrentPositionInNavigationHistory()
{
- if (!m_d->m_currentEditor
- || m_d->currentNavigationHistoryPosition < 0
- || m_d->m_navigationHistory.at(m_d->currentNavigationHistoryPosition)->editor != m_d->m_currentEditor)
+ if (!m_d->m_currentEditor || !m_d->m_currentEditor->file())
return;
- m_d->m_navigationHistory.at(m_d->currentNavigationHistoryPosition)->state = m_d->m_currentEditor->saveState();
+
+ EditorManagerPrivate::EditLocation *location;
+ if (m_d->currentNavigationHistoryPosition < m_d->m_navigationHistory.size()) {
+ location = m_d->m_navigationHistory[m_d->currentNavigationHistoryPosition];
+ } else {
+ location = new EditorManagerPrivate::EditLocation;
+ m_d->m_navigationHistory.append(location);
+ }
+ location->editor = m_d->m_currentEditor;
+ location->fileName = m_d->m_currentEditor->file()->fileName();
+ location->kind = m_d->m_currentEditor->kind();
+ location->state = QVariant(m_d->m_currentEditor->saveState());
}
void EditorManager::goBackInNavigationHistory()
diff --git a/src/plugins/coreplugin/editormanager/editormanager.h b/src/plugins/coreplugin/editormanager/editormanager.h
index 401e94b00d..75c7e28cc3 100644
--- a/src/plugins/coreplugin/editormanager/editormanager.h
+++ b/src/plugins/coreplugin/editormanager/editormanager.h
@@ -132,7 +132,7 @@ public:
QList<IEditor*> editorsForFiles(QList<IFile*> files) const;
//QList<EditorGroup *> editorGroups() const;
QList<IEditor*> editorHistory() const;
- void addCurrentPositionToNavigationHistory(bool compress = false);
+ void addCurrentPositionToNavigationHistory(const QByteArray &saveState = QByteArray(), bool compress = false);
bool saveEditor(IEditor *editor);
diff --git a/src/plugins/coreplugin/welcomemode.cpp b/src/plugins/coreplugin/welcomemode.cpp
index de9b8893f6..588bfcb827 100644
--- a/src/plugins/coreplugin/welcomemode.cpp
+++ b/src/plugins/coreplugin/welcomemode.cpp
@@ -92,6 +92,7 @@ WelcomeModePrivate::WelcomeModePrivate() :
m_projectHtmlTemplate(readFile(QLatin1String(":/core/html/recent_projects.html"))),
m_baseUrl(QUrl(QLatin1String("qrc:/core/html/welcome.html")))
{
+ m_webview->setContextMenuPolicy(Qt::NoContextMenu);
}
#if defined(QT_NO_WEBKIT)
diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp
index e356e378cf..5b363e291d 100644
--- a/src/plugins/cppeditor/cppeditor.cpp
+++ b/src/plugins/cppeditor/cppeditor.cpp
@@ -979,9 +979,8 @@ bool CPPEditor::openEditorAt(Symbol *s)
if (baseTextDocument()->fileName() == fileName) {
Core::EditorManager *editorManager = Core::EditorManager::instance();
- editorManager->addCurrentPositionToNavigationHistory(true);
- gotoLine(line, column);
editorManager->addCurrentPositionToNavigationHistory();
+ gotoLine(line, column);
setFocus();
return true;
}
diff --git a/src/plugins/debugger/debuggeractions.cpp b/src/plugins/debugger/debuggeractions.cpp
index 47a72dc0a9..0a102c4ae9 100644
--- a/src/plugins/debugger/debuggeractions.cpp
+++ b/src/plugins/debugger/debuggeractions.cpp
@@ -339,6 +339,7 @@ DebuggerSettings *theDebuggerSettings()
item = new DebuggerAction(instance);
instance->insertItem(WatchExpressionInWindow, item);
item->setTextPattern(QObject::tr("Watch expression \"%1\" in separate window"));
+ //item->setCheckable(true);
item = new DebuggerAction(instance);
instance->insertItem(AssignValue, item);
@@ -421,6 +422,10 @@ DebuggerSettings *theDebuggerSettings()
item->setText(QObject::tr("Use custom dumpers"));
item->setCheckable(true);
+ item = new DebuggerAction(instance);
+ instance->insertItem(Terminal, item);
+ item->setDefaultValue("xterm");
+ item->setSettingsKey("DebugMode", "Terminal");
item = new DebuggerAction(instance);
instance->insertItem(ListSourceFiles, item);
diff --git a/src/plugins/debugger/debuggeractions.h b/src/plugins/debugger/debuggeractions.h
index 2a64e45c2a..528bcc2c4d 100644
--- a/src/plugins/debugger/debuggeractions.h
+++ b/src/plugins/debugger/debuggeractions.h
@@ -141,6 +141,7 @@ enum DebuggerActionCode
GdbScriptFile,
GdbAutoRun,
GdbAutoQuit,
+ Terminal,
// Watchers & Locals
WatchExpression,
diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp
index 13de5d0c8e..8f4905c9d2 100644
--- a/src/plugins/debugger/debuggerplugin.cpp
+++ b/src/plugins/debugger/debuggerplugin.cpp
@@ -268,6 +268,8 @@ QWidget *GdbOptionPage::createPage(QWidget *parent)
m_ui.gdbLocationChooser->setPromptDialogTitle(tr("Choose Gdb Location"));
m_ui.scriptFileChooser->setExpectedKind(Core::Utils::PathChooser::File);
m_ui.scriptFileChooser->setPromptDialogTitle(tr("Choose Location of Startup Script File"));
+ m_ui.terminalChooser->setExpectedKind(Core::Utils::PathChooser::Command);
+ m_ui.terminalChooser->setPromptDialogTitle(tr("Choose Location of Terminal Application"));
theDebuggerAction(GdbLocation)
->connectWidget(m_ui.gdbLocationChooser);
@@ -275,6 +277,8 @@ QWidget *GdbOptionPage::createPage(QWidget *parent)
->connectWidget(m_ui.scriptFileChooser);
theDebuggerAction(GdbEnvironment)
->connectWidget(m_ui.environmentEdit);
+ theDebuggerAction(Terminal)
+ ->connectWidget(m_ui.terminalChooser);
theDebuggerAction(AllPluginBreakpoints)
->connectWidget(m_ui.radioButtonAllPluginBreakpoints);
@@ -328,6 +332,7 @@ void GdbOptionPage::apply()
theDebuggerAction(GdbLocation)->apply(s);
theDebuggerAction(GdbScriptFile)->apply(s);
theDebuggerAction(GdbEnvironment)->apply(s);
+ theDebuggerAction(Terminal)->apply(s);
theDebuggerAction(AllPluginBreakpoints)->apply(s);
theDebuggerAction(SelectedPluginBreakpoints)->apply(s);
diff --git a/src/plugins/debugger/gdboptionpage.ui b/src/plugins/debugger/gdboptionpage.ui
index 5305559947..3a51818c86 100644
--- a/src/plugins/debugger/gdboptionpage.ui
+++ b/src/plugins/debugger/gdboptionpage.ui
@@ -32,10 +32,21 @@
<item row="0" column="0">
<widget class="QLabel" name="labelGdbLocation">
<property name="toolTip">
- <string>This is either a full abolute path leading to the gdb binary you intend to use or the name of a gdb binary that wiull be searched in your PATH.</string>
+ <string>This is either a full abolute path leading to the gdb binary you intend to use or the name of a gdb binary that will be searched in your PATH.</string>
</property>
<property name="text">
- <string>Gdb Location:</string>
+ <string>Gdb location:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="terminalLocation">
+ <property name="toolTip">
+ <string>This is either a full abolute path leading to the terminal
+you indent to use or the name of a terminal that will be searched in your PATH.</string>
+ </property>
+ <property name="text">
+ <string>Terminal:</string>
</property>
</widget>
</item>
@@ -55,7 +66,7 @@
<string>This is either empty or points to a file containing gdb commands that will be executed immediately after gdb starts up.</string>
</property>
<property name="text">
- <string>Gdb Startup Script:</string>
+ <string>Gdb startup script:</string>
</property>
</widget>
</item>
@@ -65,6 +76,9 @@
<item row="0" column="1">
<widget class="Core::Utils::PathChooser" name="gdbLocationChooser" native="true"/>
</item>
+ <item row="3" column="1">
+ <widget class="Core::Utils::PathChooser" name="terminalChooser" native="true"/>
+ </item>
</layout>
</widget>
</item>
diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp
index 9dcec117d3..ab96217b1e 100644
--- a/src/plugins/debugger/watchhandler.cpp
+++ b/src/plugins/debugger/watchhandler.cpp
@@ -499,9 +499,6 @@ QVariant WatchHandler::data(const QModelIndex &idx, int role) const
case INameRole:
return data.iname;
- case VisualRole:
- return m_displayedINames.contains(data.iname);
-
case ExpandedRole:
//qDebug() << " FETCHING: " << data.iname
// << m_expandedINames.contains(data.iname)
diff --git a/src/plugins/debugger/watchhandler.h b/src/plugins/debugger/watchhandler.h
index 4cac4a87f9..a419203815 100644
--- a/src/plugins/debugger/watchhandler.h
+++ b/src/plugins/debugger/watchhandler.h
@@ -132,7 +132,7 @@ public:
bool changed;
};
-enum { INameRole = Qt::UserRole, ExpressionRole, VisualRole, ExpandedRole };
+enum { INameRole = Qt::UserRole, ExpressionRole, ExpandedRole };
class WatchHandler : public QAbstractItemModel
diff --git a/src/plugins/debugger/watchwindow.cpp b/src/plugins/debugger/watchwindow.cpp
index ceef4bc1f8..de30e8f380 100644
--- a/src/plugins/debugger/watchwindow.cpp
+++ b/src/plugins/debugger/watchwindow.cpp
@@ -54,7 +54,7 @@ using namespace Debugger::Internal;
//
/////////////////////////////////////////////////////////////////////
-enum { INameRole = Qt::UserRole, ExpressionRole, VisualRole, ExpandedRole };
+enum { INameRole = Qt::UserRole, ExpressionRole, ExpandedRole };
class WatchDelegate : public QItemDelegate
{
@@ -158,8 +158,6 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
QAction *act2 = new QAction("Always adjust column widths to contents", &menu);
act2->setCheckable(true);
act2->setChecked(m_alwaysResizeColumnsToContents);
- //QAction *act3 = 0;
- QAction *act4 = 0;
menu.addAction(act1);
menu.addAction(act2);
@@ -169,20 +167,16 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
QString exp = model()->data(mi0).toString();
QModelIndex mi1 = idx.sibling(idx.row(), 0);
QString value = model()->data(mi1).toString();
- bool visual = false;
menu.addSeparator();
int type = (m_type == LocalsType) ? WatchExpression : RemoveWatchExpression;
menu.addAction(theDebuggerAction(type)->updatedAction(exp));
- visual = model()->data(mi0, VisualRole).toBool();
- //act4 = theDebuggerAction(WatchExpressionInWindow)->action();
- //act4->setCheckable(true);
- //act4->setChecked(visual);
+ //QAction *act4 = theDebuggerAction(WatchExpressionInWindow);
//menu.addAction(act4);
- //act3 = new QAction(tr("Add to watch window..."), &menu);
- //menu.addAction(act3);
+ QAction *act3 = new QAction(tr("Insert new watch item"), &menu);
+ menu.addAction(act3);
menu.addSeparator();
menu.addAction(theDebuggerAction(RecheckDumpers));
@@ -196,10 +190,8 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
resizeColumnsToContents();
else if (act == act2)
setAlwaysResizeColumnsToContents(!m_alwaysResizeColumnsToContents);
- else if (act == act4)
- model()->setData(mi0, !visual, VisualRole);
- else if (act == act4)
- model()->setData(mi0, !visual, VisualRole);
+ else if (act == act3)
+ theDebuggerAction(WatchExpression)->trigger("<Edit>");
}
void WatchWindow::resizeColumnsToContents()
diff --git a/src/plugins/fakevim/fakevimconstants.h b/src/plugins/fakevim/fakevimconstants.h
index 7c21750451..c1b7ff1b15 100644
--- a/src/plugins/fakevim/fakevimconstants.h
+++ b/src/plugins/fakevim/fakevimconstants.h
@@ -44,6 +44,13 @@ const char * const ConfigSmartTab = "smarttab";
const char * const ConfigStartOfLine = "startofline";
const char * const ConfigTabStop = "tabstop";
+const char * const ConfigBackspace = "backspace";
+// indent allow backspacing over autoindent
+// eol allow backspacing over line breaks (join lines)
+// start allow backspacing over the start of insert; CTRL-W and CTRL-U
+// stop once at the start of insert.
+
+
} // namespace Constants
} // namespace FakeVim
diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp
index 62f56238f4..36a6a3264e 100644
--- a/src/plugins/fakevim/fakevimhandler.cpp
+++ b/src/plugins/fakevim/fakevimhandler.cpp
@@ -250,6 +250,8 @@ private:
int cursorColumnInDocument() const;
int linesInDocument() const;
void scrollToLineInDocument(int line);
+ void scrollUp(int count);
+ void scrollDown(int count) { scrollUp(-count); }
// helper functions for indenting
bool isElectricCharacter(QChar c) const
@@ -378,9 +380,14 @@ public:
// marks as lines
QHash<int, int> m_marks;
+ QString m_oldNeedle;
// vi style configuration
QHash<QString, QString> m_config;
+ bool hasConfig(const char *name) const
+ { return m_config[name] == ConfigOn; }
+ bool hasConfig(const char *name, const char *value) const
+ { return m_config[name].contains(value); } // FIXME
// for restoring cursor position
int m_savedYankPosition;
@@ -418,6 +425,8 @@ FakeVimHandler::Private::Private(FakeVimHandler *parent, QWidget *widget)
m_savedYankPosition = 0;
m_cursorWidth = EDITOR(cursorWidth());
+#if 1
+ // Plain
m_config[ConfigStartOfLine] = ConfigOn;
m_config[ConfigHlSearch] = ConfigOn;
m_config[ConfigTabStop] = "8";
@@ -425,6 +434,18 @@ FakeVimHandler::Private::Private(FakeVimHandler *parent, QWidget *widget)
m_config[ConfigShiftWidth] = "8";
m_config[ConfigExpandTab] = ConfigOff;
m_config[ConfigAutoIndent] = ConfigOff;
+ m_config[ConfigBackspace] = "";
+#else
+ // Qt Local
+ m_config[ConfigStartOfLine] = ConfigOn;
+ m_config[ConfigHlSearch] = ConfigOn;
+ m_config[ConfigTabStop] = "4";
+ m_config[ConfigSmartTab] = ConfigOff;
+ m_config[ConfigShiftWidth] = "4";
+ m_config[ConfigExpandTab] = ConfigOn;
+ m_config[ConfigAutoIndent] = ConfigOff;
+ m_config[ConfigBackspace] = "indent,eol,start";
+#endif
}
bool FakeVimHandler::Private::wantsOverride(QKeyEvent *ev)
@@ -513,7 +534,7 @@ EventResult FakeVimHandler::Private::handleEvent(QKeyEvent *ev)
moveLeft();
EDITOR(setTextCursor(m_tc));
- EDITOR(ensureCursorVisible());
+ //EDITOR(ensureCursorVisible());
return result;
}
@@ -838,21 +859,21 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
if (key == Key_Return || key == 't') { // cursor line to top of window
if (!m_mvcount.isEmpty())
setPosition(firstPositionInLine(count()));
- scrollToLineInDocument(cursorLineInDocument());
+ scrollUp(- cursorLineOnScreen());
if (key == Key_Return)
moveToFirstNonBlankOnLine();
finishMovement();
} else if (key == '.' || key == 'z') { // cursor line to center of window
if (!m_mvcount.isEmpty())
setPosition(firstPositionInLine(count()));
- scrollToLineInDocument(cursorLineInDocument() - linesOnScreen() / 2);
+ scrollUp(linesOnScreen() / 2 - cursorLineOnScreen());
if (key == '.')
moveToFirstNonBlankOnLine();
finishMovement();
} else if (key == '-' || key == 'b') { // cursor line to bottom of window
if (!m_mvcount.isEmpty())
setPosition(firstPositionInLine(count()));
- scrollToLineInDocument(cursorLineInDocument() - linesOnScreen() - 1);
+ scrollUp(linesOnScreen() - cursorLineOnScreen());
if (key == '-')
moveToFirstNonBlankOnLine();
finishMovement();
@@ -1092,6 +1113,12 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
m_moveType = MoveInclusive;
moveToWordBoundary(true, true);
finishMovement();
+ } else if (key == control('e')) {
+ // FIXME: this should use the "scroll" option, and "count"
+ if (cursorLineOnScreen() == 0)
+ moveDown(1);
+ scrollDown(1);
+ finishMovement();
} else if (key == 'f') {
m_subsubmode = FtSubSubMode;
m_moveType = MoveInclusive;
@@ -1104,7 +1131,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
if (m_gflag) {
m_gflag = false;
m_tc.setPosition(firstPositionInLine(1), KeepAnchor);
- if (m_config[ConfigStartOfLine] == ConfigOn)
+ if (hasConfig(ConfigStartOfLine))
moveToFirstNonBlankOnLine();
finishMovement();
} else {
@@ -1113,7 +1140,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
} else if (key == 'G') {
int n = m_mvcount.isEmpty() ? linesInDocument() : count();
m_tc.setPosition(firstPositionInLine(n), KeepAnchor);
- if (m_config[ConfigStartOfLine] == ConfigOn)
+ if (hasConfig(ConfigStartOfLine))
moveToFirstNonBlankOnLine();
finishMovement();
} else if (key == 'h' || key == Key_Left
@@ -1229,7 +1256,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
moveToEndOfLine();
recordInsertText("\n");
moveToStartOfLine();
- if (0 && m_config[ConfigAutoIndent] == ConfigOn)
+ if (0 && hasConfig(ConfigAutoIndent))
recordInsertText(QString(indentDist(), ' '));
else
recordInsertText(QString(numSpaces, ' '));
@@ -1447,11 +1474,13 @@ EventResult FakeVimHandler::Private::handleInsertMode(int key, int,
m_submode = NoSubMode;
m_tc.insertBlock();
m_lastInsertion += "\n";
- if (0 && m_config[ConfigAutoIndent] == ConfigOn)
+ if (0 && hasConfig(ConfigAutoIndent))
indentRegion('\n');
} else if (key == Key_Backspace || key == control('h')) {
- m_tc.deletePreviousChar();
- m_lastInsertion = m_lastInsertion.left(m_lastInsertion.size() - 1);
+ if (!m_lastInsertion.isEmpty() || hasConfig(ConfigBackspace, "start")) {
+ m_tc.deletePreviousChar();
+ m_lastInsertion = m_lastInsertion.left(m_lastInsertion.size() - 1);
+ }
} else if (key == Key_Delete) {
m_tc.deleteChar();
m_lastInsertion.clear();
@@ -1461,7 +1490,7 @@ EventResult FakeVimHandler::Private::handleInsertMode(int key, int,
} else if (key == Key_PageUp || key == control('b')) {
moveUp(count() * (linesOnScreen() - 2));
m_lastInsertion.clear();
- } else if (key == Key_Tab && m_config[ConfigExpandTab] == ConfigOn) {
+ } else if (key == Key_Tab && hasConfig(ConfigExpandTab)) {
QString str = QString(m_config[ConfigTabStop].toInt(), ' ');
m_lastInsertion.append(str);
m_tc.insertText(str);
@@ -1476,8 +1505,7 @@ EventResult FakeVimHandler::Private::handleInsertMode(int key, int,
m_tc.deleteChar();
}
m_tc.insertText(text);
- if (0 && m_config[ConfigAutoIndent] == ConfigOn
- && isElectricCharacter(text.at(0))) {
+ if (0 && hasConfig(ConfigAutoIndent) && isElectricCharacter(text.at(0))) {
const QString leftText = m_tc.block().text()
.left(m_tc.position() - 1 - m_tc.block().position());
if (leftText.simplified().isEmpty())
@@ -1500,10 +1528,11 @@ EventResult FakeVimHandler::Private::handleMiniBufferModes(int key, int unmodifi
enterCommandMode();
updateMiniBuffer();
} else if (key == Key_Backspace) {
- if (m_commandBuffer.isEmpty())
+ if (m_commandBuffer.isEmpty()) {
enterCommandMode();
- else
+ } else {
m_commandBuffer.chop(1);
+ }
updateMiniBuffer();
} else if (key == Key_Left) {
// FIXME:
@@ -1837,51 +1866,56 @@ void FakeVimHandler::Private::search(const QString &needle0, bool forward)
if (oldLine != cursorLineInDocument() - cursorLineOnScreen())
scrollToLineInDocument(cursorLineInDocument() - linesOnScreen() / 2);
highlightMatches(needle);
- return;
- }
-
- m_tc.setPosition(forward ? 0 : lastPositionInDocument() - 1);
- EDITOR(setTextCursor(m_tc));
- if (EDITOR(find(needle, flags))) {
- m_tc = EDITOR(textCursor());
- m_tc.setPosition(m_tc.anchor());
- if (oldLine != cursorLineInDocument() - cursorLineOnScreen())
- scrollToLineInDocument(cursorLineInDocument() - linesOnScreen() / 2);
- if (forward)
- showRedMessage("search hit BOTTOM, continuing at TOP");
- else
- showRedMessage("search hit TOP, continuing at BOTTOM");
- highlightMatches(needle);
- return;
+ } else {
+ m_tc.setPosition(forward ? 0 : lastPositionInDocument() - 1);
+ EDITOR(setTextCursor(m_tc));
+ if (EDITOR(find(needle, flags))) {
+ m_tc = EDITOR(textCursor());
+ m_tc.setPosition(m_tc.anchor());
+ if (oldLine != cursorLineInDocument() - cursorLineOnScreen())
+ scrollToLineInDocument(cursorLineInDocument() - linesOnScreen() / 2);
+ if (forward)
+ showRedMessage("search hit BOTTOM, continuing at TOP");
+ else
+ showRedMessage("search hit TOP, continuing at BOTTOM");
+ highlightMatches(needle);
+ } else {
+ m_tc = orig;
+ showRedMessage("E486: Pattern not found: " + needle);
+ highlightMatches(QString());
+ }
}
-
- m_tc = orig;
}
void FakeVimHandler::Private::highlightMatches(const QString &needle0)
{
- if (m_config[ConfigHlSearch] == ConfigOff)
+ if (!hasConfig(ConfigHlSearch))
+ return;
+ if (needle0 == m_oldNeedle)
return;
+ m_oldNeedle = needle0;
+ m_searchSelections.clear();
- QTextCursor tc = m_tc;
- tc.movePosition(QTextCursor::Start, MoveAnchor);
+ if (!needle0.isEmpty()) {
+ QTextCursor tc = m_tc;
+ tc.movePosition(QTextCursor::Start, MoveAnchor);
- QTextDocument::FindFlags flags = QTextDocument::FindCaseSensitively;
- QString needle = needle0;
- vimPatternToQtPattern(&needle, &flags);
+ QTextDocument::FindFlags flags = QTextDocument::FindCaseSensitively;
+ QString needle = needle0;
+ vimPatternToQtPattern(&needle, &flags);
- m_searchSelections.clear();
- EDITOR(setTextCursor(tc));
- while (EDITOR(find(needle, flags))) {
- tc = EDITOR(textCursor());
- QTextEdit::ExtraSelection sel;
- sel.cursor = tc;
- sel.format = tc.blockCharFormat();
- sel.format.setBackground(QColor(177, 177, 0));
- m_searchSelections.append(sel);
- tc.movePosition(Right, MoveAnchor);
EDITOR(setTextCursor(tc));
+ while (EDITOR(find(needle, flags))) {
+ tc = EDITOR(textCursor());
+ QTextEdit::ExtraSelection sel;
+ sel.cursor = tc;
+ sel.format = tc.blockCharFormat();
+ sel.format.setBackground(QColor(177, 177, 0));
+ m_searchSelections.append(sel);
+ tc.movePosition(Right, MoveAnchor);
+ EDITOR(setTextCursor(tc));
+ }
}
updateSelection();
}
@@ -2134,9 +2168,15 @@ void FakeVimHandler::Private::scrollToLineInDocument(int line)
{
// FIXME: works only for QPlainTextEdit
QScrollBar *scrollBar = EDITOR(verticalScrollBar());
+ //qDebug() << "SCROLL: " << scrollBar->value() << line;
scrollBar->setValue(line);
}
+void FakeVimHandler::Private::scrollUp(int count)
+{
+ scrollToLineInDocument(cursorLineInDocument() - cursorLineOnScreen() - count);
+}
+
int FakeVimHandler::Private::lastPositionInDocument() const
{
QTextBlock block = m_tc.block().document()->lastBlock();
diff --git a/src/plugins/genericprojectmanager/genericproject.cpp b/src/plugins/genericprojectmanager/genericproject.cpp
index 9070dabd5c..c0f497c062 100644
--- a/src/plugins/genericprojectmanager/genericproject.cpp
+++ b/src/plugins/genericprojectmanager/genericproject.cpp
@@ -31,6 +31,7 @@
#include "genericprojectconstants.h"
#include "genericmakestep.h"
+#include <projectexplorer/toolchain.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <cpptools/cppmodelmanagerinterface.h>
#include <extensionsystem/pluginmanager.h>
@@ -112,12 +113,12 @@ GenericProject::GenericProject(Manager *manager, const QString &fileName)
m_toolChain(0)
{
QFileInfo fileInfo(m_fileName);
- const QString projectBaseName = fileInfo.baseName();
QDir dir = fileInfo.dir();
- m_filesFileName = QFileInfo(dir, projectBaseName + QLatin1String(".files")).absoluteFilePath();
- m_includesFileName = QFileInfo(dir, projectBaseName + QLatin1String(".includes")).absoluteFilePath();
- m_configFileName = QFileInfo(dir, projectBaseName + QLatin1String(".config")).absoluteFilePath();
+ m_projectName = fileInfo.baseName();
+ m_filesFileName = QFileInfo(dir, m_projectName + QLatin1String(".files")).absoluteFilePath();
+ m_includesFileName = QFileInfo(dir, m_projectName + QLatin1String(".includes")).absoluteFilePath();
+ m_configFileName = QFileInfo(dir, m_projectName + QLatin1String(".config")).absoluteFilePath();
m_file = new GenericProjectFile(this, fileName);
m_rootNode = new GenericProjectNode(this, m_file);
@@ -142,7 +143,7 @@ QString GenericProject::includesFileName() const
QString GenericProject::configFileName() const
{ return m_configFileName; }
-QStringList GenericProject::readLines(const QString &absoluteFileName) const
+static QStringList readLines(const QString &absoluteFileName)
{
QStringList lines;
@@ -167,34 +168,41 @@ QStringList GenericProject::readLines(const QString &absoluteFileName) const
}
-void GenericProject::parseProject()
+void GenericProject::parseProject(RefreshOptions options)
{
- const QFileInfo projectFileInfo(m_fileName);
-
- QSettings projectInfo(m_fileName, QSettings::IniFormat);
-
- m_files = convertToAbsoluteFiles(readLines(filesFileName()));
- m_files.removeDuplicates();
+ if (options & Files) {
+ m_files = convertToAbsoluteFiles(readLines(filesFileName()));
+ m_files.removeDuplicates();
+ }
- m_projectIncludePaths = readLines(includesFileName());
- m_projectIncludePaths.removeDuplicates();
+ if (options & Configuration) {
+ m_projectIncludePaths = readLines(includesFileName());
+ m_projectIncludePaths.removeDuplicates();
- m_generated = convertToAbsoluteFiles(projectInfo.value(QLatin1String("generated")).toStringList());
+ QSettings projectInfo(m_fileName, QSettings::IniFormat);
+ m_generated = convertToAbsoluteFiles(projectInfo.value(QLatin1String("generated")).toStringList());
- m_defines.clear();
+ m_defines.clear();
- QFile configFile(configFileName());
- if (configFile.open(QFile::ReadOnly))
- m_defines = configFile.readAll();
+ QFile configFile(configFileName());
+ if (configFile.open(QFile::ReadOnly))
+ m_defines = configFile.readAll();
+ }
- emit fileListChanged();
+ if (options & Files)
+ emit fileListChanged();
}
-void GenericProject::refresh()
+void GenericProject::refresh(RefreshOptions options)
{
- parseProject();
+ QSet<QString> oldFileList;
+ if (!(options & Configuration))
+ oldFileList = m_files.toSet();
- m_rootNode->refresh();
+ parseProject(options);
+
+ if (options & Files)
+ m_rootNode->refresh();
CppTools::CppModelManagerInterface *modelManager =
ExtensionSystem::PluginManager::instance()->getObject<CppTools::CppModelManagerInterface>();
@@ -213,7 +221,6 @@ void GenericProject::refresh()
foreach (const ProjectExplorer::HeaderPath &headerPath, m_toolChain->systemHeaderPaths()) {
if (headerPath.kind() == ProjectExplorer::HeaderPath::FrameworkHeaderPath)
allFrameworkPaths.append(headerPath.path());
-
else
allIncludePaths.append(headerPath.path());
}
@@ -227,8 +234,17 @@ void GenericProject::refresh()
pinfo.sourceFiles = files();
pinfo.sourceFiles += generated();
- QStringList filesToUpdate = pinfo.sourceFiles;
- filesToUpdate.append(QLatin1String("<configuration>")); // XXX don't hardcode configuration file name
+ QStringList filesToUpdate;
+
+ if (options & Configuration) {
+ filesToUpdate = pinfo.sourceFiles;
+ filesToUpdate.append(QLatin1String("<configuration>")); // XXX don't hardcode configuration file name
+ } else if (options & Files) {
+ // Only update files that got added to the list
+ QSet<QString> newFileList = m_files.toSet();
+ newFileList.subtract(oldFileList);
+ filesToUpdate.append(newFileList.toList());
+ }
modelManager->updateProjectInfo(pinfo);
modelManager->updateSourceFiles(filesToUpdate);
@@ -449,8 +465,7 @@ void GenericProject::restoreSettingsImpl(ProjectExplorer::PersistentSettingsRead
setIncludePaths(allIncludePaths());
- parseProject();
- refresh();
+ refresh(Everything);
}
void GenericProject::saveSettingsImpl(ProjectExplorer::PersistentSettingsWriter &writer)
diff --git a/src/plugins/genericprojectmanager/genericproject.h b/src/plugins/genericprojectmanager/genericproject.h
index a5f4abb7fb..25877c40ac 100644
--- a/src/plugins/genericprojectmanager/genericproject.h
+++ b/src/plugins/genericprojectmanager/genericproject.h
@@ -36,7 +36,6 @@
#include <projectexplorer/project.h>
#include <projectexplorer/projectnodes.h>
#include <projectexplorer/buildstep.h>
-#include <projectexplorer/toolchain.h>
#include <coreplugin/ifile.h>
QT_BEGIN_NAMESPACE
@@ -95,6 +94,14 @@ public:
QString buildParser(const QString &buildConfiguration) const;
ProjectExplorer::ToolChain *toolChain() const;
+ enum RefreshOptions {
+ Files = 0x01,
+ Configuration = 0x02,
+ Everything = Files | Configuration
+ };
+
+ void refresh(RefreshOptions options);
+
QStringList includePaths() const;
void setIncludePaths(const QStringList &includePaths);
@@ -107,18 +114,15 @@ public:
public Q_SLOTS:
void setToolChainId(const QString &toolChainId);
- void refresh();
protected:
virtual void saveSettingsImpl(ProjectExplorer::PersistentSettingsWriter &writer);
virtual void restoreSettingsImpl(ProjectExplorer::PersistentSettingsReader &reader);
private:
- void parseProject();
+ void parseProject(RefreshOptions options);
QStringList convertToAbsoluteFiles(const QStringList &paths) const;
- QStringList readLines(const QString &absoluteFileName) const;
-
Manager *m_manager;
QString m_fileName;
QString m_filesFileName;
diff --git a/src/plugins/genericprojectmanager/genericprojectmanager.cpp b/src/plugins/genericprojectmanager/genericprojectmanager.cpp
index 5495173f8d..58f19648a3 100644
--- a/src/plugins/genericprojectmanager/genericprojectmanager.cpp
+++ b/src/plugins/genericprojectmanager/genericprojectmanager.cpp
@@ -79,10 +79,12 @@ void Manager::unregisterProject(GenericProject *project)
void Manager::notifyChanged(const QString &fileName)
{
foreach (GenericProject *project, m_projects) {
- if (fileName == project->filesFileName() ||
- fileName == project->includesFileName() ||
- fileName == project->configFileName())
- project->refresh();
+ if (fileName == project->filesFileName()) {
+ project->refresh(GenericProject::Files);
+ }
+ else if (fileName == project->includesFileName() ||
+ fileName == project->configFileName()) {
+ project->refresh(GenericProject::Configuration);
+ }
}
}
-
diff --git a/src/plugins/genericprojectmanager/genericprojectnodes.cpp b/src/plugins/genericprojectmanager/genericprojectnodes.cpp
index b6bde51ca4..016ada7f47 100644
--- a/src/plugins/genericprojectmanager/genericprojectnodes.cpp
+++ b/src/plugins/genericprojectmanager/genericprojectnodes.cpp
@@ -30,12 +30,10 @@
#include "genericprojectnodes.h"
#include "genericproject.h"
+#include <coreplugin/ifile.h>
#include <projectexplorer/projectexplorer.h>
-#include <QDir>
#include <QFileInfo>
-#include <QSettings>
-#include <QtDebug>
using namespace GenericProjectManager;
using namespace GenericProjectManager::Internal;
@@ -44,7 +42,9 @@ GenericProjectNode::GenericProjectNode(GenericProject *project, Core::IFile *pro
: ProjectExplorer::ProjectNode(QFileInfo(projectFile->fileName()).absolutePath()),
m_project(project),
m_projectFile(projectFile)
-{}
+{
+ setFolderName(QFileInfo(projectFile->fileName()).baseName());
+}
GenericProjectNode::~GenericProjectNode()
{ }
diff --git a/src/plugins/genericprojectmanager/genericprojectnodes.h b/src/plugins/genericprojectmanager/genericprojectnodes.h
index 4b647a860e..326e0ee3ce 100644
--- a/src/plugins/genericprojectmanager/genericprojectnodes.h
+++ b/src/plugins/genericprojectmanager/genericprojectnodes.h
@@ -30,11 +30,15 @@
#ifndef GENERICPROJECTNODE_H
#define GENERICPROJECTNODE_H
-#include <coreplugin/ifile.h>
#include <projectexplorer/projectnodes.h>
+
#include <QStringList>
#include <QHash>
+namespace Core {
+class IFile;
+}
+
namespace GenericProjectManager {
namespace Internal {
diff --git a/src/plugins/genericprojectmanager/genericprojectwizard.cpp b/src/plugins/genericprojectmanager/genericprojectwizard.cpp
index 289cbfd343..7c3185e148 100644
--- a/src/plugins/genericprojectmanager/genericprojectwizard.cpp
+++ b/src/plugins/genericprojectmanager/genericprojectwizard.cpp
@@ -4,16 +4,17 @@
#include <coreplugin/mimedatabase.h>
#include <projectexplorer/projectexplorer.h>
+#include <utils/filenamevalidatinglineedit.h>
+#include <utils/filewizardpage.h>
#include <utils/pathchooser.h>
#include <QtCore/QDir>
#include <QtCore/QtDebug>
-#include <QtGui/QWizard>
+#include <QtGui/QDirModel>
#include <QtGui/QFormLayout>
#include <QtGui/QListView>
#include <QtGui/QTreeView>
-#include <QtGui/QDirModel>
using namespace GenericProjectManager::Internal;
using namespace Core::Utils;
@@ -94,14 +95,12 @@ GenericProjectWizardDialog::GenericProjectWizardDialog(QWidget *parent)
setWindowTitle(tr("Import Existing Project"));
// first page
- QWizardPage *firstPage = new QWizardPage;
- firstPage->setTitle(tr("Project"));
-
- QFormLayout *layout = new QFormLayout(firstPage);
- m_pathChooser = new PathChooser;
- layout->addRow(tr("Source Directory:"), m_pathChooser);
+ m_firstPage = new FileWizardPage;
+ m_firstPage->setTitle(tr("Import Project"));
+ m_firstPage->setNameLabel(tr("Project name:"));
+ m_firstPage->setPathLabel(tr("Location:"));
- m_firstPageId = addPage(firstPage);
+ addPage(m_firstPage);
#if 0
// second page
@@ -146,7 +145,14 @@ GenericProjectWizardDialog::~GenericProjectWizardDialog()
{ }
QString GenericProjectWizardDialog::path() const
-{ return m_pathChooser->path(); }
+{
+ return m_firstPage->path();
+}
+
+QString GenericProjectWizardDialog::projectName() const
+{
+ return m_firstPage->name();
+}
void GenericProjectWizardDialog::updateFilesView(const QModelIndex &current,
const QModelIndex &)
@@ -182,12 +188,11 @@ bool GenericProjectWizardDialog::validateCurrentPage()
{
using namespace Core::Utils;
- if (currentId() == m_firstPageId) {
- return ! m_pathChooser->path().isEmpty();
-
- } else if (currentId() == m_secondPageId) {
+#if 0
+ if (currentId() == m_secondPageId) {
return true;
}
+#endif
return QWizard::validateCurrentPage();
}
@@ -271,7 +276,7 @@ Core::GeneratedFiles GenericProjectWizard::generateFiles(const QWizard *w,
const GenericProjectWizardDialog *wizard = qobject_cast<const GenericProjectWizardDialog *>(w);
const QString projectPath = wizard->path();
const QDir dir(projectPath);
- const QString projectName = QFileInfo(projectPath).baseName();
+ const QString projectName = wizard->projectName();
const QString creatorFileName = QFileInfo(dir, projectName + QLatin1String(".creator")).absoluteFilePath();
const QString filesFileName = QFileInfo(dir, projectName + QLatin1String(".files")).absoluteFilePath();
const QString includesFileName = QFileInfo(dir, projectName + QLatin1String(".includes")).absoluteFilePath();
diff --git a/src/plugins/genericprojectmanager/genericprojectwizard.h b/src/plugins/genericprojectmanager/genericprojectwizard.h
index c268ce5f2a..73cf61e82c 100644
--- a/src/plugins/genericprojectmanager/genericprojectwizard.h
+++ b/src/plugins/genericprojectmanager/genericprojectwizard.h
@@ -2,23 +2,31 @@
#define GENERICPROJECTWIZARD_H
#include <coreplugin/basefilewizard.h>
-#include <utils/pathchooser.h>
-#include <QWizard>
+
+#include <QtGui/QWizard>
QT_BEGIN_NAMESPACE
-class QListView;
-class QTreeView;
+class QDir;
class QDirModel;
+class QFileInfo;
+class QListView;
class QModelIndex;
-class QDir;
class QStringList;
-class QFileInfo;
+class QTreeView;
QT_END_NAMESPACE
+namespace Core {
+namespace Utils {
+
+class FileWizardPage;
+
+} // namespace Utils
+} // namespace Core
+
namespace GenericProjectManager {
namespace Internal {
-class GenericProjectWizardDialog: public QWizard
+class GenericProjectWizardDialog : public QWizard
{
Q_OBJECT
@@ -27,6 +35,7 @@ public:
virtual ~GenericProjectWizardDialog();
QString path() const;
+ QString projectName() const;
private Q_SLOTS:
void updateFilesView(const QModelIndex &current,
@@ -37,10 +46,9 @@ protected:
virtual bool validateCurrentPage();
private:
- int m_firstPageId;
int m_secondPageId;
- Core::Utils::PathChooser *m_pathChooser;
+ Core::Utils::FileWizardPage *m_firstPage;
QTreeView *m_dirView;
QDirModel *m_dirModel;
diff --git a/src/plugins/git/gitplugin.cpp b/src/plugins/git/gitplugin.cpp
index 29af542988..2c04340401 100644
--- a/src/plugins/git/gitplugin.cpp
+++ b/src/plugins/git/gitplugin.cpp
@@ -142,7 +142,8 @@ GitPlugin::GitPlugin() :
m_coreListener(0),
m_submitEditorFactory(0),
m_versionControl(0),
- m_changeTmpFile(0)
+ m_changeTmpFile(0),
+ m_submitActionTriggered(false)
{
m_instance = this;
}
@@ -651,6 +652,7 @@ Core::IEditor *GitPlugin::openSubmitEditor(const QString &fileName, const Commit
void GitPlugin::submitCurrentLog()
{
// Close the submit editor
+ m_submitActionTriggered = true;
QList<Core::IEditor*> editors;
editors.push_back(m_core->editorManager()->currentEditor());
m_core->editorManager()->closeEditors(editors);
@@ -672,13 +674,18 @@ bool GitPlugin::editorAboutToClose(Core::IEditor *iEditor)
// Paranoia!
if (editorFile.absoluteFilePath() != changeFile.absoluteFilePath())
return true;
- // Prompt user.
- const QMessageBox::StandardButton answer = QMessageBox::question(m_core->mainWindow(), tr("Closing git editor"), tr("Do you want to commit the change?"),
- QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel, QMessageBox::Yes);
+ // Prompt user. Force a prompt unless submit was actually invoked (that
+ // is, the editor was closed or shutdown).
+ const VCSBase::VCSBaseSubmitEditor::PromptSubmitResult answer =
+ editor->promptSubmit(tr("Closing git editor"),
+ tr("Do you want to commit the change?"),
+ tr("The commit message check failed. Do you want to commit the change?"),
+ !m_submitActionTriggered);
+ m_submitActionTriggered = false;
switch (answer) {
- case QMessageBox::Cancel:
+ case VCSBase::VCSBaseSubmitEditor::SubmitCanceled:
return false; // Keep editing and change file
- case QMessageBox::No:
+ case VCSBase::VCSBaseSubmitEditor::SubmitDiscarded:
cleanChangeTmpFile();
return true; // Cancel all
default:
diff --git a/src/plugins/git/gitplugin.h b/src/plugins/git/gitplugin.h
index 6337a60d96..8f7f0bfeed 100644
--- a/src/plugins/git/gitplugin.h
+++ b/src/plugins/git/gitplugin.h
@@ -171,6 +171,7 @@ private:
QString m_submitRepository;
QStringList m_submitOrigCommitFiles;
QTemporaryFile *m_changeTmpFile;
+ bool m_submitActionTriggered;
};
} // namespace Git
diff --git a/src/plugins/git/gitsubmitpanel.ui b/src/plugins/git/gitsubmitpanel.ui
index aba46b7c52..7dfa9b3ba0 100644
--- a/src/plugins/git/gitsubmitpanel.ui
+++ b/src/plugins/git/gitsubmitpanel.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>201</width>
- <height>189</height>
+ <width>374</width>
+ <height>229</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
@@ -59,26 +59,43 @@
<property name="title">
<string>Commit Information</string>
</property>
- <layout class="QFormLayout" name="editFormLayout">
- <item row="0" column="0">
- <widget class="QLabel" name="authorLabel">
- <property name="text">
- <string>Author:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QLineEdit" name="authorLineEdit"/>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <layout class="QFormLayout" name="formLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="authorLabel">
+ <property name="text">
+ <string>Author:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="authorLineEdit"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="emailLabel">
+ <property name="text">
+ <string>Email:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="emailLineEdit"/>
+ </item>
+ </layout>
</item>
- <item row="1" column="0">
- <widget class="QLabel" name="emailLabel">
- <property name="text">
- <string>Email:</string>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
</property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QLineEdit" name="emailLineEdit"/>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>161</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
</item>
</layout>
</widget>
diff --git a/src/plugins/perforce/perforceplugin.cpp b/src/plugins/perforce/perforceplugin.cpp
index 65efbc977f..25ea4524a6 100644
--- a/src/plugins/perforce/perforceplugin.cpp
+++ b/src/plugins/perforce/perforceplugin.cpp
@@ -175,13 +175,18 @@ PerforcePlugin::PerforcePlugin() :
m_diffProjectAction(0),
m_diffAllAction(0),
m_resolveAction(0),
- m_submitAction(0),
+ m_submitAction(0),
m_pendingAction(0),
m_describeAction(0),
m_annotateCurrentAction(0),
m_annotateAction(0),
m_filelogCurrentAction(0),
m_filelogAction(0),
+ m_submitCurrentLogAction(0),
+ m_submitActionTriggered(false),
+ m_diffSelectedFiles(0),
+ m_undoAction(0),
+ m_redoAction(0),
m_changeTmpFile(0),
#ifdef USE_P4_API
m_workbenchClientUser(0),
@@ -949,6 +954,7 @@ void PerforcePlugin::describe(const QString & source, const QString &n)
void PerforcePlugin::submitCurrentLog()
{
+ m_submitActionTriggered = true;
Core::EditorManager *em = Core::EditorManager::instance();
em->closeEditors(QList<Core::IEditor*>() << em->currentEditor());
}
@@ -961,21 +967,28 @@ bool PerforcePlugin::editorAboutToClose(Core::IEditor *editor)
Core::IFile *fileIFace = editor->file();
if (!fileIFace)
return true;
+ const PerforceSubmitEditor *perforceEditor = qobject_cast<PerforceSubmitEditor *>(editor);
+ if (!perforceEditor)
+ return true;
QFileInfo editorFile(fileIFace->fileName());
QFileInfo changeFile(m_changeTmpFile->fileName());
if (editorFile.absoluteFilePath() == changeFile.absoluteFilePath()) {
- const QMessageBox::StandardButton answer =
- QMessageBox::question(core->mainWindow(),
- tr("Closing p4 Editor"),
- tr("Do you want to submit this change list?"),
- QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel, QMessageBox::Yes);
- if (answer == QMessageBox::Cancel)
+ // Prompt the user. Force a prompt unless submit was actually invoked (that
+ // is, the editor was closed or shutdown).
+ const VCSBase::VCSBaseSubmitEditor::PromptSubmitResult answer =
+ perforceEditor->promptSubmit(tr("Closing p4 Editor"),
+ tr("Do you want to submit this change list?"),
+ tr("The commit message check failed. Do you want to submit this change list"),
+ !m_submitActionTriggered);
+ m_submitActionTriggered = false;
+
+ if (answer == VCSBase::VCSBaseSubmitEditor::SubmitCanceled)
return false;
core->fileManager()->blockFileChange(fileIFace);
fileIFace->save();
core->fileManager()->unblockFileChange(fileIFace);
- if (answer == QMessageBox::Yes) {
+ if (answer == VCSBase::VCSBaseSubmitEditor::SubmitConfirmed) {
QByteArray change = m_changeTmpFile->readAll();
m_changeTmpFile->close();
if (!checkP4Command()) {
@@ -1007,10 +1020,10 @@ bool PerforcePlugin::editorAboutToClose(Core::IEditor *editor)
m_changeTmpFile = 0;
return false;
}
- QString output = QString::fromUtf8(proc.readAll());
+ const QString output = QString::fromUtf8(proc.readAll());
showOutput(output);
- if (output.contains("Out of date files must be resolved or reverted"), true) {
- QMessageBox::warning(editor->widget(), "Pending change", "Could not submit the change, because your workspace was out of date. Created a pending submit instead.");
+ if (output.contains(QLatin1String("Out of date files must be resolved or reverted)"))) {
+ QMessageBox::warning(editor->widget(), tr("Pending change"), tr("Could not submit the change, because your workspace was out of date. Created a pending submit instead."));
}
QApplication::restoreOverrideCursor();
}
diff --git a/src/plugins/perforce/perforceplugin.h b/src/plugins/perforce/perforceplugin.h
index 919ab0c6d0..8ac7188994 100644
--- a/src/plugins/perforce/perforceplugin.h
+++ b/src/plugins/perforce/perforceplugin.h
@@ -190,6 +190,7 @@ private:
QAction *m_filelogCurrentAction;
QAction *m_filelogAction;
QAction *m_submitCurrentLogAction;
+ bool m_submitActionTriggered;
QAction *m_diffSelectedFiles;
QAction *m_undoAction;
@@ -232,7 +233,7 @@ private:
PerforceVersionControl *m_versionControl;
PerforceSettings m_settings;
- friend class PerforceOutputWindow;
+ friend class PerforceOutputWindow; // needs openFiles()
};
} // namespace Perforce
diff --git a/src/plugins/projectexplorer/environment.cpp b/src/plugins/projectexplorer/environment.cpp
index 0c2e74f67e..541445cf99 100644
--- a/src/plugins/projectexplorer/environment.cpp
+++ b/src/plugins/projectexplorer/environment.cpp
@@ -288,6 +288,16 @@ void Environment::modify(const QList<EnvironmentItem> & list)
*this = resultEnvironment;
}
+bool Environment::operator!=(const Environment &other)
+{
+ return !(*this == other);
+}
+
+bool Environment::operator==(const Environment &other)
+{
+ return m_values == other.m_values;
+}
+
QStringList Environment::parseCombinedArgString(const QString &program)
{
QStringList args;
@@ -341,3 +351,5 @@ QString Environment::joinArgumentList(const QStringList &arguments)
return result;
}
+
+
diff --git a/src/plugins/projectexplorer/environment.h b/src/plugins/projectexplorer/environment.h
index 91cd958d4b..367aee5a80 100644
--- a/src/plugins/projectexplorer/environment.h
+++ b/src/plugins/projectexplorer/environment.h
@@ -89,6 +89,8 @@ public:
static QStringList parseCombinedArgString(const QString &program);
static QString joinArgumentList(const QStringList &arguments);
+ bool operator!=(const Environment &other);
+ bool operator==(const Environment &other);
private:
QMap<QString, QString> m_values;
};
diff --git a/src/plugins/projectexplorer/toolchain.cpp b/src/plugins/projectexplorer/toolchain.cpp
index 7c080aad8e..e827a5a3d4 100644
--- a/src/plugins/projectexplorer/toolchain.cpp
+++ b/src/plugins/projectexplorer/toolchain.cpp
@@ -246,13 +246,13 @@ QList<HeaderPath> MSVCToolChain::systemHeaderPaths()
void MSVCToolChain::addToEnvironment(ProjectExplorer::Environment &env)
{
- if (!m_valuesSet) {
+ if (!m_valuesSet || env != m_lastEnvironment) {
+ m_lastEnvironment = env;
QSettings registry("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VS7",
QSettings::NativeFormat);
if (m_name.isEmpty())
return;
QString path = registry.value(m_name).toString();
- ProjectExplorer::Environment oldEnv(env);
QString desc;
QString varsbat = path + "Common7\\Tools\\vsvars32.bat";
if (QFileInfo(varsbat).exists()) {
@@ -265,7 +265,8 @@ void MSVCToolChain::addToEnvironment(ProjectExplorer::Environment &env)
tf.flush();
tf.waitForBytesWritten(30000);
- QProcess run; // TODO run in the environment we want to add to...
+ QProcess run;
+ run.setEnvironment(env.toStringList());
QString cmdPath = env.searchInPath("cmd");
run.start(cmdPath, QStringList()<<"/c"<<filename);
run.waitForFinished();
@@ -281,9 +282,7 @@ void MSVCToolChain::addToEnvironment(ProjectExplorer::Environment &env)
if (regexp.exactMatch(line2)) {
QString variable = regexp.cap(1);
QString value = regexp.cap(2);
- value.replace('%' + variable + '%', oldEnv.value(variable));
m_values.append(QPair<QString, QString>(variable, value));
-
}
}
vars.close();
@@ -293,14 +292,11 @@ void MSVCToolChain::addToEnvironment(ProjectExplorer::Environment &env)
m_valuesSet = true;
}
- //qDebug()<<"MSVC Environment:";
QList< QPair<QString, QString> >::const_iterator it, end;
end = m_values.constEnd();
for (it = m_values.constBegin(); it != end; ++it) {
env.set((*it).first, (*it).second);
- //qDebug()<<"variable:"<<(*it).first<<"value:"<<(*it).second;
}
-
}
QString MSVCToolChain::makeCommand() const
diff --git a/src/plugins/projectexplorer/toolchain.h b/src/plugins/projectexplorer/toolchain.h
index a977c125bf..813092d7bc 100644
--- a/src/plugins/projectexplorer/toolchain.h
+++ b/src/plugins/projectexplorer/toolchain.h
@@ -119,6 +119,7 @@ protected:
private:
mutable QList<QPair<QString, QString> > m_values;
mutable bool m_valuesSet;
+ mutable ProjectExplorer::Environment m_lastEnvironment;
};
// TODO some stuff needs to be moved into here
diff --git a/src/plugins/qt4projectmanager/qt4nodes.h b/src/plugins/qt4projectmanager/qt4nodes.h
index 7e663fc34b..e94b08e67a 100644
--- a/src/plugins/qt4projectmanager/qt4nodes.h
+++ b/src/plugins/qt4projectmanager/qt4nodes.h
@@ -98,7 +98,8 @@ class Qt4PriFileNode;
class Qt4ProFileNode;
// Implements ProjectNode for qt4 pro files
-class Qt4PriFileNode : public ProjectExplorer::ProjectNode {
+class Qt4PriFileNode : public ProjectExplorer::ProjectNode
+{
Q_OBJECT
Q_DISABLE_COPY(Qt4PriFileNode)
public:
@@ -164,7 +165,8 @@ private:
};
// Implements ProjectNode for qt4 pro files
-class Qt4ProFileNode : public Qt4PriFileNode {
+class Qt4ProFileNode : public Qt4PriFileNode
+{
Q_OBJECT
Q_DISABLE_COPY(Qt4ProFileNode)
public:
@@ -208,7 +210,8 @@ private:
friend class Qt4NodeHierarchy;
};
-class Qt4NodesWatcher : public ProjectExplorer::NodesWatcher {
+class Qt4NodesWatcher : public ProjectExplorer::NodesWatcher
+{
Q_OBJECT
Q_DISABLE_COPY(Qt4NodesWatcher)
public:
diff --git a/src/plugins/qt4projectmanager/qt4project.h b/src/plugins/qt4projectmanager/qt4project.h
index df23a18ba3..3351d14813 100644
--- a/src/plugins/qt4projectmanager/qt4project.h
+++ b/src/plugins/qt4projectmanager/qt4project.h
@@ -78,8 +78,7 @@ class Qt4Manager;
class Qt4Project;
class Qt4RunStep;
-class Qt4ProjectFile
- : public Core::IFile
+class Qt4ProjectFile : public Core::IFile
{
Q_OBJECT
@@ -108,8 +107,7 @@ private:
QString m_filePath;
};
-class Qt4Project
- : public ProjectExplorer::Project
+class Qt4Project : public ProjectExplorer::Project
{
Q_OBJECT
diff --git a/src/plugins/qt4projectmanager/qt4runconfiguration.cpp b/src/plugins/qt4projectmanager/qt4runconfiguration.cpp
index 09e1827c7a..f77bc917c4 100644
--- a/src/plugins/qt4projectmanager/qt4runconfiguration.cpp
+++ b/src/plugins/qt4projectmanager/qt4runconfiguration.cpp
@@ -344,11 +344,8 @@ void Qt4RunConfiguration::updateTarget()
#if defined (Q_OS_MAC)
if (reader->values("CONFIG").contains("app_bundle")) {
- QString qmakeBuildConfig = "release";
- if (projectBuildConfiguration & QtVersion::DebugBuild)
- qmakeBuildConfig = "debug";
m_workingDir += QLatin1Char('/')
- + qmakeBuildConfig
+ + reader->value("TARGET")
+ QLatin1String(".app/Contents/MacOS");
}
#endif
diff --git a/src/plugins/qt4projectmanager/qtversionmanager.cpp b/src/plugins/qt4projectmanager/qtversionmanager.cpp
index 013e7b1ca7..0c968b8485 100644
--- a/src/plugins/qt4projectmanager/qtversionmanager.cpp
+++ b/src/plugins/qt4projectmanager/qtversionmanager.cpp
@@ -204,7 +204,7 @@ void QtVersionManager::writeVersionsIntoSettings()
{
QSettings *s = Core::ICore::instance()->settings();
s->setValue(defaultQtVersionKey, m_defaultVersion);
- s->beginWriteArray("QtVersions");
+ s->beginWriteArray(QtVersionsSectionName);
for (int i = 0; i < m_versions.size(); ++i) {
s->setArrayIndex(i);
s->setValue("Name", m_versions.at(i)->name());
@@ -521,8 +521,8 @@ void QtDirWidget::showEnvironmentPage(QTreeWidgetItem *item)
m_ui.msvcLabel->setText("");
} else {
m_ui.msvcComboBox->setVisible(true);
- m_ui.msvcComboBox->clear();
bool block = m_ui.msvcComboBox->blockSignals(true);
+ m_ui.msvcComboBox->clear();
foreach(const QString &msvcenv, msvcEnvironments) {
m_ui.msvcComboBox->addItem(msvcenv);
if (msvcenv == m_versions.at(index)->msvcVersion()) {
@@ -1235,7 +1235,6 @@ void QtVersion::addToEnvironment(Environment &env)
// add libdir, includedir and bindir
// or add Mingw dirs
// or do nothing on other
-
}
int QtVersion::uniqueId() const
diff --git a/src/plugins/subversion/subversionplugin.cpp b/src/plugins/subversion/subversionplugin.cpp
index 67e56eacf6..064bb08693 100644
--- a/src/plugins/subversion/subversionplugin.cpp
+++ b/src/plugins/subversion/subversionplugin.cpp
@@ -188,7 +188,8 @@ SubversionPlugin::SubversionPlugin() :
m_submitCurrentLogAction(0),
m_submitDiffAction(0),
m_submitUndoAction(0),
- m_submitRedoAction(0)
+ m_submitRedoAction(0),
+ m_submitActionTriggered(false)
{
}
@@ -463,15 +464,18 @@ bool SubversionPlugin::editorAboutToClose(Core::IEditor *iEditor)
if (editorFile.absoluteFilePath() != changeFile.absoluteFilePath())
return true; // Oops?!
- // Prompt user.
- const QMessageBox::StandardButton answer = QMessageBox::question(
- Core::ICore::instance()->mainWindow(), tr("Closing Subversion Editor"),
- tr("Do you want to commit the change?"),
- QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel, QMessageBox::Yes);
+ // Prompt user. Force a prompt unless submit was actually invoked (that
+ // is, the editor was closed or shutdown).
+ const VCSBase::VCSBaseSubmitEditor::PromptSubmitResult answer =
+ editor->promptSubmit(tr("Closing Subversion Editor"),
+ tr("Do you want to commit the change?"),
+ tr("The commit message check failed. Do you want to commit the change?"),
+ !m_submitActionTriggered);
+ m_submitActionTriggered = false;
switch (answer) {
- case QMessageBox::Cancel:
+ case VCSBase::VCSBaseSubmitEditor::SubmitCanceled:
return false; // Keep editing and change file
- case QMessageBox::No:
+ case VCSBase::VCSBaseSubmitEditor::SubmitDiscarded:
cleanChangeTmpFile();
return true; // Cancel all
default:
@@ -922,6 +926,7 @@ void SubversionPlugin::slotDescribe()
void SubversionPlugin::submitCurrentLog()
{
+ m_submitActionTriggered = true;
Core::EditorManager::instance()->closeEditors(QList<Core::IEditor*>()
<< Core::EditorManager::instance()->currentEditor());
}
diff --git a/src/plugins/subversion/subversionplugin.h b/src/plugins/subversion/subversionplugin.h
index a9dbd5ca65..1611db8f2b 100644
--- a/src/plugins/subversion/subversionplugin.h
+++ b/src/plugins/subversion/subversionplugin.h
@@ -168,6 +168,7 @@ private:
QAction *m_submitDiffAction;
QAction *m_submitUndoAction;
QAction *m_submitRedoAction;
+ bool m_submitActionTriggered;
static const char * const SUBVERSION_MENU;
static const char * const ADD;
diff --git a/src/plugins/texteditor/basetexteditor.cpp b/src/plugins/texteditor/basetexteditor.cpp
index e5fb77e259..6574d41631 100644
--- a/src/plugins/texteditor/basetexteditor.cpp
+++ b/src/plugins/texteditor/basetexteditor.cpp
@@ -128,12 +128,11 @@ ITextEditor *BaseTextEditor::openEditorAt(const QString &fileName,
const QString &editorKind)
{
Core::EditorManager *editorManager = Core::EditorManager::instance();
- editorManager->addCurrentPositionToNavigationHistory(true);
+ editorManager->addCurrentPositionToNavigationHistory();
Core::IEditor *editor = editorManager->openEditor(fileName, editorKind, Core::EditorManager::IgnoreNavigationHistory);
TextEditor::ITextEditor *texteditor = qobject_cast<TextEditor::ITextEditor *>(editor);
if (texteditor) {
texteditor->gotoLine(line, column);
- editorManager->addCurrentPositionToNavigationHistory();
return texteditor;
}
return 0;
@@ -749,7 +748,6 @@ void BaseTextEditor::cleanWhitespace()
void BaseTextEditor::keyPressEvent(QKeyEvent *e)
{
-
d->clearVisibleCollapsedBlock();
QKeyEvent *original_e = e;
@@ -763,8 +761,6 @@ void BaseTextEditor::keyPressEvent(QKeyEvent *e)
return;
}
- d->m_contentsChanged = false;
-
bool ro = isReadOnly();
if (d->m_inBlockSelectionMode) {
@@ -965,6 +961,7 @@ void BaseTextEditor::setTextCursor(const QTextCursor &cursor)
void BaseTextEditor::gotoLine(int line, int column)
{
+ d->m_lastCursorChangeWasInteresting = false; // avoid adding the previous position to history
const int blockNumber = line - 1;
const QTextBlock &block = document()->findBlockByNumber(blockNumber);
if (block.isValid()) {
@@ -981,6 +978,7 @@ void BaseTextEditor::gotoLine(int line, int column)
setTextCursor(cursor);
centerCursor();
}
+ saveCurrentCursorPositionForNavigation();
}
int BaseTextEditor::position(ITextEditor::PositionOperation posOp, int at) const
@@ -1033,6 +1031,7 @@ QChar BaseTextEditor::characterAt(int pos) const
bool BaseTextEditor::event(QEvent *e)
{
+ d->m_contentsChanged = false;
switch (e->type()) {
case QEvent::ShortcutOverride:
e->ignore(); // we are a really nice citizen
@@ -1116,9 +1115,11 @@ bool BaseTextEditor::restoreState(const QByteArray &state)
stream >> hval;
stream >> lval;
stream >> cval;
+ d->m_lastCursorChangeWasInteresting = false; // avoid adding last position to history
gotoLine(lval, cval);
verticalScrollBar()->setValue(vval);
horizontalScrollBar()->setValue(hval);
+ saveCurrentCursorPositionForNavigation();
return true;
}
@@ -1250,6 +1251,7 @@ int BaseTextEditor::visibleWrapColumn() const
BaseTextEditorPrivate::BaseTextEditorPrivate()
:
m_contentsChanged(false),
+ m_lastCursorChangeWasInteresting(false),
m_document(new BaseTextDocument()),
m_parenthesesMatchingEnabled(false),
m_extraArea(0),
@@ -1435,6 +1437,7 @@ QRectF TextEditDocumentLayout::blockBoundingRect(const QTextBlock &block) const
bool BaseTextEditor::viewportEvent(QEvent *event)
{
+ d->m_contentsChanged = false;
if (event->type() == QEvent::ContextMenu) {
const QContextMenuEvent *ce = static_cast<QContextMenuEvent*>(event);
if (ce->reason() == QContextMenuEvent::Mouse && !textCursor().hasSelection())
@@ -2321,8 +2324,20 @@ void BaseTextEditor::slotUpdateRequest(const QRect &r, int dy)
slotUpdateExtraAreaWidth();
}
+void BaseTextEditor::saveCurrentCursorPositionForNavigation()
+{
+ d->m_lastCursorChangeWasInteresting = true;
+ d->m_tempState = saveState();
+}
+
void BaseTextEditor::slotCursorPositionChanged()
{
+ if (!d->m_contentsChanged && d->m_lastCursorChangeWasInteresting) {
+ Core::EditorManager::instance()->addCurrentPositionToNavigationHistory(d->m_tempState);
+ d->m_lastCursorChangeWasInteresting = false;
+ } else if (d->m_contentsChanged) {
+ saveCurrentCursorPositionForNavigation();
+ }
QList<QTextEdit::ExtraSelection> extraSelections;
setExtraSelections(ParenthesesMatchingSelection, extraSelections); // clear
if (d->m_parenthesesMatchingEnabled)
diff --git a/src/plugins/texteditor/basetexteditor.h b/src/plugins/texteditor/basetexteditor.h
index 1813f4e4a9..8c10618134 100644
--- a/src/plugins/texteditor/basetexteditor.h
+++ b/src/plugins/texteditor/basetexteditor.h
@@ -454,6 +454,7 @@ private:
void handleHomeKey(bool anchor);
void handleBackspaceKey();
void moveLineUpDown(bool up);
+ void saveCurrentCursorPositionForNavigation();
void toggleBlockVisible(const QTextBlock &block);
QRect collapseBox(const QTextBlock &block);
@@ -498,7 +499,7 @@ public:
int currentLine() const;
int currentColumn() const;
- inline void gotoLine(int line, int column = 0) { e->gotoLine(line, column); }
+ void gotoLine(int line, int column = 0) { e->gotoLine(line, column); }
inline int position(
ITextEditor::PositionOperation posOp = ITextEditor::Current
diff --git a/src/plugins/texteditor/basetexteditor_p.h b/src/plugins/texteditor/basetexteditor_p.h
index 9609d3c6ea..638f2faba2 100644
--- a/src/plugins/texteditor/basetexteditor_p.h
+++ b/src/plugins/texteditor/basetexteditor_p.h
@@ -140,6 +140,7 @@ public:
BaseTextEditor *q;
bool m_contentsChanged;
+ bool m_lastCursorChangeWasInteresting;
QList<QTextEdit::ExtraSelection> m_syntaxHighlighterSelections;
QTextEdit::ExtraSelection m_lineSelection;
diff --git a/src/plugins/texteditor/linenumberfilter.cpp b/src/plugins/texteditor/linenumberfilter.cpp
index f7cb55cbc6..711f8eb9da 100644
--- a/src/plugins/texteditor/linenumberfilter.cpp
+++ b/src/plugins/texteditor/linenumberfilter.cpp
@@ -62,9 +62,8 @@ void LineNumberFilter::accept(FilterEntry selection) const
if (editor) {
Core::EditorManager *editorManager = Core::EditorManager::instance();
editorManager->ensureEditorManagerVisible();
- editorManager->addCurrentPositionToNavigationHistory(true);
- editor->gotoLine(selection.internalData.toInt());
editorManager->addCurrentPositionToNavigationHistory();
+ editor->gotoLine(selection.internalData.toInt());
editor->widget()->setFocus();
}
}
diff --git a/src/plugins/vcsbase/nicknamedialog.cpp b/src/plugins/vcsbase/nicknamedialog.cpp
new file mode 100644
index 0000000000..d6a10ad302
--- /dev/null
+++ b/src/plugins/vcsbase/nicknamedialog.cpp
@@ -0,0 +1,270 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+**
+**************************************************************************/
+
+#include "nicknamedialog.h"
+#include "vcsbaseplugin.h"
+#include "ui_nicknamedialog.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QFile>
+#include <QtGui/QPushButton>
+#include <QtGui/QStandardItemModel>
+#include <QtGui/QSortFilterProxyModel>
+
+enum { NickNameRole = Qt::UserRole + 1 };
+
+namespace VCSBase {
+namespace Internal {
+
+// For code clarity, a struct representing the entries of a mail map file
+// with parse and model functions.
+struct NickNameEntry {
+ void clear();
+ bool parse(const QString &);
+ QString nickName() const;
+ QList<QStandardItem *> toModelRow() const;
+ static QString nickNameOf(const QStandardItem *item);
+
+ QString name;
+ QString email;
+ QString aliasName;
+ QString aliasEmail;
+};
+
+void NickNameEntry::clear()
+{
+ name.clear();
+ email.clear();
+ aliasName.clear();
+ aliasEmail.clear();
+}
+
+// Parse "Hans Mustermann <HM@acme.de> [Alias [<alias@acme.de>]]"
+
+bool NickNameEntry::parse(const QString &l)
+{
+ clear();
+ const QChar lessThan = QLatin1Char('<');
+ const QChar greaterThan = QLatin1Char('>');
+ // Get first name/mail pair
+ int mailPos = l.indexOf(lessThan);
+ if (mailPos == -1)
+ return false;
+ name = l.mid(0, mailPos).trimmed();
+ mailPos++;
+ const int mailEndPos = l.indexOf(greaterThan, mailPos);
+ if (mailEndPos == -1)
+ return false;
+ email = l.mid(mailPos, mailEndPos - mailPos);
+ // get optional 2nd name/mail pair
+ const int aliasNameStart = mailEndPos + 1;
+ if (aliasNameStart >= l.size())
+ return true;
+ int aliasMailPos = l.indexOf(lessThan, aliasNameStart);
+ if (aliasMailPos == -1) {
+ aliasName =l.mid(aliasNameStart, l.size() - aliasNameStart).trimmed();
+ return true;
+ }
+ aliasName = l.mid(aliasNameStart, aliasMailPos - aliasNameStart).trimmed();
+ aliasMailPos++;
+ const int aliasMailEndPos = l.indexOf(greaterThan, aliasMailPos);
+ if (aliasMailEndPos == -1)
+ return true;
+ aliasEmail = l.mid(aliasMailPos, aliasMailEndPos - aliasMailPos);
+ return true;
+}
+
+// Format "Hans Mustermann <HM@acme.de>"
+static inline QString formatNick(const QString &name, const QString &email)
+{
+ QString rc = name;
+ if (!email.isEmpty()) {
+ rc += QLatin1String(" <");
+ rc += email;
+ rc += QLatin1Char('>');
+ }
+ return rc;
+}
+
+QString NickNameEntry::nickName() const
+{
+ return aliasName.isEmpty() ? formatNick(name, email) : formatNick(aliasName, aliasEmail);
+}
+
+QList<QStandardItem *> NickNameEntry::toModelRow() const
+{
+ const QVariant nickNameData = nickName();
+ QStandardItem *i1 = new QStandardItem(name);
+ i1->setData(nickNameData, NickNameRole);
+ QStandardItem *i2 = new QStandardItem(email);
+ i2->setData(nickNameData, NickNameRole);
+ QStandardItem *i3 = new QStandardItem(aliasName);
+ i3->setData(nickNameData, NickNameRole);
+ QStandardItem *i4 = new QStandardItem(aliasEmail);
+ i4->setData(nickNameData, NickNameRole);
+ QList<QStandardItem *> row;
+ row << i1 << i2 << i3 << i4;
+ return row;
+}
+
+QString NickNameEntry::nickNameOf(const QStandardItem *item)
+{
+ return item->data(NickNameRole).toString();
+}
+
+QDebug operator<<(QDebug d, const NickNameEntry &e)
+{
+ d.nospace() << "Name='" << e.name << "' Mail='" << e.email
+ << " Alias='" << e.aliasName << " AliasEmail='" << e.aliasEmail << "'\n";
+ return d;
+}
+
+// Globally cached model tacked onto the plugin.
+static QStandardItemModel *nickModel()
+{
+ static QStandardItemModel *model = 0;
+ if (!model) {
+ model = new QStandardItemModel(VCSBasePlugin::instance());
+ QStringList headers;
+ headers << NickNameDialog::tr("Name")
+ << NickNameDialog::tr("E-mail")
+ << NickNameDialog::tr("Alias")
+ << NickNameDialog::tr("Alias e-mail");
+ model->setHorizontalHeaderLabels(headers);
+ }
+ return model;
+}
+
+static inline void clearModel(QStandardItemModel *model)
+{
+ if (const int rowCount = model->rowCount())
+ model->removeRows(0, rowCount);
+}
+
+NickNameDialog::NickNameDialog(QWidget *parent) :
+ QDialog(parent),
+ m_ui(new Ui::NickNameDialog),
+ m_filterModel(new QSortFilterProxyModel(this))
+{
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+ m_ui->setupUi(this);
+ okButton()->setEnabled(false);
+
+ // Populate model and grow tree to accommodate it
+ m_filterModel->setSourceModel(nickModel());
+ m_filterModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
+ m_ui->filterTreeView->setModel(m_filterModel);
+ const int columnCount = m_filterModel->columnCount();
+ int treeWidth = 0;
+ for (int c = 0; c < columnCount; c++) {
+ m_ui->filterTreeView->resizeColumnToContents(c);
+ treeWidth += m_ui->filterTreeView->columnWidth(c);
+ }
+ m_ui->filterTreeView->setMinimumWidth(treeWidth + 20);
+ connect(m_ui->filterTreeView, SIGNAL(doubleClicked(QModelIndex)), this,
+ SLOT(slotDoubleClicked(QModelIndex)));
+ connect(m_ui->filterTreeView->selectionModel(), SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
+ this, SLOT(slotCurrentItemChanged(QModelIndex)));
+ connect(m_ui->filterLineEdit, SIGNAL(textChanged(QString)),
+ m_filterModel, SLOT(setFilterFixedString(QString)));
+}
+
+NickNameDialog::~NickNameDialog()
+{
+ delete m_ui;
+}
+
+QPushButton *NickNameDialog::okButton() const
+{
+ return m_ui->buttonBox->button(QDialogButtonBox::Ok);
+}
+
+void NickNameDialog::slotCurrentItemChanged(const QModelIndex &index)
+{
+ okButton()->setEnabled(index.isValid());
+}
+
+void NickNameDialog::slotDoubleClicked(const QModelIndex &)
+{
+ if (okButton()->isEnabled())
+ okButton()->animateClick();
+}
+
+QString NickNameDialog::nickName() const
+{
+ const QModelIndex index = m_ui->filterTreeView->selectionModel()->currentIndex();
+ if (index.isValid()) {
+ const QModelIndex sourceIndex = m_filterModel->mapToSource(index);
+ if (const QStandardItem *item = nickModel()->itemFromIndex(sourceIndex))
+ return NickNameEntry::nickNameOf(item);
+ }
+ return QString();
+}
+
+void NickNameDialog::clearNickNames()
+{
+ clearModel(nickModel());
+}
+
+bool NickNameDialog::readNickNamesFromMailCapFile(const QString &fileName, QString *errorMessage)
+{
+ QFile file(fileName);
+ if (!file.open(QIODevice::ReadOnly|QIODevice::Text)) {
+ *errorMessage = tr("Cannot open '%1': %2").arg(fileName, file.errorString());
+ return false;
+ }
+ QStandardItemModel *model = nickModel();
+ clearModel(model);
+ // Split into lines and read
+ NickNameEntry entry;
+ const QStringList lines = QString::fromUtf8(file.readAll()).trimmed().split(QLatin1Char('\n'));
+ const int count = lines.size();
+ for (int i = 0; i < count; i++) {
+ if (entry.parse(lines.at(i))) {
+ model->appendRow(entry.toModelRow());
+ } else {
+ qWarning("%s: Invalid mail cap entry at line %d: '%s'\n", qPrintable(fileName), i + 1, qPrintable(lines.at(i)));
+ }
+ }
+ model->sort(0);
+ return true;
+}
+
+QStringList NickNameDialog::nickNameList()
+{
+ QStringList rc;
+ const QStandardItemModel *model = nickModel();
+ const int rowCount = model->rowCount();
+ for (int r = 0; r < rowCount; r++)
+ rc.push_back(NickNameEntry::nickNameOf(model->item(r, 0)));
+ return rc;
+}
+
+}
+}
diff --git a/src/plugins/vcsbase/nicknamedialog.h b/src/plugins/vcsbase/nicknamedialog.h
new file mode 100644
index 0000000000..7c64410577
--- /dev/null
+++ b/src/plugins/vcsbase/nicknamedialog.h
@@ -0,0 +1,83 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+**
+**************************************************************************/
+
+#ifndef NICKNAMEDIALOG_H
+#define NICKNAMEDIALOG_H
+
+#include <QtGui/QDialog>
+
+QT_BEGIN_NAMESPACE
+namespace Ui {
+ class NickNameDialog;
+}
+class QSortFilterProxyModel;
+class QModelIndex;
+class QPushButton;
+QT_END_NAMESPACE
+
+namespace VCSBase {
+namespace Internal {
+
+/* Nick name dialog: Manages a list of users read from an extended
+ * mail cap file, consisting of 4 columns:
+ * "Name Mail [AliasName [AliasMail]]".
+ * The names can be used for insertion into "RevBy:" fields; aliases will
+ * be preferred. The static functions to read/clear the mail map
+ * files access a global model which is shared by all instances of the
+ * dialog to achieve updating. */
+
+class NickNameDialog : public QDialog {
+ Q_OBJECT
+public:
+ explicit NickNameDialog(QWidget *parent = 0);
+ virtual ~NickNameDialog();
+
+ QString nickName() const;
+
+ // Fill/clear the global nick name cache
+ static bool readNickNamesFromMailCapFile(const QString &file, QString *errorMessage);
+ static void clearNickNames();
+ // Return a list for a completer on the field line edits
+ static QStringList nickNameList();
+
+private slots:
+ void slotCurrentItemChanged(const QModelIndex &);
+ void slotDoubleClicked(const QModelIndex &);
+
+private:
+ QPushButton *okButton() const;
+
+ Ui::NickNameDialog *m_ui;
+ QSortFilterProxyModel *m_filterModel;
+};
+
+} // namespace Internal
+} // namespace VCSBase
+
+#endif // NICKNAMEDIALOG_H
diff --git a/src/plugins/vcsbase/nicknamedialog.ui b/src/plugins/vcsbase/nicknamedialog.ui
new file mode 100644
index 0000000000..6d7217d700
--- /dev/null
+++ b/src/plugins/vcsbase/nicknamedialog.ui
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>NickNameDialog</class>
+ <widget class="QDialog" name="NickNameDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>618</width>
+ <height>414</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Nick Names</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="filterLabel">
+ <property name="text">
+ <string>Filter:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="filterLineEdit"/>
+ </item>
+ <item>
+ <widget class="QToolButton" name="filterClearToolButton">
+ <property name="text">
+ <string>Clear</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QTreeView" name="filterTreeView"/>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>NickNameDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>252</x>
+ <y>405</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>NickNameDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>293</x>
+ <y>405</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>filterClearToolButton</sender>
+ <signal>clicked()</signal>
+ <receiver>filterLineEdit</receiver>
+ <slot>clear()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>263</x>
+ <y>14</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>198</x>
+ <y>19</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/plugins/vcsbase/vcsbase.pro b/src/plugins/vcsbase/vcsbase.pro
index d34fe84e7c..58bbc0dd4e 100644
--- a/src/plugins/vcsbase/vcsbase.pro
+++ b/src/plugins/vcsbase/vcsbase.pro
@@ -14,7 +14,11 @@ HEADERS += vcsbase_global.h \
basevcseditorfactory.h \
submiteditorfile.h \
basevcssubmiteditorfactory.h \
- submitfilemodel.h
+ submitfilemodel.h \
+ vcsbasesettings.h \
+ vcsbasesettingspage.h \
+ nicknamedialog.h
+
SOURCES += vcsbaseplugin.cpp \
baseannotationhighlighter.cpp \
diffhighlighter.cpp \
@@ -24,5 +28,12 @@ SOURCES += vcsbaseplugin.cpp \
basevcseditorfactory.cpp \
submiteditorfile.cpp \
basevcssubmiteditorfactory.cpp \
- submitfilemodel.cpp
-RESOURCES = vcsbase.qrc
+ submitfilemodel.cpp \
+ vcsbasesettings.cpp \
+ vcsbasesettingspage.cpp \
+ nicknamedialog.cpp
+
+RESOURCES += vcsbase.qrc
+
+FORMS += vcsbasesettingspage.ui \
+ nicknamedialog.ui
diff --git a/src/plugins/vcsbase/vcsbaseconstants.h b/src/plugins/vcsbase/vcsbaseconstants.h
index 6ce3141cb6..bb180213fb 100644
--- a/src/plugins/vcsbase/vcsbaseconstants.h
+++ b/src/plugins/vcsbase/vcsbaseconstants.h
@@ -36,6 +36,7 @@ namespace VCSBase {
namespace Constants {
const char * const VCS_SETTINGS_CATEGORY = QT_TRANSLATE_NOOP("VCSBase", "Version Control System");
+const char * const VCS_COMMON_SETTINGS_ID = QT_TRANSLATE_NOOP("VCSBase", "Common");
namespace Internal {
enum { debug = 0 };
diff --git a/src/plugins/vcsbase/vcsbaseeditor.cpp b/src/plugins/vcsbase/vcsbaseeditor.cpp
index 2376f3b83e..d185efa9b0 100644
--- a/src/plugins/vcsbase/vcsbaseeditor.cpp
+++ b/src/plugins/vcsbase/vcsbaseeditor.cpp
@@ -265,9 +265,8 @@ void VCSBaseEditor::slotDiffBrowse(int index)
return;
const int lineNumber = d->m_diffSections.at(index);
Core::EditorManager *editorManager = Core::EditorManager::instance();
- editorManager->addCurrentPositionToNavigationHistory(true);
- gotoLine(lineNumber + 1, 0); // TextEdit uses 1..n convention
editorManager->addCurrentPositionToNavigationHistory();
+ gotoLine(lineNumber + 1, 0); // TextEdit uses 1..n convention
}
// Locate a line number in the list of diff sections.
diff --git a/src/plugins/vcsbase/vcsbaseplugin.cpp b/src/plugins/vcsbase/vcsbaseplugin.cpp
index 1aa9a32ff6..0de678e80e 100644
--- a/src/plugins/vcsbase/vcsbaseplugin.cpp
+++ b/src/plugins/vcsbase/vcsbaseplugin.cpp
@@ -29,6 +29,7 @@
#include "vcsbaseplugin.h"
#include "diffhighlighter.h"
+#include "vcsbasesettingspage.h"
#include <coreplugin/icore.h>
#include <coreplugin/coreconstants.h>
@@ -42,7 +43,8 @@ namespace Internal {
VCSBasePlugin *VCSBasePlugin::m_instance = 0;
-VCSBasePlugin::VCSBasePlugin()
+VCSBasePlugin::VCSBasePlugin() :
+ m_settingsPage(0)
{
m_instance = this;
}
@@ -61,6 +63,8 @@ bool VCSBasePlugin::initialize(const QStringList &arguments, QString *errorMessa
if (!core->mimeDatabase()->addMimeTypes(QLatin1String(":/vcsbase/VCSBase.mimetypes.xml"), errorMessage))
return false;
+ m_settingsPage = new VCSBaseSettingsPage;
+ addAutoReleasedObject(m_settingsPage);
return true;
}
@@ -73,6 +77,11 @@ VCSBasePlugin *VCSBasePlugin::instance()
return m_instance;
}
+VCSBaseSettings VCSBasePlugin::settings() const
+{
+ return m_settingsPage->settings();
+}
+
} // namespace Internal
} // namespace VCSBase
diff --git a/src/plugins/vcsbase/vcsbaseplugin.h b/src/plugins/vcsbase/vcsbaseplugin.h
index 0adbd5b8a6..7b845a3055 100644
--- a/src/plugins/vcsbase/vcsbaseplugin.h
+++ b/src/plugins/vcsbase/vcsbaseplugin.h
@@ -37,6 +37,9 @@
namespace VCSBase {
namespace Internal {
+struct VCSBaseSettings;
+class VCSBaseSettingsPage;
+
class VCSBasePlugin : public ExtensionSystem::IPlugin
{
Q_OBJECT
@@ -51,8 +54,11 @@ public:
static VCSBasePlugin *instance();
+ VCSBaseSettings settings() const;
+
private:
static VCSBasePlugin *m_instance;
+ VCSBaseSettingsPage *m_settingsPage;
};
} // namespace Internal
diff --git a/src/plugins/vcsbase/vcsbasesettings.cpp b/src/plugins/vcsbase/vcsbasesettings.cpp
new file mode 100644
index 0000000000..d2f6951bbd
--- /dev/null
+++ b/src/plugins/vcsbase/vcsbasesettings.cpp
@@ -0,0 +1,78 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+**
+**************************************************************************/
+
+#include "vcsbasesettings.h"
+
+#include <QtCore/QSettings>
+#include <QtCore/QDebug>
+
+static const char *settingsGroupC = "VCS";
+static const char *nickNameMailMapKeyC = "NickNameMailMap";
+static const char *nickNameFieldListFileKeyC = "NickNameFieldListFile";
+static const char *promptForSubmitKeyC = "PromptForSubmit";
+static const char *submitMessageCheckScriptKeyC = "SubmitMessageCheckScript";
+
+namespace VCSBase {
+namespace Internal {
+
+VCSBaseSettings::VCSBaseSettings() :
+ promptForSubmit(true)
+{
+}
+
+void VCSBaseSettings::toSettings(QSettings *s) const
+{
+ s->beginGroup(QLatin1String(settingsGroupC));
+ s->setValue(QLatin1String(nickNameMailMapKeyC), nickNameMailMap);
+ s->setValue(QLatin1String(nickNameFieldListFileKeyC), nickNameFieldListFile);
+ s->setValue(QLatin1String(submitMessageCheckScriptKeyC), submitMessageCheckScript);
+ s->setValue(QLatin1String(promptForSubmitKeyC), promptForSubmit);
+ s->endGroup();
+}
+
+void VCSBaseSettings::fromSettings(QSettings *s)
+{
+ s->beginGroup(QLatin1String(settingsGroupC));
+ nickNameMailMap = s->value(QLatin1String(nickNameMailMapKeyC), QString()).toString();
+ nickNameFieldListFile = s->value(QLatin1String(nickNameFieldListFileKeyC), QString()).toString();
+ submitMessageCheckScript = s->value(QLatin1String(submitMessageCheckScriptKeyC), QString()).toString();
+ promptForSubmit = s->value(QLatin1String(promptForSubmitKeyC), QVariant(true)).toBool();
+ s->endGroup();
+}
+
+bool VCSBaseSettings::equals(const VCSBaseSettings &rhs) const
+{
+ return promptForSubmit == rhs.promptForSubmit
+ && nickNameMailMap == rhs.nickNameMailMap
+ && nickNameFieldListFile == rhs.nickNameFieldListFile
+ && submitMessageCheckScript == rhs.submitMessageCheckScript;
+}
+
+}
+}
diff --git a/src/plugins/vcsbase/vcsbasesettings.h b/src/plugins/vcsbase/vcsbasesettings.h
new file mode 100644
index 0000000000..b4efd59d33
--- /dev/null
+++ b/src/plugins/vcsbase/vcsbasesettings.h
@@ -0,0 +1,66 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+**
+**************************************************************************/
+
+#ifndef VCSBASESETTINGS_H
+#define VCSBASESETTINGS_H
+
+#include <QtCore/QString>
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+class QSettings;
+QT_END_NAMESPACE
+
+namespace VCSBase {
+namespace Internal {
+
+// Common VCS settings, message check script and user nick names.
+struct VCSBaseSettings {
+ VCSBaseSettings();
+
+ bool promptForSubmit;
+
+ QString nickNameMailMap;
+ QString nickNameFieldListFile;
+
+ QString submitMessageCheckScript;
+
+ void toSettings(QSettings *) const;
+ void fromSettings(QSettings *);
+
+ bool equals(const VCSBaseSettings &rhs) const;
+};
+
+inline bool operator==(const VCSBaseSettings &s1, const VCSBaseSettings &s2) { return s1.equals(s2); }
+inline bool operator!=(const VCSBaseSettings &s1, const VCSBaseSettings &s2) { return !s1.equals(s2); }
+
+} // namespace Internal
+} // namespace VCSBase
+
+#endif // VCSBASESETTINGS_H
diff --git a/src/plugins/vcsbase/vcsbasesettingspage.cpp b/src/plugins/vcsbase/vcsbasesettingspage.cpp
new file mode 100644
index 0000000000..0cc528a2e7
--- /dev/null
+++ b/src/plugins/vcsbase/vcsbasesettingspage.cpp
@@ -0,0 +1,145 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+**
+**************************************************************************/
+
+#include "vcsbasesettingspage.h"
+#include "vcsbaseconstants.h"
+#include "nicknamedialog.h"
+
+#include "ui_vcsbasesettingspage.h"
+
+#include <coreplugin/icore.h>
+#include <extensionsystem/pluginmanager.h>
+
+#include <QtCore/QDebug>
+#include <QtCore/QCoreApplication>
+#include <QtGui/QMessageBox>
+
+namespace VCSBase {
+namespace Internal {
+
+// ------------------ VCSBaseSettingsWidget
+
+VCSBaseSettingsWidget::VCSBaseSettingsWidget(QWidget *parent) :
+ QWidget(parent),
+ m_ui(new Ui::VCSBaseSettingsPage)
+{
+ m_ui->setupUi(this);
+ m_ui->submitMessageCheckScriptChooser->setExpectedKind(Core::Utils::PathChooser::Command);
+ m_ui->nickNameFieldsFileChooser->setExpectedKind(Core::Utils::PathChooser::File);
+ m_ui->nickNameMailMapChooser->setExpectedKind(Core::Utils::PathChooser::File);
+}
+
+VCSBaseSettingsWidget::~VCSBaseSettingsWidget()
+{
+ delete m_ui;
+}
+
+VCSBaseSettings VCSBaseSettingsWidget::settings() const
+{
+ VCSBaseSettings rc;
+ rc.nickNameMailMap = m_ui->nickNameMailMapChooser->path();
+ rc.nickNameFieldListFile = m_ui->nickNameFieldsFileChooser->path();
+ rc.submitMessageCheckScript = m_ui->submitMessageCheckScriptChooser->path();
+ rc.promptForSubmit = m_ui->promptForSubmitCheckBox->isChecked();
+ return rc;
+}
+
+void VCSBaseSettingsWidget::setSettings(const VCSBaseSettings &s)
+{
+
+ m_ui->nickNameMailMapChooser->setPath(s.nickNameMailMap);
+ m_ui->nickNameFieldsFileChooser->setPath(s.nickNameFieldListFile);
+ m_ui->submitMessageCheckScriptChooser->setPath(s.submitMessageCheckScript);
+ m_ui->promptForSubmitCheckBox->setChecked(s.promptForSubmit);
+}
+
+// --------------- VCSBaseSettingsPage
+VCSBaseSettingsPage::VCSBaseSettingsPage(QObject *parent) :
+ Core::IOptionsPage(parent)
+{
+ m_settings.fromSettings(Core::ICore::instance()->settings());
+ updateNickNames();
+}
+
+void VCSBaseSettingsPage::updateNickNames()
+{
+ if (m_settings.nickNameMailMap.isEmpty()) {
+ NickNameDialog::clearNickNames();
+ } else {
+ QString errorMessage;
+ if (!NickNameDialog::readNickNamesFromMailCapFile(m_settings.nickNameMailMap, &errorMessage))
+ qWarning("%s", qPrintable(errorMessage));
+ }
+}
+
+VCSBaseSettingsPage::~VCSBaseSettingsPage()
+{
+}
+
+QString VCSBaseSettingsPage::id() const
+{
+ return QLatin1String(Constants::VCS_COMMON_SETTINGS_ID);
+}
+
+QString VCSBaseSettingsPage::trName() const
+{
+ return QCoreApplication::translate("VCSBase", Constants::VCS_COMMON_SETTINGS_ID);
+}
+
+QString VCSBaseSettingsPage::category() const
+{
+ return QLatin1String(Constants::VCS_SETTINGS_CATEGORY);
+}
+
+QString VCSBaseSettingsPage::trCategory() const
+{
+ return QCoreApplication::translate("VCSBase", Constants::VCS_SETTINGS_CATEGORY);
+}
+
+QWidget *VCSBaseSettingsPage::createPage(QWidget *parent)
+{
+ m_widget = new VCSBaseSettingsWidget(parent);
+ m_widget->setSettings(m_settings);
+ return m_widget;
+}
+
+void VCSBaseSettingsPage::apply()
+{
+ if (m_widget) {
+ const VCSBaseSettings newSettings = m_widget->settings();
+ if (newSettings != m_settings) {
+ m_settings = newSettings;
+ m_settings.toSettings(Core::ICore::instance()->settings());
+ updateNickNames();
+ }
+ }
+}
+
+}
+}
diff --git a/src/plugins/vcsbase/vcsbasesettingspage.h b/src/plugins/vcsbase/vcsbasesettingspage.h
new file mode 100644
index 0000000000..4492f66544
--- /dev/null
+++ b/src/plugins/vcsbase/vcsbasesettingspage.h
@@ -0,0 +1,86 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+**
+**************************************************************************/
+
+#ifndef VCSBASESETTINGSPAGE_H
+#define VCSBASESETTINGSPAGE_H
+
+#include "vcsbasesettings.h"
+#include <coreplugin/dialogs/ioptionspage.h>
+#include <QtCore/QPointer>
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+namespace Ui {
+ class VCSBaseSettingsPage;
+}
+QT_END_NAMESPACE
+
+namespace VCSBase {
+namespace Internal {
+
+class VCSBaseSettingsWidget : public QWidget {
+ Q_OBJECT
+public:
+ explicit VCSBaseSettingsWidget(QWidget *parent = 0);
+ virtual ~VCSBaseSettingsWidget();
+
+ VCSBaseSettings settings() const;
+ void setSettings(const VCSBaseSettings &s);
+
+private:
+ Ui::VCSBaseSettingsPage *m_ui;
+};
+
+class VCSBaseSettingsPage : public Core::IOptionsPage
+{
+public:
+ explicit VCSBaseSettingsPage(QObject *parent = 0);
+ virtual ~VCSBaseSettingsPage();
+
+ virtual QString id() const;
+ virtual QString trName() const;
+ virtual QString category() const;
+ virtual QString trCategory() const;
+
+ virtual QWidget *createPage(QWidget *parent);
+ virtual void apply();
+ virtual void finish() { }
+
+ VCSBaseSettings settings() const { return m_settings; }
+
+private:
+ void updateNickNames();
+ QPointer<VCSBaseSettingsWidget> m_widget;
+ VCSBaseSettings m_settings;
+};
+
+} // namespace Internal
+} // namespace VCSBase
+
+#endif // VCSBASESETTINGSPAGE_H
diff --git a/src/plugins/vcsbase/vcsbasesettingspage.ui b/src/plugins/vcsbase/vcsbasesettingspage.ui
new file mode 100644
index 0000000000..01e478f817
--- /dev/null
+++ b/src/plugins/vcsbase/vcsbasesettingspage.ui
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>VCSBaseSettingsPage</class>
+ <widget class="QWidget" name="VCSBaseSettingsPage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>536</width>
+ <height>407</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <layout class="QFormLayout" name="formLayout">
+ <property name="fieldGrowthPolicy">
+ <enum>QFormLayout::ExpandingFieldsGrow</enum>
+ </property>
+ <item row="0" column="0">
+ <widget class="QLabel" name="promptForSubmitLabel">
+ <property name="text">
+ <string>Prompt for submit:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QCheckBox" name="promptForSubmitCheckBox"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="submitMessageCheckScriptLabel">
+ <property name="toolTip">
+ <string>An executable which is called with the submit message in a temporary file as first argument. It should return with an exit != 0 and a message on standard error to indicate failure.</string>
+ </property>
+ <property name="text">
+ <string>Submit message check script:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="Core::Utils::PathChooser" name="submitMessageCheckScriptChooser" native="true"/>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="nickNameMailMapLabel">
+ <property name="toolTip">
+ <string>A file listing user names and email addresses in a 4-column mailmap format:
+name &lt;email&gt; alias &lt;email&gt;</string>
+ </property>
+ <property name="text">
+ <string>User/alias configuration file:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="Core::Utils::PathChooser" name="nickNameMailMapChooser" native="true"/>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="nickNameFieldsFileLabel">
+ <property name="toolTip">
+ <string>A simple file containing lines with field names like &quot;Reviewed-By:&quot; which will be added below the submit editor.</string>
+ </property>
+ <property name="text">
+ <string>User fields configuration file:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="Core::Utils::PathChooser" name="nickNameFieldsFileChooser" native="true"/>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>307</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>Core::Utils::PathChooser</class>
+ <extends>QWidget</extends>
+ <header location="global">utils/pathchooser.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/plugins/vcsbase/vcsbasesubmiteditor.cpp b/src/plugins/vcsbase/vcsbasesubmiteditor.cpp
index 473abaf175..46ae4374cf 100644
--- a/src/plugins/vcsbase/vcsbasesubmiteditor.cpp
+++ b/src/plugins/vcsbase/vcsbasesubmiteditor.cpp
@@ -28,10 +28,14 @@
**************************************************************************/
#include "vcsbasesubmiteditor.h"
+#include "vcsbasesettings.h"
+#include "vcsbaseplugin.h"
+#include "nicknamedialog.h"
#include "submiteditorfile.h"
#include <aggregation/aggregate.h>
#include <coreplugin/ifile.h>
+#include <coreplugin/icore.h>
#include <coreplugin/uniqueidmanager.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <utils/submiteditorwidget.h>
@@ -42,18 +46,31 @@
#include <QtCore/QDebug>
#include <QtCore/QDir>
+#include <QtCore/QTemporaryFile>
+#include <QtCore/QProcess>
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
#include <QtCore/QPointer>
#include <QtCore/QTextStream>
#include <QtGui/QStyle>
#include <QtGui/QToolBar>
+#include <QtGui/QAction>
+#include <QtGui/QApplication>
+#include <QtGui/QMessageBox>
+#include <QtGui/QMainWindow>
+#include <QtGui/QCompleter>
+#include <QtGui/QLineEdit>
enum { debug = 0 };
enum { wantToolBar = 0 };
namespace VCSBase {
+static inline QString submitMessageCheckScript()
+{
+ return Internal::VCSBasePlugin::instance()->settings().submitMessageCheckScript;
+}
+
struct VCSBaseSubmitEditorPrivate
{
VCSBaseSubmitEditorPrivate(const VCSBaseSubmitEditorParameters *parameters,
@@ -69,6 +86,8 @@ struct VCSBaseSubmitEditorPrivate
QPointer<QAction> m_diffAction;
QPointer<QAction> m_submitAction;
+
+ Internal::NickNameDialog *m_nickNameDialog;
};
VCSBaseSubmitEditorPrivate::VCSBaseSubmitEditorPrivate(const VCSBaseSubmitEditorParameters *parameters,
@@ -77,7 +96,8 @@ VCSBaseSubmitEditorPrivate::VCSBaseSubmitEditorPrivate(const VCSBaseSubmitEditor
m_widget(editorWidget),
m_toolWidget(0),
m_parameters(parameters),
- m_file(new VCSBase::Internal::SubmitEditorFile(QLatin1String(m_parameters->mimeType), q))
+ m_file(new VCSBase::Internal::SubmitEditorFile(QLatin1String(m_parameters->mimeType), q)),
+ m_nickNameDialog(0)
{
m_contexts << Core::UniqueIDManager::instance()->uniqueIdentifier(m_parameters->context);
}
@@ -93,6 +113,29 @@ VCSBaseSubmitEditor::VCSBaseSubmitEditor(const VCSBaseSubmitEditorParameters *pa
connect(m_d->m_widget, SIGNAL(diffSelected(QStringList)), this, SLOT(slotDiffSelectedVCSFiles(QStringList)));
connect(m_d->m_widget->descriptionEdit(), SIGNAL(textChanged()), this, SLOT(slotDescriptionChanged()));
+ const Internal::VCSBaseSettings settings = Internal::VCSBasePlugin::instance()->settings();
+ // Add additional context menu settings
+ if (!settings.submitMessageCheckScript.isEmpty() || !settings.nickNameMailMap.isEmpty()) {
+ QAction *sep = new QAction(this);
+ sep->setSeparator(true);
+ m_d->m_widget->addDescriptionEditContextMenuAction(sep);
+ // Run check action
+ if (!settings.submitMessageCheckScript.isEmpty()) {
+ QAction *checkAction = new QAction(tr("Check message"), this);
+ connect(checkAction, SIGNAL(triggered()), this, SLOT(slotCheckSubmitMessage()));
+ m_d->m_widget->addDescriptionEditContextMenuAction(checkAction);
+ }
+ // Insert nick
+ if (!settings.nickNameMailMap.isEmpty()) {
+ QAction *insertAction = new QAction(tr("Insert name..."), this);
+ connect(insertAction, SIGNAL(triggered()), this, SLOT(slotInsertNickName()));
+ m_d->m_widget->addDescriptionEditContextMenuAction(insertAction);
+ }
+ }
+ // Do we have user fields?
+ if (!settings.nickNameFieldListFile.isEmpty())
+ createUserFields(settings.nickNameFieldListFile);
+ connect(m_d->m_widget, SIGNAL(fieldDialogRequested(int)), this, SLOT(slotSetFieldNickName(int)));
Aggregation::Aggregate *aggregate = new Aggregation::Aggregate;
aggregate->add(new Find::BaseTextFind(m_d->m_widget->descriptionEdit()));
aggregate->add(this);
@@ -105,6 +148,26 @@ VCSBaseSubmitEditor::~VCSBaseSubmitEditor()
delete m_d;
}
+void VCSBaseSubmitEditor::createUserFields(const QString &fieldConfigFile)
+{
+ QFile fieldFile(fieldConfigFile);
+ if (!fieldFile.open(QIODevice::ReadOnly|QIODevice::Text)) {
+ qWarning("%s: Unable to open %s: %s", Q_FUNC_INFO, qPrintable(fieldConfigFile), qPrintable(fieldFile.errorString()));
+ return;
+ }
+ // Parse into fields
+ const QStringList fields = QString::fromUtf8(fieldFile.readAll()).trimmed().split(QLatin1Char('\n'));
+ if (fields.empty())
+ return;
+ // Create a completer on user names
+ QCompleter *completer = new QCompleter(Internal::NickNameDialog::nickNameList(), this);
+ foreach(const QString &field, fields) {
+ const QString trimmedField = field.trimmed();
+ if (!trimmedField.isEmpty())
+ m_d->m_widget->addField(trimmedField, true)->setCompleter(completer);
+ }
+}
+
void VCSBaseSubmitEditor::registerActions(QAction *editorUndoAction, QAction *editorRedoAction,
QAction *submitAction, QAction *diffAction)\
{
@@ -139,7 +202,6 @@ void VCSBaseSubmitEditor::setFileListSelectionMode(QAbstractItemView::SelectionM
m_d->m_widget->setFileListSelectionMode(sm);
}
-
void VCSBaseSubmitEditor::slotDescriptionChanged()
{
}
@@ -304,6 +366,131 @@ bool VCSBaseSubmitEditor::setFileContents(const QString &contents)
return true;
}
+enum { checkDialogMinimumWidth = 500 };
+
+VCSBaseSubmitEditor::PromptSubmitResult
+ VCSBaseSubmitEditor::promptSubmit(const QString &title,
+ const QString &question,
+ const QString &checkFailureQuestion,
+ bool forcePrompt) const
+{
+ QString errorMessage;
+ QMessageBox::StandardButton answer = QMessageBox::Yes;
+
+ const bool prompt = forcePrompt || Internal::VCSBasePlugin::instance()->settings().promptForSubmit;
+
+ QWidget *parent = Core::ICore::instance()->mainWindow();
+ // Pop up a message depending on whether the check succeeded and the
+ // user wants to be prompted
+ if (checkSubmitMessage(&errorMessage)) {
+ // Check ok, do prompt?
+ if (prompt) {
+ answer = QMessageBox::question(parent, title, question,
+ QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel,
+ QMessageBox::Yes);
+ }
+ } else {
+ // Check failed.
+ QMessageBox msgBox(QMessageBox::Question, title, checkFailureQuestion,
+ QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel, parent);
+ msgBox.setDefaultButton(QMessageBox::Cancel);
+ msgBox.setInformativeText(errorMessage);
+ msgBox.setMinimumWidth(checkDialogMinimumWidth);
+ answer = static_cast<QMessageBox::StandardButton>(msgBox.exec());
+ }
+ switch (answer) {
+ case QMessageBox::Cancel:
+ return SubmitCanceled;
+ case QMessageBox::No:
+ return SubmitDiscarded;
+ default:
+ break;
+ }
+ return SubmitConfirmed;
+}
+
+QString VCSBaseSubmitEditor::promptForNickName()
+{
+ if (!m_d->m_nickNameDialog)
+ m_d->m_nickNameDialog = new Internal::NickNameDialog(m_d->m_widget);
+ if (m_d->m_nickNameDialog->exec() == QDialog::Accepted)
+ return m_d->m_nickNameDialog->nickName();
+ return QString();
+}
+
+void VCSBaseSubmitEditor::slotInsertNickName()
+{
+ const QString nick = promptForNickName();
+ if (!nick.isEmpty())
+ m_d->m_widget->descriptionEdit()->textCursor().insertText(nick);
+}
+
+void VCSBaseSubmitEditor::slotSetFieldNickName(int i)
+{
+ const QString nick = promptForNickName();
+ if (!nick.isEmpty())
+ m_d->m_widget->fieldLineEdit(i)->setText(nick);
+}
+
+void VCSBaseSubmitEditor::slotCheckSubmitMessage()
+{
+ QString errorMessage;
+ if (!checkSubmitMessage(&errorMessage)) {
+ QMessageBox msgBox(QMessageBox::Warning, tr("Submit Message Check failed"),
+ errorMessage, QMessageBox::Ok, m_d->m_widget);
+ msgBox.setMinimumWidth(checkDialogMinimumWidth);
+ msgBox.exec();
+ }
+}
+
+bool VCSBaseSubmitEditor::checkSubmitMessage(QString *errorMessage) const
+{
+ const QString checkScript = submitMessageCheckScript();
+ if (checkScript.isEmpty())
+ return true;
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+ const bool rc = runSubmitMessageCheckScript(checkScript, errorMessage);
+ QApplication::restoreOverrideCursor();
+ return rc;
+}
+
+bool VCSBaseSubmitEditor::runSubmitMessageCheckScript(const QString &checkScript, QString *errorMessage) const
+{
+ // Write out message
+ QString tempFilePattern = QDir::tempPath();
+ if (!tempFilePattern.endsWith(QDir::separator()))
+ tempFilePattern += QDir::separator();
+ tempFilePattern += QLatin1String("msgXXXXXX.txt");
+ QTemporaryFile messageFile(tempFilePattern);
+ messageFile.setAutoRemove(true);
+ if (!messageFile.open()) {
+ *errorMessage = tr("Unable to open '%1': %2").arg(messageFile.fileName(), messageFile.errorString());
+ return false;
+ }
+ const QString messageFileName = messageFile.fileName();
+ messageFile.write(fileContents().toUtf8());
+ messageFile.close();
+ // Run check process
+ QProcess checkProcess;
+ checkProcess.start(checkScript, QStringList(messageFileName));
+ if (!checkProcess.waitForStarted()) {
+ *errorMessage = tr("The check script '%1' could not be started: %2").arg(checkScript, checkProcess.errorString());
+ return false;
+ }
+ if (!checkProcess.waitForFinished()) {
+ *errorMessage = tr("The check script '%1' could not be run: %2").arg(checkScript, checkProcess.errorString());
+ return false;
+ }
+ const int exitCode = checkProcess.exitCode();
+ if (exitCode != 0) {
+ *errorMessage = QString::fromLocal8Bit(checkProcess.readAllStandardError());
+ if (errorMessage->isEmpty())
+ *errorMessage = tr("The check script returned exit code %1.").arg(exitCode);
+ return false;
+ }
+ return true;
+}
+
QIcon VCSBaseSubmitEditor::diffIcon()
{
return QIcon(QLatin1String(":/vcsbase/images/diff.png"));
diff --git a/src/plugins/vcsbase/vcsbasesubmiteditor.h b/src/plugins/vcsbase/vcsbasesubmiteditor.h
index 3dcc4e4d29..4a02d262a2 100644
--- a/src/plugins/vcsbase/vcsbasesubmiteditor.h
+++ b/src/plugins/vcsbase/vcsbasesubmiteditor.h
@@ -50,7 +50,9 @@ namespace Core {
}
namespace VCSBase {
-
+namespace Internal {
+ struct VCSBaseSettings;
+}
struct VCSBaseSubmitEditorPrivate;
/* Utility struct to parametrize a VCSBaseSubmitEditor. */
@@ -104,6 +106,15 @@ public:
virtual ~VCSBaseSubmitEditor();
+ // A utility routine to be called when closing a submit editor.
+ // Runs checks on the message and prompts according to configuration.
+ // Force prompt should be true if it is invoked by closing an editor
+ // as opposed to invoking the "Submit" button.
+ enum PromptSubmitResult { SubmitConfirmed, SubmitCanceled, SubmitDiscarded };
+ PromptSubmitResult promptSubmit(const QString &title, const QString &question,
+ const QString &checkFailureQuestion,
+ bool forcePrompt = false) const;
+
int fileNameColumn() const;
void setFileNameColumn(int c);
@@ -147,6 +158,9 @@ private slots:
void slotDiffSelectedVCSFiles(const QStringList &rawList);
bool save(const QString &fileName);
void slotDescriptionChanged();
+ void slotCheckSubmitMessage();
+ void slotInsertNickName();
+ void slotSetFieldNickName(int);
protected:
/* These hooks allow for modifying the contents that goes to
@@ -156,6 +170,11 @@ protected:
virtual bool setFileContents(const QString &contents);
private:
+ void createUserFields(const QString &fieldConfigFile);
+ bool checkSubmitMessage(QString *errorMessage) const;
+ bool runSubmitMessageCheckScript(const QString &script, QString *errorMessage) const;
+ QString promptForNickName();
+
VCSBaseSubmitEditorPrivate *m_d;
};