Commit 0ada412e authored by Friedemann Kleint's avatar Friedemann Kleint
Browse files

Add option to wrap commit message at 72 chars and make it default.

Reorganize the settings model in the VCS base plugin, store model in the plugin for better delayed initialization/update.
parent 361a70ab
......@@ -44,6 +44,7 @@
#include <QtGui/QSpacerItem>
enum { debug = 0 };
enum { defaultLineWidth = 72 };
namespace Core {
namespace Utils {
......@@ -131,6 +132,7 @@ struct SubmitEditorWidgetPrivate
typedef QPair<QString, QLineEdit*> FieldEntry;
QList<FieldEntry> m_fieldEntries;
QSignalMapper *m_fieldSignalMapper;
int m_lineWidth;
};
SubmitEditorWidgetPrivate::SubmitEditorWidgetPrivate() :
......@@ -139,7 +141,8 @@ SubmitEditorWidgetPrivate::SubmitEditorWidgetPrivate() :
m_fileNameColumn(1),
m_activatedRow(-1),
m_fieldLayout(0),
m_fieldSignalMapper(0)
m_fieldSignalMapper(0),
m_lineWidth(defaultLineWidth)
{
}
......@@ -149,6 +152,7 @@ SubmitEditorWidget::SubmitEditorWidget(QWidget *parent) :
{
m_d->m_ui.setupUi(this);
m_d->m_ui.description->setContextMenuPolicy(Qt::CustomContextMenu);
m_d->m_ui.description->setLineWrapMode(QTextEdit::NoWrap);
connect(m_d->m_ui.description, SIGNAL(customContextMenuRequested(QPoint)),
this, SLOT(editorCustomContextMenuRequested(QPoint)));
......@@ -189,7 +193,7 @@ void SubmitEditorWidget::registerActions(QAction *editorUndoAction, QAction *ed
int count = 0;
if (const QAbstractItemModel *model = m_d->m_ui.fileView->model())
count = model->rowCount();
qDebug() << submitAction << count << "items" << m_d->m_filesChecked;
qDebug() << Q_FUNC_INFO << submitAction << count << "items" << m_d->m_filesChecked;
}
submitAction->setEnabled(m_d->m_filesChecked);
connect(this, SIGNAL(fileCheckStateChanged(bool)), submitAction, SLOT(setEnabled(bool)));
......@@ -255,6 +259,39 @@ void SubmitEditorWidget::setDescriptionText(const QString &text)
m_d->m_ui.description->setPlainText(text);
}
bool SubmitEditorWidget::lineWrap() const
{
return m_d->m_ui.description->lineWrapMode() != QTextEdit::NoWrap;
}
void SubmitEditorWidget::setLineWrap(bool v)
{
if (debug)
qDebug() << Q_FUNC_INFO << v;
if (v) {
m_d->m_ui.description->setLineWrapColumnOrWidth(m_d->m_lineWidth);
m_d->m_ui.description->setLineWrapMode(QTextEdit::FixedColumnWidth);
} else {
m_d->m_ui.description->setLineWrapMode(QTextEdit::NoWrap);
}
}
int SubmitEditorWidget::lineWrapWidth() const
{
return m_d->m_lineWidth;
}
void SubmitEditorWidget::setLineWrapWidth(int v)
{
if (debug)
qDebug() << Q_FUNC_INFO << v << lineWrap();
if (m_d->m_lineWidth == v)
return;
m_d->m_lineWidth = v;
if (lineWrap())
m_d->m_ui.description->setLineWrapColumnOrWidth(v);
}
int SubmitEditorWidget::fileNameColumn() const
{
return m_d->m_fileNameColumn;
......@@ -332,7 +369,7 @@ QStringList SubmitEditorWidget::checkedFiles() const
return rc;
}
QPlainTextEdit *SubmitEditorWidget::descriptionEdit() const
QTextEdit *SubmitEditorWidget::descriptionEdit() const
{
return m_d->m_ui.description;
}
......
......@@ -36,7 +36,7 @@
#include <QtGui/QAbstractItemView>
QT_BEGIN_NAMESPACE
class QPlainTextEdit;
class QTextEdit;
class QListWidgetItem;
class QAction;
class QAbstractItemModel;
......@@ -74,6 +74,8 @@ class QWORKBENCH_UTILS_EXPORT SubmitEditorWidget : public QWidget
Q_PROPERTY(QString descriptionText READ descriptionText WRITE setDescriptionText DESIGNABLE true)
Q_PROPERTY(int fileNameColumn READ fileNameColumn WRITE setFileNameColumn DESIGNABLE false)
Q_PROPERTY(QAbstractItemView::SelectionMode fileListSelectionMode READ fileListSelectionMode WRITE setFileListSelectionMode DESIGNABLE true)
Q_PROPERTY(bool lineWrap READ lineWrap WRITE setLineWrap DESIGNABLE true)
Q_PROPERTY(int lineWrapWidth READ lineWrapWidth WRITE setLineWrapWidth DESIGNABLE true)
public:
explicit SubmitEditorWidget(QWidget *parent = 0);
virtual ~SubmitEditorWidget();
......@@ -91,6 +93,12 @@ public:
int fileNameColumn() const;
void setFileNameColumn(int c);
bool lineWrap() const;
void setLineWrap(bool);
int lineWrapWidth() const;
void setLineWrapWidth(int);
QAbstractItemView::SelectionMode fileListSelectionMode() const;
void setFileListSelectionMode(QAbstractItemView::SelectionMode sm);
......@@ -103,7 +111,7 @@ public:
// Selected files for diff
QStringList selectedFiles() const;
QPlainTextEdit *descriptionEdit() const;
QTextEdit *descriptionEdit() const;
void addDescriptionEditContextMenuAction(QAction *a);
void insertDescriptionEditContextMenuAction(int pos, QAction *a);
......
......@@ -24,7 +24,11 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPlainTextEdit" name="description"/>
<widget class="QTextEdit" name="description">
<property name="acceptRichText">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
......
......@@ -28,7 +28,6 @@
**************************************************************************/
#include "nicknamedialog.h"
#include "vcsbaseplugin.h"
#include "ui_nicknamedialog.h"
#include <QtCore/QDebug>
......@@ -120,13 +119,18 @@ QString NickNameEntry::nickName() const
QList<QStandardItem *> NickNameEntry::toModelRow() const
{
const QVariant nickNameData = nickName();
const Qt::ItemFlags flags = Qt::ItemIsSelectable|Qt::ItemIsEnabled;
QStandardItem *i1 = new QStandardItem(name);
i1->setFlags(flags);
i1->setData(nickNameData, NickNameRole);
QStandardItem *i2 = new QStandardItem(email);
i1->setFlags(flags);
i2->setData(nickNameData, NickNameRole);
QStandardItem *i3 = new QStandardItem(aliasName);
i3->setFlags(flags);
i3->setData(nickNameData, NickNameRole);
QStandardItem *i4 = new QStandardItem(aliasEmail);
i4->setFlags(flags);
i4->setData(nickNameData, NickNameRole);
QList<QStandardItem *> row;
row << i1 << i2 << i3 << i4;
......@@ -145,31 +149,10 @@ QDebug operator<<(QDebug d, const NickNameEntry &e)
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) :
NickNameDialog::NickNameDialog(QStandardItemModel *model, QWidget *parent) :
QDialog(parent),
m_ui(new Ui::NickNameDialog),
m_model(model),
m_filterModel(new QSortFilterProxyModel(this))
{
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
......@@ -177,7 +160,7 @@ NickNameDialog::NickNameDialog(QWidget *parent) :
okButton()->setEnabled(false);
// Populate model and grow tree to accommodate it
m_filterModel->setSourceModel(nickModel());
m_filterModel->setSourceModel(model);
m_filterModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
m_ui->filterTreeView->setModel(m_filterModel);
const int columnCount = m_filterModel->columnCount();
......@@ -221,26 +204,35 @@ 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))
if (const QStandardItem *item = m_model->itemFromIndex(sourceIndex))
return NickNameEntry::nickNameOf(item);
}
return QString();
}
void NickNameDialog::clearNickNames()
QStandardItemModel *NickNameDialog::createModel(QObject *parent)
{
clearModel(nickModel());
QStandardItemModel *model = new QStandardItemModel(parent);
QStringList headers;
headers << tr("Name") << tr("E-mail")
<< tr("Alias") << tr("Alias e-mail");
model->setHorizontalHeaderLabels(headers);
return model;
}
bool NickNameDialog::readNickNamesFromMailCapFile(const QString &fileName, QString *errorMessage)
bool NickNameDialog::populateModelFromMailCapFile(const QString &fileName,
QStandardItemModel *model,
QString *errorMessage)
{
if (const int rowCount = model->rowCount())
model->removeRows(0, rowCount);
if (fileName.isEmpty())
return true;
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'));
......@@ -256,10 +248,9 @@ bool NickNameDialog::readNickNamesFromMailCapFile(const QString &fileName, QStri
return true;
}
QStringList NickNameDialog::nickNameList()
QStringList NickNameDialog::nickNameList(const QStandardItemModel *model)
{
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)));
......
......@@ -37,6 +37,7 @@ namespace Ui {
class NickNameDialog;
}
class QSortFilterProxyModel;
class QStandardItemModel;
class QModelIndex;
class QPushButton;
QT_END_NAMESPACE
......@@ -48,23 +49,24 @@ namespace Internal {
* 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. */
* be preferred. */
class NickNameDialog : public QDialog {
Q_OBJECT
public:
explicit NickNameDialog(QWidget *parent = 0);
explicit NickNameDialog(QStandardItemModel *model, 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();
// Utilities to initialize/populate the model
static QStandardItemModel *createModel(QObject *parent);
static bool populateModelFromMailCapFile(const QString &file,
QStandardItemModel *model,
QString *errorMessage);
// Return a list for a completer on the field line edits
static QStringList nickNameList();
static QStringList nickNameList(const QStandardItemModel *model);
private slots:
void slotCurrentItemChanged(const QModelIndex &);
......@@ -74,7 +76,9 @@ private:
QPushButton *okButton() const;
Ui::NickNameDialog *m_ui;
QStandardItemModel *m_model;
QSortFilterProxyModel *m_filterModel;
};
} // namespace Internal
......
......@@ -30,6 +30,7 @@
#include "vcsbaseplugin.h"
#include "diffhighlighter.h"
#include "vcsbasesettingspage.h"
#include "nicknamedialog.h"
#include <coreplugin/icore.h>
#include <coreplugin/coreconstants.h>
......@@ -37,6 +38,7 @@
#include <coreplugin/mimedatabase.h>
#include <QtCore/QtPlugin>
#include <QtCore/QDebug>
namespace VCSBase {
namespace Internal {
......@@ -44,7 +46,8 @@ namespace Internal {
VCSBasePlugin *VCSBasePlugin::m_instance = 0;
VCSBasePlugin::VCSBasePlugin() :
m_settingsPage(0)
m_settingsPage(0),
m_nickNameModel(0)
{
m_instance = this;
}
......@@ -65,6 +68,11 @@ bool VCSBasePlugin::initialize(const QStringList &arguments, QString *errorMessa
m_settingsPage = new VCSBaseSettingsPage;
addAutoReleasedObject(m_settingsPage);
connect(m_settingsPage, SIGNAL(settingsChanged(VCSBase::Internal::VCSBaseSettings)),
this, SIGNAL(settingsChanged(VCSBase::Internal::VCSBaseSettings)));
connect(m_settingsPage, SIGNAL(settingsChanged(VCSBase::Internal::VCSBaseSettings)),
this, SLOT(slotSettingsChanged()));
slotSettingsChanged();
return true;
}
......@@ -82,6 +90,32 @@ VCSBaseSettings VCSBasePlugin::settings() const
return m_settingsPage->settings();
}
/* Delayed creation/update of the nick name model. */
QStandardItemModel *VCSBasePlugin::nickNameModel()
{
if (!m_nickNameModel) {
m_nickNameModel = NickNameDialog::createModel(this);
populateNickNameModel();
}
return m_nickNameModel;
}
void VCSBasePlugin::populateNickNameModel()
{
QString errorMessage;
if (!NickNameDialog::populateModelFromMailCapFile(settings().nickNameMailMap,
m_nickNameModel,
&errorMessage)) {
qWarning("%s", qPrintable(errorMessage));
}
}
void VCSBasePlugin::slotSettingsChanged()
{
if (m_nickNameModel)
populateNickNameModel();
}
} // namespace Internal
} // namespace VCSBase
......
......@@ -34,6 +34,10 @@
#include <QtCore/QObject>
QT_BEGIN_NAMESPACE
class QStandardItemModel;
QT_END_NAMESPACE
namespace VCSBase {
namespace Internal {
......@@ -56,9 +60,23 @@ public:
VCSBaseSettings settings() const;
// Model of user nick names used for the submit
// editor. Stored centrally here to achieve delayed
// initialization and updating on settings change.
QStandardItemModel *nickNameModel();
signals:
void settingsChanged(const VCSBase::Internal::VCSBaseSettings& s);
private slots:
void slotSettingsChanged();
private:
void populateNickNameModel();
static VCSBasePlugin *m_instance;
VCSBaseSettingsPage *m_settingsPage;
QStandardItemModel *m_nickNameModel;
};
} // namespace Internal
......
......@@ -37,12 +37,19 @@ static const char *nickNameMailMapKeyC = "NickNameMailMap";
static const char *nickNameFieldListFileKeyC = "NickNameFieldListFile";
static const char *promptForSubmitKeyC = "PromptForSubmit";
static const char *submitMessageCheckScriptKeyC = "SubmitMessageCheckScript";
static const char *lineWrapKeyC = "LineWrap";
static const char *lineWrapWidthKeyC = "LineWrapWidth";
static const int lineWrapWidthDefault = 72;
static const bool lineWrapDefault = true;
namespace VCSBase {
namespace Internal {
VCSBaseSettings::VCSBaseSettings() :
promptForSubmit(true)
promptForSubmit(true),
lineWrap(lineWrapDefault),
lineWrapWidth(lineWrapWidthDefault)
{
}
......@@ -53,6 +60,8 @@ void VCSBaseSettings::toSettings(QSettings *s) const
s->setValue(QLatin1String(nickNameFieldListFileKeyC), nickNameFieldListFile);
s->setValue(QLatin1String(submitMessageCheckScriptKeyC), submitMessageCheckScript);
s->setValue(QLatin1String(promptForSubmitKeyC), promptForSubmit);
s->setValue(QLatin1String(lineWrapKeyC), lineWrap);
s->setValue(QLatin1String(lineWrapWidthKeyC), lineWrapWidth);
s->endGroup();
}
......@@ -63,16 +72,30 @@ void VCSBaseSettings::fromSettings(QSettings *s)
nickNameFieldListFile = s->value(QLatin1String(nickNameFieldListFileKeyC), QString()).toString();
submitMessageCheckScript = s->value(QLatin1String(submitMessageCheckScriptKeyC), QString()).toString();
promptForSubmit = s->value(QLatin1String(promptForSubmitKeyC), QVariant(true)).toBool();
lineWrap = s->value(QLatin1String(lineWrapKeyC), lineWrapDefault).toBool();
lineWrapWidth = s->value(QLatin1String(lineWrapWidthKeyC), lineWrapWidthDefault).toInt();
s->endGroup();
}
bool VCSBaseSettings::equals(const VCSBaseSettings &rhs) const
{
return promptForSubmit == rhs.promptForSubmit
&& lineWrap == rhs.lineWrap
&& lineWrapWidth == rhs.lineWrapWidth
&& nickNameMailMap == rhs.nickNameMailMap
&& nickNameFieldListFile == rhs.nickNameFieldListFile
&& submitMessageCheckScript == rhs.submitMessageCheckScript;
}
QDebug operator<<(QDebug d,const VCSBaseSettings& s)
{
d.nospace() << "promptForSubmit=" << s.promptForSubmit
<< " lineWrap=" << s.lineWrap
<< " lineWrapWidth=" << s.lineWrapWidth
<< " nickNameMailMap='" << s.nickNameMailMap
<< "' nickNameFieldListFile='" << s.nickNameFieldListFile
<< "'submitMessageCheckScript='" << s.submitMessageCheckScript << "'\n";
return d;
}
}
}
......@@ -35,6 +35,7 @@
QT_BEGIN_NAMESPACE
class QSettings;
class QDebug;
QT_END_NAMESPACE
namespace VCSBase {
......@@ -51,6 +52,9 @@ struct VCSBaseSettings {
QString submitMessageCheckScript;
bool lineWrap;
int lineWrapWidth;
void toSettings(QSettings *) const;
void fromSettings(QSettings *);
......@@ -60,6 +64,7 @@ struct VCSBaseSettings {
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); }
QDebug operator<<(QDebug,const VCSBaseSettings& );
} // namespace Internal
} // namespace VCSBase
......
......@@ -67,16 +67,19 @@ VCSBaseSettings VCSBaseSettingsWidget::settings() const
rc.nickNameFieldListFile = m_ui->nickNameFieldsFileChooser->path();
rc.submitMessageCheckScript = m_ui->submitMessageCheckScriptChooser->path();
rc.promptForSubmit = m_ui->promptForSubmitCheckBox->isChecked();
rc.lineWrap= m_ui->lineWrapCheckBox->isChecked();
rc.lineWrapWidth = m_ui->lineWrapSpinBox->value();
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);
m_ui->lineWrapCheckBox->setChecked(s.lineWrap);
m_ui->lineWrapSpinBox->setValue(s.lineWrapWidth);
}
// --------------- VCSBaseSettingsPage
......@@ -84,18 +87,10 @@ 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()
......@@ -136,7 +131,7 @@ void VCSBaseSettingsPage::apply()
if (newSettings != m_settings) {
m_settings = newSettings;
m_settings.toSettings(Core::ICore::instance()->settings());
updateNickNames();
emit settingsChanged(m_settings);
}
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment