forked from qt-creator/qt-creator
Add a submit field widget modeled after mail client address controls
This commit is contained in:
BIN
src/libs/utils/images/removesubmitfield.png
Normal file
BIN
src/libs/utils/images/removesubmitfield.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 578 B |
@@ -28,17 +28,15 @@
|
|||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include "submiteditorwidget.h"
|
#include "submiteditorwidget.h"
|
||||||
|
#include "submitfieldwidget.h"
|
||||||
#include "ui_submiteditorwidget.h"
|
#include "ui_submiteditorwidget.h"
|
||||||
|
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
#include <QtCore/QPointer>
|
#include <QtCore/QPointer>
|
||||||
#include <QtCore/QTimer>
|
#include <QtCore/QTimer>
|
||||||
#include <QtCore/QSignalMapper>
|
|
||||||
|
|
||||||
#include <QtGui/QPushButton>
|
#include <QtGui/QPushButton>
|
||||||
#include <QtGui/QMenu>
|
#include <QtGui/QMenu>
|
||||||
#include <QtGui/QLineEdit>
|
|
||||||
#include <QtGui/QFormLayout>
|
|
||||||
#include <QtGui/QHBoxLayout>
|
#include <QtGui/QHBoxLayout>
|
||||||
#include <QtGui/QToolButton>
|
#include <QtGui/QToolButton>
|
||||||
#include <QtGui/QSpacerItem>
|
#include <QtGui/QSpacerItem>
|
||||||
@@ -127,11 +125,8 @@ struct SubmitEditorWidgetPrivate
|
|||||||
int m_activatedRow;
|
int m_activatedRow;
|
||||||
|
|
||||||
QList<AdditionalContextMenuAction> descriptionEditContextMenuActions;
|
QList<AdditionalContextMenuAction> descriptionEditContextMenuActions;
|
||||||
QFormLayout *m_fieldLayout;
|
QVBoxLayout *m_fieldLayout;
|
||||||
// Field entries (label, line edits)
|
QList<SubmitFieldWidget *> m_fieldWidgets;
|
||||||
typedef QPair<QString, QLineEdit*> FieldEntry;
|
|
||||||
QList<FieldEntry> m_fieldEntries;
|
|
||||||
QSignalMapper *m_fieldSignalMapper;
|
|
||||||
int m_lineWidth;
|
int m_lineWidth;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -141,7 +136,6 @@ SubmitEditorWidgetPrivate::SubmitEditorWidgetPrivate() :
|
|||||||
m_fileNameColumn(1),
|
m_fileNameColumn(1),
|
||||||
m_activatedRow(-1),
|
m_activatedRow(-1),
|
||||||
m_fieldLayout(0),
|
m_fieldLayout(0),
|
||||||
m_fieldSignalMapper(0),
|
|
||||||
m_lineWidth(defaultLineWidth)
|
m_lineWidth(defaultLineWidth)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -259,15 +253,8 @@ QString SubmitEditorWidget::descriptionText() const
|
|||||||
{
|
{
|
||||||
QString rc = trimMessageText(lineWrap() ? wrappedText(m_d->m_ui.description) : m_d->m_ui.description->toPlainText());
|
QString rc = trimMessageText(lineWrap() ? wrappedText(m_d->m_ui.description) : m_d->m_ui.description->toPlainText());
|
||||||
// append field entries
|
// append field entries
|
||||||
foreach(const SubmitEditorWidgetPrivate::FieldEntry &fe, m_d->m_fieldEntries) {
|
foreach(const SubmitFieldWidget *fw, m_d->m_fieldWidgets)
|
||||||
const QString fieldText = fe.second->text().trimmed();
|
rc += fw->fieldValues();
|
||||||
if (!fieldText.isEmpty()) {
|
|
||||||
rc += fe.first;
|
|
||||||
rc += QLatin1Char(' ');
|
|
||||||
rc += fieldText;
|
|
||||||
rc += QLatin1Char('\n');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -470,6 +457,27 @@ void SubmitEditorWidget::insertTopWidget(QWidget *w)
|
|||||||
m_d->m_ui.vboxLayout->insertWidget(0, w);
|
m_d->m_ui.vboxLayout->insertWidget(0, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SubmitEditorWidget::addSubmitFieldWidget(SubmitFieldWidget *f)
|
||||||
|
{
|
||||||
|
if (!m_d->m_fieldLayout) {
|
||||||
|
// VBox with horizontal, expanding spacer
|
||||||
|
m_d->m_fieldLayout = new QVBoxLayout;
|
||||||
|
QHBoxLayout *outerLayout = new QHBoxLayout;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
m_d->m_fieldLayout->addWidget(f);
|
||||||
|
m_d->m_fieldWidgets.push_back(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<SubmitFieldWidget *> SubmitEditorWidget::submitFieldWidgets() const
|
||||||
|
{
|
||||||
|
return m_d->m_fieldWidgets;
|
||||||
|
}
|
||||||
|
|
||||||
void SubmitEditorWidget::addDescriptionEditContextMenuAction(QAction *a)
|
void SubmitEditorWidget::addDescriptionEditContextMenuAction(QAction *a)
|
||||||
{
|
{
|
||||||
m_d->descriptionEditContextMenuActions.push_back(SubmitEditorWidgetPrivate::AdditionalContextMenuAction(-1, a));
|
m_d->descriptionEditContextMenuActions.push_back(SubmitEditorWidgetPrivate::AdditionalContextMenuAction(-1, a));
|
||||||
@@ -497,47 +505,6 @@ void SubmitEditorWidget::editorCustomContextMenuRequested(const QPoint &pos)
|
|||||||
delete menu;
|
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 Utils
|
||||||
} // namespace Core
|
} // namespace Core
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ QT_END_NAMESPACE
|
|||||||
namespace Core {
|
namespace Core {
|
||||||
namespace Utils {
|
namespace Utils {
|
||||||
|
|
||||||
|
class SubmitFieldWidget;
|
||||||
struct SubmitEditorWidgetPrivate;
|
struct SubmitEditorWidgetPrivate;
|
||||||
|
|
||||||
/* The submit editor presents the commit message in a text editor and an
|
/* The submit editor presents the commit message in a text editor and an
|
||||||
@@ -114,17 +115,13 @@ public:
|
|||||||
void addDescriptionEditContextMenuAction(QAction *a);
|
void addDescriptionEditContextMenuAction(QAction *a);
|
||||||
void insertDescriptionEditContextMenuAction(int pos, QAction *a);
|
void insertDescriptionEditContextMenuAction(int pos, QAction *a);
|
||||||
|
|
||||||
// Fields are additional fields consisting of a Label and a Line Edit.
|
void addSubmitFieldWidget(SubmitFieldWidget *f);
|
||||||
// A field dialog is wired to a button labeled "..." that pops up a chooser
|
QList<SubmitFieldWidget *> submitFieldWidgets() const;
|
||||||
// resulting in text being set
|
|
||||||
QLineEdit *addField(const QString &label, bool hasDialogButton);
|
|
||||||
QLineEdit *fieldLineEdit(int i) const;
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void diffSelected(const QStringList &);
|
void diffSelected(const QStringList &);
|
||||||
void fileSelectionChanged(bool someFileSelected);
|
void fileSelectionChanged(bool someFileSelected);
|
||||||
void fileCheckStateChanged(bool someFileChecked);
|
void fileCheckStateChanged(bool someFileChecked);
|
||||||
void fieldDialogRequested(int);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void changeEvent(QEvent *e);
|
virtual void changeEvent(QEvent *e);
|
||||||
|
|||||||
344
src/libs/utils/submitfieldwidget.cpp
Normal file
344
src/libs/utils/submitfieldwidget.cpp
Normal file
@@ -0,0 +1,344 @@
|
|||||||
|
#include "submitfieldwidget.h"
|
||||||
|
|
||||||
|
#include <QtGui/QComboBox>
|
||||||
|
#include <QtGui/QHBoxLayout>
|
||||||
|
#include <QtGui/QVBoxLayout>
|
||||||
|
#include <QtGui/QLineEdit>
|
||||||
|
#include <QtGui/QToolButton>
|
||||||
|
#include <QtGui/QCompleter>
|
||||||
|
#include <QtGui/QIcon>
|
||||||
|
#include <QtGui/QToolBar>
|
||||||
|
|
||||||
|
#include <QtCore/QList>
|
||||||
|
#include <QtCore/QDebug>
|
||||||
|
|
||||||
|
enum { debug = 0 };
|
||||||
|
enum { spacing = 2 };
|
||||||
|
|
||||||
|
static void inline setComboBlocked(QComboBox *cb, int index)
|
||||||
|
{
|
||||||
|
const bool blocked = cb->blockSignals(true);
|
||||||
|
cb->setCurrentIndex(index);
|
||||||
|
cb->blockSignals(blocked);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
namespace Utils {
|
||||||
|
|
||||||
|
// Field/Row entry
|
||||||
|
struct FieldEntry {
|
||||||
|
FieldEntry();
|
||||||
|
void createGui(const QIcon &removeIcon);
|
||||||
|
void deleteGuiLater();
|
||||||
|
|
||||||
|
QComboBox *combo;
|
||||||
|
QHBoxLayout *layout;
|
||||||
|
QLineEdit *lineEdit;
|
||||||
|
QToolBar *toolBar;
|
||||||
|
QToolButton *clearButton;
|
||||||
|
QToolButton *browseButton;
|
||||||
|
int comboIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
FieldEntry::FieldEntry() :
|
||||||
|
combo(0),
|
||||||
|
layout(0),
|
||||||
|
lineEdit(0),
|
||||||
|
toolBar(0),
|
||||||
|
clearButton(0),
|
||||||
|
browseButton(0),
|
||||||
|
comboIndex(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void FieldEntry::createGui(const QIcon &removeIcon)
|
||||||
|
{
|
||||||
|
layout = new QHBoxLayout;
|
||||||
|
layout->setMargin(0);
|
||||||
|
layout ->setSpacing(spacing);
|
||||||
|
combo = new QComboBox;
|
||||||
|
layout->addWidget(combo);
|
||||||
|
lineEdit = new QLineEdit;
|
||||||
|
layout->addWidget(lineEdit);
|
||||||
|
toolBar = new QToolBar;
|
||||||
|
toolBar->setProperty("_q_custom_style_disabled", QVariant(true));
|
||||||
|
layout->addWidget(toolBar);
|
||||||
|
clearButton = new QToolButton;
|
||||||
|
clearButton->setIcon(removeIcon);
|
||||||
|
toolBar->addWidget(clearButton);
|
||||||
|
browseButton = new QToolButton;
|
||||||
|
browseButton->setText(QLatin1String("..."));
|
||||||
|
toolBar->addWidget(browseButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FieldEntry::deleteGuiLater()
|
||||||
|
{
|
||||||
|
clearButton->deleteLater();
|
||||||
|
browseButton->deleteLater();
|
||||||
|
toolBar->deleteLater();
|
||||||
|
lineEdit->deleteLater();
|
||||||
|
combo->deleteLater();
|
||||||
|
layout->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------- SubmitFieldWidgetPrivate
|
||||||
|
struct SubmitFieldWidgetPrivate {
|
||||||
|
SubmitFieldWidgetPrivate();
|
||||||
|
|
||||||
|
int findSender(const QObject *o) const;
|
||||||
|
int findField(const QString &f, int excluded = -1) const;
|
||||||
|
inline QString fieldText(int) const;
|
||||||
|
inline QString fieldValue(int) const;
|
||||||
|
inline void focusField(int);
|
||||||
|
|
||||||
|
const QIcon removeFieldIcon;
|
||||||
|
QStringList fields;
|
||||||
|
QCompleter *completer;
|
||||||
|
bool hasBrowseButton;
|
||||||
|
bool allowDuplicateFields;
|
||||||
|
|
||||||
|
QList <FieldEntry> fieldEntries;
|
||||||
|
QVBoxLayout *layout;
|
||||||
|
};
|
||||||
|
|
||||||
|
SubmitFieldWidgetPrivate::SubmitFieldWidgetPrivate() :
|
||||||
|
removeFieldIcon(QLatin1String(":/utils/images/removesubmitfield.png")),
|
||||||
|
completer(0),
|
||||||
|
hasBrowseButton(false),
|
||||||
|
allowDuplicateFields(false),
|
||||||
|
layout(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int SubmitFieldWidgetPrivate::findSender(const QObject *o) const
|
||||||
|
{
|
||||||
|
const int count = fieldEntries.size();
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
const FieldEntry &fe = fieldEntries.at(i);
|
||||||
|
if (fe.combo == o || fe.browseButton == o || fe.clearButton == o || fe.lineEdit == o)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SubmitFieldWidgetPrivate::findField(const QString &ft, int excluded) const
|
||||||
|
{
|
||||||
|
const int count = fieldEntries.size();
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
if (i != excluded && fieldText(i) == ft)
|
||||||
|
return i;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString SubmitFieldWidgetPrivate::fieldText(int pos) const
|
||||||
|
{
|
||||||
|
return fieldEntries.at(pos).combo->currentText();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString SubmitFieldWidgetPrivate::fieldValue(int pos) const
|
||||||
|
{
|
||||||
|
return fieldEntries.at(pos).lineEdit->text();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SubmitFieldWidgetPrivate::focusField(int pos)
|
||||||
|
{
|
||||||
|
fieldEntries.at(pos).lineEdit->setFocus(Qt::TabFocusReason);
|
||||||
|
}
|
||||||
|
|
||||||
|
// SubmitFieldWidget
|
||||||
|
SubmitFieldWidget::SubmitFieldWidget(QWidget *parent) :
|
||||||
|
QWidget(parent),
|
||||||
|
m_d(new SubmitFieldWidgetPrivate)
|
||||||
|
{
|
||||||
|
m_d->layout = new QVBoxLayout;
|
||||||
|
m_d->layout->setMargin(0);
|
||||||
|
m_d->layout->setSpacing(spacing);
|
||||||
|
setLayout(m_d->layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
SubmitFieldWidget::~SubmitFieldWidget()
|
||||||
|
{
|
||||||
|
delete m_d;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SubmitFieldWidget::setFields(const QStringList & f)
|
||||||
|
{
|
||||||
|
// remove old fields
|
||||||
|
for (int i = m_d->fieldEntries.size() - 1 ; i >= 0 ; i--)
|
||||||
|
removeField(i);
|
||||||
|
|
||||||
|
m_d->fields = f;
|
||||||
|
if (!f.empty())
|
||||||
|
createField(f.front());
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList SubmitFieldWidget::fields() const
|
||||||
|
{
|
||||||
|
return m_d->fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SubmitFieldWidget::hasBrowseButton() const
|
||||||
|
{
|
||||||
|
return m_d->hasBrowseButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SubmitFieldWidget::setHasBrowseButton(bool d)
|
||||||
|
{
|
||||||
|
if (m_d->hasBrowseButton == d)
|
||||||
|
return;
|
||||||
|
m_d->hasBrowseButton = d;
|
||||||
|
foreach(const FieldEntry &fe, m_d->fieldEntries)
|
||||||
|
fe.browseButton->setVisible(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SubmitFieldWidget::allowDuplicateFields() const
|
||||||
|
{
|
||||||
|
return m_d->allowDuplicateFields;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SubmitFieldWidget::setAllowDuplicateFields(bool v)
|
||||||
|
{
|
||||||
|
m_d->allowDuplicateFields = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
QCompleter *SubmitFieldWidget::completer() const
|
||||||
|
{
|
||||||
|
return m_d->completer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SubmitFieldWidget::setCompleter(QCompleter *c)
|
||||||
|
{
|
||||||
|
if (c == m_d->completer)
|
||||||
|
return;
|
||||||
|
m_d->completer = c;
|
||||||
|
foreach(const FieldEntry &fe, m_d->fieldEntries)
|
||||||
|
fe.lineEdit->setCompleter(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString SubmitFieldWidget::fieldValue(int pos) const
|
||||||
|
{
|
||||||
|
return m_d->fieldValue(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SubmitFieldWidget::setFieldValue(int pos, const QString &value)
|
||||||
|
{
|
||||||
|
m_d->fieldEntries.at(pos).lineEdit->setText(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString SubmitFieldWidget::fieldValues() const
|
||||||
|
{
|
||||||
|
const QChar blank = QLatin1Char(' ');
|
||||||
|
const QChar newLine = QLatin1Char('\n');
|
||||||
|
// Format as "RevBy: value\nSigned-Off: value\n"
|
||||||
|
QString rc;
|
||||||
|
foreach(const FieldEntry &fe, m_d->fieldEntries) {
|
||||||
|
const QString value = fe.lineEdit->text().trimmed();
|
||||||
|
if (!value.isEmpty()) {
|
||||||
|
rc += fe.combo->currentText();
|
||||||
|
rc += blank;
|
||||||
|
rc += value;
|
||||||
|
rc += newLine;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SubmitFieldWidget::createField(const QString &f)
|
||||||
|
{
|
||||||
|
FieldEntry fe;
|
||||||
|
fe.createGui(m_d->removeFieldIcon);
|
||||||
|
fe.combo->addItems(m_d->fields);
|
||||||
|
if (!f.isEmpty()) {
|
||||||
|
const int index = fe.combo->findText(f);
|
||||||
|
if (index != -1) {
|
||||||
|
setComboBlocked(fe.combo, index);
|
||||||
|
fe.comboIndex = index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
connect(fe.browseButton, SIGNAL(clicked()), this, SLOT(slotBrowseButtonClicked()));
|
||||||
|
if (!m_d->hasBrowseButton)
|
||||||
|
fe.browseButton->setVisible(false);
|
||||||
|
|
||||||
|
if (m_d->completer)
|
||||||
|
fe.lineEdit->setCompleter(m_d->completer);
|
||||||
|
|
||||||
|
connect(fe.combo, SIGNAL(currentIndexChanged(int)),
|
||||||
|
this, SLOT(slotComboIndexChanged(int)));
|
||||||
|
connect(fe.clearButton, SIGNAL(clicked()),
|
||||||
|
this, SLOT(slotRemove()));
|
||||||
|
m_d->layout->addLayout(fe.layout);
|
||||||
|
m_d->fieldEntries.push_back(fe);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SubmitFieldWidget::slotRemove()
|
||||||
|
{
|
||||||
|
// Never remove first entry
|
||||||
|
const int index = m_d->findSender(sender());
|
||||||
|
switch (index) {
|
||||||
|
case -1:
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
m_d->fieldEntries.front().lineEdit->clear();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
removeField(index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SubmitFieldWidget::removeField(int index)
|
||||||
|
{
|
||||||
|
FieldEntry fe = m_d->fieldEntries.takeAt(index);
|
||||||
|
QLayoutItem * item = m_d->layout->takeAt(index);
|
||||||
|
fe.deleteGuiLater();
|
||||||
|
delete item;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SubmitFieldWidget::slotComboIndexChanged(int comboIndex)
|
||||||
|
{
|
||||||
|
const int pos = m_d->findSender(sender());
|
||||||
|
if (debug)
|
||||||
|
qDebug() << '>' << Q_FUNC_INFO << pos;
|
||||||
|
if (pos == -1)
|
||||||
|
return;
|
||||||
|
// Accept new index or reset combo to previous value?
|
||||||
|
int &previousIndex = m_d->fieldEntries[pos].comboIndex;
|
||||||
|
if (comboIndexChange(pos, comboIndex)) {
|
||||||
|
previousIndex = comboIndex;
|
||||||
|
} else {
|
||||||
|
setComboBlocked(m_d->fieldEntries.at(pos).combo, previousIndex);
|
||||||
|
}
|
||||||
|
if (debug)
|
||||||
|
qDebug() << '<' << Q_FUNC_INFO << pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle change of a combo. Return "false" if the combo
|
||||||
|
// is to be reset (refuse new field).
|
||||||
|
bool SubmitFieldWidget::comboIndexChange(int pos, int index)
|
||||||
|
{
|
||||||
|
const QString newField = m_d->fieldEntries.at(pos).combo->itemText(index);
|
||||||
|
// If the field is visible elsewhere: focus the existing one and refuse
|
||||||
|
if (!m_d->allowDuplicateFields) {
|
||||||
|
const int existingFieldIndex = m_d->findField(newField, pos);
|
||||||
|
if (existingFieldIndex != -1) {
|
||||||
|
m_d->focusField(existingFieldIndex);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Empty value: just change the field
|
||||||
|
if (m_d->fieldValue(pos).isEmpty())
|
||||||
|
return true;
|
||||||
|
// Non-empty: Create a new field and reset the triggering combo
|
||||||
|
createField(newField);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SubmitFieldWidget::slotBrowseButtonClicked()
|
||||||
|
{
|
||||||
|
const int pos = m_d->findSender(sender());
|
||||||
|
emit browseButtonClicked(pos, m_d->fieldText(pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
71
src/libs/utils/submitfieldwidget.h
Normal file
71
src/libs/utils/submitfieldwidget.h
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
#ifndef SUBMITFIELDWIDGET_H
|
||||||
|
#define SUBMITFIELDWIDGET_H
|
||||||
|
|
||||||
|
#include "utils_global.h"
|
||||||
|
|
||||||
|
#include <QtGui/QWidget>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QCompleter;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
namespace Utils {
|
||||||
|
|
||||||
|
struct SubmitFieldWidgetPrivate;
|
||||||
|
|
||||||
|
/* A widget for editing submit message fields like "reviewed-by:",
|
||||||
|
* "signed-off-by:". It displays them in a vertical row of combo/line edit fields
|
||||||
|
* that is modeled after the target address controls of mail clients.
|
||||||
|
* When choosing a different field in the combo, a new row is opened if text
|
||||||
|
* has been entered for the current field. Optionally, a "Browse..." button and
|
||||||
|
* completer can be added. */
|
||||||
|
class QWORKBENCH_UTILS_EXPORT SubmitFieldWidget : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(QStringList fields READ fields WRITE setFields DESIGNABLE true)
|
||||||
|
Q_PROPERTY(bool hasBrowseButton READ hasBrowseButton WRITE setHasBrowseButton DESIGNABLE true)
|
||||||
|
Q_PROPERTY(bool allowDuplicateFields READ allowDuplicateFields WRITE setAllowDuplicateFields DESIGNABLE true)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit SubmitFieldWidget(QWidget *parent = 0);
|
||||||
|
virtual ~SubmitFieldWidget();
|
||||||
|
|
||||||
|
QStringList fields() const;
|
||||||
|
void setFields(const QStringList&);
|
||||||
|
|
||||||
|
bool hasBrowseButton() const;
|
||||||
|
void setHasBrowseButton(bool d);
|
||||||
|
|
||||||
|
// Allow several entries for fields ("reviewed-by: a", "reviewed-by: b")
|
||||||
|
bool allowDuplicateFields() const;
|
||||||
|
void setAllowDuplicateFields(bool);
|
||||||
|
|
||||||
|
QCompleter *completer() const;
|
||||||
|
void setCompleter(QCompleter *c);
|
||||||
|
|
||||||
|
QString fieldValue(int pos) const;
|
||||||
|
void setFieldValue(int pos, const QString &value);
|
||||||
|
|
||||||
|
QString fieldValues() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void browseButtonClicked(int pos, const QString &field);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void slotRemove();
|
||||||
|
void slotComboIndexChanged(int);
|
||||||
|
void slotBrowseButtonClicked();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void removeField(int index);
|
||||||
|
bool comboIndexChange(int fieldNumber, int index);
|
||||||
|
void createField(const QString &f);
|
||||||
|
|
||||||
|
SubmitFieldWidgetPrivate *m_d;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SUBMITFIELDWIDGET_H
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
TEMPLATE = lib
|
TEMPLATE = lib
|
||||||
TARGET = Utils
|
TARGET = Utils
|
||||||
QT += network
|
QT += gui network
|
||||||
|
|
||||||
DEFINES += QWORKBENCH_UTILS_LIBRARY
|
DEFINES += QWORKBENCH_UTILS_LIBRARY
|
||||||
|
|
||||||
@@ -24,7 +24,8 @@ SOURCES += \
|
|||||||
fancylineedit.cpp \
|
fancylineedit.cpp \
|
||||||
qtcolorbutton.cpp \
|
qtcolorbutton.cpp \
|
||||||
submiteditorwidget.cpp \
|
submiteditorwidget.cpp \
|
||||||
synchronousprocess.cpp
|
synchronousprocess.cpp \
|
||||||
|
submitfieldwidget.cpp
|
||||||
|
|
||||||
win32 {
|
win32 {
|
||||||
SOURCES += abstractprocess_win.cpp \
|
SOURCES += abstractprocess_win.cpp \
|
||||||
@@ -57,9 +58,12 @@ HEADERS += \
|
|||||||
submiteditorwidget.h \
|
submiteditorwidget.h \
|
||||||
abstractprocess.h \
|
abstractprocess.h \
|
||||||
consoleprocess.h \
|
consoleprocess.h \
|
||||||
synchronousprocess.h
|
synchronousprocess.h \
|
||||||
|
submitfieldwidget.h
|
||||||
|
|
||||||
FORMS += filewizardpage.ui \
|
FORMS += filewizardpage.ui \
|
||||||
projectintropage.ui \
|
projectintropage.ui \
|
||||||
newclasswidget.ui \
|
newclasswidget.ui \
|
||||||
submiteditorwidget.ui
|
submiteditorwidget.ui
|
||||||
|
|
||||||
|
RESOURCES += utils.qrc
|
||||||
|
|||||||
5
src/libs/utils/utils.qrc
Normal file
5
src/libs/utils/utils.qrc
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<RCC>
|
||||||
|
<qresource prefix="/utils" >
|
||||||
|
<file>images/removesubmitfield.png</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
||||||
@@ -39,6 +39,7 @@
|
|||||||
#include <coreplugin/uniqueidmanager.h>
|
#include <coreplugin/uniqueidmanager.h>
|
||||||
#include <coreplugin/actionmanager/actionmanager.h>
|
#include <coreplugin/actionmanager/actionmanager.h>
|
||||||
#include <utils/submiteditorwidget.h>
|
#include <utils/submiteditorwidget.h>
|
||||||
|
#include <utils/submitfieldwidget.h>
|
||||||
#include <find/basetextfind.h>
|
#include <find/basetextfind.h>
|
||||||
|
|
||||||
#include <projectexplorer/projectexplorer.h>
|
#include <projectexplorer/projectexplorer.h>
|
||||||
@@ -135,7 +136,6 @@ VCSBaseSubmitEditor::VCSBaseSubmitEditor(const VCSBaseSubmitEditorParameters *pa
|
|||||||
// Do we have user fields?
|
// Do we have user fields?
|
||||||
if (!settings.nickNameFieldListFile.isEmpty())
|
if (!settings.nickNameFieldListFile.isEmpty())
|
||||||
createUserFields(settings.nickNameFieldListFile);
|
createUserFields(settings.nickNameFieldListFile);
|
||||||
connect(m_d->m_widget, SIGNAL(fieldDialogRequested(int)), this, SLOT(slotSetFieldNickName(int)));
|
|
||||||
|
|
||||||
// wrapping. etc
|
// wrapping. etc
|
||||||
slotUpdateEditorSettings(settings);
|
slotUpdateEditorSettings(settings);
|
||||||
@@ -161,6 +161,19 @@ void VCSBaseSubmitEditor::slotUpdateEditorSettings(const Internal::VCSBaseSettin
|
|||||||
setLineWrap(s.lineWrap);
|
setLineWrap(s.lineWrap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return a trimmed list of non-empty field texts
|
||||||
|
static inline QStringList fieldTexts(const QString &fileContents)
|
||||||
|
{
|
||||||
|
QStringList rc;
|
||||||
|
const QStringList rawFields = fileContents.trimmed().split(QLatin1Char('\n'));
|
||||||
|
foreach(const QString &field, rawFields) {
|
||||||
|
const QString trimmedField = field.trimmed();
|
||||||
|
if (!trimmedField.isEmpty())
|
||||||
|
rc.push_back(trimmedField);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
void VCSBaseSubmitEditor::createUserFields(const QString &fieldConfigFile)
|
void VCSBaseSubmitEditor::createUserFields(const QString &fieldConfigFile)
|
||||||
{
|
{
|
||||||
QFile fieldFile(fieldConfigFile);
|
QFile fieldFile(fieldConfigFile);
|
||||||
@@ -169,17 +182,21 @@ void VCSBaseSubmitEditor::createUserFields(const QString &fieldConfigFile)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Parse into fields
|
// Parse into fields
|
||||||
const QStringList fields = QString::fromUtf8(fieldFile.readAll()).trimmed().split(QLatin1Char('\n'));
|
const QStringList fields = fieldTexts(QString::fromUtf8(fieldFile.readAll()));
|
||||||
if (fields.empty())
|
if (fields.empty())
|
||||||
return;
|
return;
|
||||||
// Create a completer on user names
|
// Create a completer on user names
|
||||||
const QStandardItemModel *nickNameModel = Internal::VCSBasePlugin::instance()->nickNameModel();
|
const QStandardItemModel *nickNameModel = Internal::VCSBasePlugin::instance()->nickNameModel();
|
||||||
QCompleter *completer = new QCompleter(Internal::NickNameDialog::nickNameList(nickNameModel), this);
|
QCompleter *completer = new QCompleter(Internal::NickNameDialog::nickNameList(nickNameModel), this);
|
||||||
foreach(const QString &field, fields) {
|
|
||||||
const QString trimmedField = field.trimmed();
|
Core::Utils::SubmitFieldWidget *fieldWidget = new Core::Utils::SubmitFieldWidget;
|
||||||
if (!trimmedField.isEmpty())
|
connect(fieldWidget, SIGNAL(browseButtonClicked(int,QString)),
|
||||||
m_d->m_widget->addField(trimmedField, true)->setCompleter(completer);
|
this, SLOT(slotSetFieldNickName(int)));
|
||||||
}
|
fieldWidget->setCompleter(completer);
|
||||||
|
fieldWidget->setAllowDuplicateFields(true);
|
||||||
|
fieldWidget->setHasBrowseButton(true);
|
||||||
|
fieldWidget->setFields(fields);
|
||||||
|
m_d->m_widget->addSubmitFieldWidget(fieldWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VCSBaseSubmitEditor::registerActions(QAction *editorUndoAction, QAction *editorRedoAction,
|
void VCSBaseSubmitEditor::registerActions(QAction *editorUndoAction, QAction *editorRedoAction,
|
||||||
@@ -461,9 +478,11 @@ void VCSBaseSubmitEditor::slotInsertNickName()
|
|||||||
|
|
||||||
void VCSBaseSubmitEditor::slotSetFieldNickName(int i)
|
void VCSBaseSubmitEditor::slotSetFieldNickName(int i)
|
||||||
{
|
{
|
||||||
|
if (Core::Utils::SubmitFieldWidget *sfw =m_d->m_widget->submitFieldWidgets().front()) {
|
||||||
const QString nick = promptForNickName();
|
const QString nick = promptForNickName();
|
||||||
if (!nick.isEmpty())
|
if (!nick.isEmpty())
|
||||||
m_d->m_widget->fieldLineEdit(i)->setText(nick);
|
sfw->setFieldValue(i, nick);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VCSBaseSubmitEditor::slotCheckSubmitMessage()
|
void VCSBaseSubmitEditor::slotCheckSubmitMessage()
|
||||||
|
|||||||
@@ -143,6 +143,17 @@ SubmitEditorWidget_CW::SubmitEditorWidget_CW(QObject *parent) :
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SubmitFieldWidget_CW::SubmitFieldWidget_CW(QObject *parent) :
|
||||||
|
QObject(parent),
|
||||||
|
CustomWidget<Core::Utils::SubmitFieldWidget>
|
||||||
|
(QLatin1String("<utils/submitfieldwidget.h>"),
|
||||||
|
false,
|
||||||
|
QLatin1String(groupC),
|
||||||
|
QIcon(),
|
||||||
|
tr("Show predefined fields of a submit message in a control based on mail address controls"))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
// -------------- WidgetCollection
|
// -------------- WidgetCollection
|
||||||
WidgetCollection::WidgetCollection(QObject *parent) :
|
WidgetCollection::WidgetCollection(QObject *parent) :
|
||||||
QObject(parent)
|
QObject(parent)
|
||||||
@@ -157,6 +168,7 @@ WidgetCollection::WidgetCollection(QObject *parent) :
|
|||||||
m_plugins.push_back(new FancyLineEdit_CW(this));
|
m_plugins.push_back(new FancyLineEdit_CW(this));
|
||||||
m_plugins.push_back(new QtColorButton_CW(this));
|
m_plugins.push_back(new QtColorButton_CW(this));
|
||||||
m_plugins.push_back(new SubmitEditorWidget_CW(this));
|
m_plugins.push_back(new SubmitEditorWidget_CW(this));
|
||||||
|
m_plugins.push_back(new SubmitFieldWidget_CW(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QDesignerCustomWidgetInterface*> WidgetCollection::customWidgets() const
|
QList<QDesignerCustomWidgetInterface*> WidgetCollection::customWidgets() const
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
#include <utils/fancylineedit.h>
|
#include <utils/fancylineedit.h>
|
||||||
#include <utils/qtcolorbutton.h>
|
#include <utils/qtcolorbutton.h>
|
||||||
#include <utils/submiteditorwidget.h>
|
#include <utils/submiteditorwidget.h>
|
||||||
|
#include <utils/submitfieldwidget.h>
|
||||||
|
|
||||||
#include <QtDesigner/QDesignerCustomWidgetCollectionInterface>
|
#include <QtDesigner/QDesignerCustomWidgetCollectionInterface>
|
||||||
|
|
||||||
@@ -141,6 +142,16 @@ public:
|
|||||||
explicit SubmitEditorWidget_CW(QObject *parent = 0);
|
explicit SubmitEditorWidget_CW(QObject *parent = 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SubmitFieldWidget_CW :
|
||||||
|
public QObject,
|
||||||
|
public CustomWidget<Core::Utils::SubmitFieldWidget>
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_INTERFACES(QDesignerCustomWidgetInterface)
|
||||||
|
public:
|
||||||
|
explicit SubmitFieldWidget_CW(QObject *parent = 0);
|
||||||
|
};
|
||||||
|
|
||||||
// Collection
|
// Collection
|
||||||
|
|
||||||
class WidgetCollection : public QObject, public QDesignerCustomWidgetCollectionInterface
|
class WidgetCollection : public QObject, public QDesignerCustomWidgetCollectionInterface
|
||||||
|
|||||||
Reference in New Issue
Block a user