forked from qt-creator/qt-creator
VCS: Add 'Check/Uncheck' all context menu to submit file list.
Update 'Commit' button to show number of files to be committed. Task-number: QTCREATORBUG-2090
This commit is contained in:
@@ -34,6 +34,7 @@
|
|||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
#include <QtCore/QPointer>
|
#include <QtCore/QPointer>
|
||||||
#include <QtCore/QTimer>
|
#include <QtCore/QTimer>
|
||||||
|
#include <QtCore/QScopedPointer>
|
||||||
|
|
||||||
#include <QtGui/QPushButton>
|
#include <QtGui/QPushButton>
|
||||||
#include <QtGui/QMenu>
|
#include <QtGui/QMenu>
|
||||||
@@ -44,6 +45,8 @@
|
|||||||
enum { debug = 0 };
|
enum { debug = 0 };
|
||||||
enum { defaultLineWidth = 72 };
|
enum { defaultLineWidth = 72 };
|
||||||
|
|
||||||
|
enum { checkableColumn = 0 };
|
||||||
|
|
||||||
namespace Utils {
|
namespace Utils {
|
||||||
|
|
||||||
// QActionPushButton: A push button tied to an action
|
// QActionPushButton: A push button tied to an action
|
||||||
@@ -68,10 +71,27 @@ QActionPushButton::QActionPushButton(QAction *a) :
|
|||||||
|
|
||||||
void QActionPushButton::actionChanged()
|
void QActionPushButton::actionChanged()
|
||||||
{
|
{
|
||||||
if (const QAction *a = qobject_cast<QAction*>(sender()))
|
if (const QAction *a = qobject_cast<QAction*>(sender())) {
|
||||||
setEnabled(a->isEnabled());
|
setEnabled(a->isEnabled());
|
||||||
|
setText(a->text());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A helper parented on a QAction,
|
||||||
|
// making QAction::setText() a slot (which it currently is not).
|
||||||
|
class QActionSetTextSlotHelper : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit QActionSetTextSlotHelper(QAction *a) : QObject(a) {}
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void setText(const QString &t) {
|
||||||
|
if (QAction *action = qobject_cast<QAction *>(parent()))
|
||||||
|
action->setText(t);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Helpers to retrieve model data
|
// Helpers to retrieve model data
|
||||||
static inline bool listModelChecked(const QAbstractItemModel *model, int row, int column = 0)
|
static inline bool listModelChecked(const QAbstractItemModel *model, int row, int column = 0)
|
||||||
{
|
{
|
||||||
@@ -79,22 +99,22 @@ static inline bool listModelChecked(const QAbstractItemModel *model, int row, in
|
|||||||
return model->data(checkableIndex, Qt::CheckStateRole).toInt() == Qt::Checked;
|
return model->data(checkableIndex, Qt::CheckStateRole).toInt() == Qt::Checked;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void setListModelChecked(QAbstractItemModel *model, bool checked, int column = 0)
|
||||||
|
{
|
||||||
|
const QVariant data = QVariant(int(checked ? Qt::Checked : Qt::Unchecked));
|
||||||
|
const int count = model->rowCount();
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
const QModelIndex checkableIndex = model->index(i, column, QModelIndex());
|
||||||
|
model->setData(checkableIndex, data, Qt::CheckStateRole);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline QString listModelText(const QAbstractItemModel *model, int row, int column)
|
static inline QString listModelText(const QAbstractItemModel *model, int row, int column)
|
||||||
{
|
{
|
||||||
const QModelIndex index = model->index(row, column, QModelIndex());
|
const QModelIndex index = model->index(row, column, QModelIndex());
|
||||||
return model->data(index, Qt::DisplayRole).toString();
|
return model->data(index, Qt::DisplayRole).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find a check item in a model
|
|
||||||
static bool listModelContainsCheckedItem(const QAbstractItemModel *model)
|
|
||||||
{
|
|
||||||
const int count = model->rowCount();
|
|
||||||
for (int i = 0; i < count; i++)
|
|
||||||
if (listModelChecked(model, i, 0))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convenience to extract a list of selected indexes
|
// Convenience to extract a list of selected indexes
|
||||||
QList<int> selectedRows(const QAbstractItemView *view)
|
QList<int> selectedRows(const QAbstractItemView *view)
|
||||||
{
|
{
|
||||||
@@ -151,6 +171,9 @@ SubmitEditorWidget::SubmitEditorWidget(QWidget *parent) :
|
|||||||
this, SLOT(editorCustomContextMenuRequested(QPoint)));
|
this, SLOT(editorCustomContextMenuRequested(QPoint)));
|
||||||
|
|
||||||
// File List
|
// File List
|
||||||
|
m_d->m_ui.fileView->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
|
connect(m_d->m_ui.fileView, SIGNAL(customContextMenuRequested(QPoint)),
|
||||||
|
this, SLOT(fileListCustomContextMenuRequested(QPoint)));
|
||||||
m_d->m_ui.fileView->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
m_d->m_ui.fileView->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||||
m_d->m_ui.fileView->setRootIsDecorated(false);
|
m_d->m_ui.fileView->setRootIsDecorated(false);
|
||||||
connect(m_d->m_ui.fileView, SIGNAL(doubleClicked(QModelIndex)),
|
connect(m_d->m_ui.fileView, SIGNAL(doubleClicked(QModelIndex)),
|
||||||
@@ -188,6 +211,11 @@ void SubmitEditorWidget::registerActions(QAction *editorUndoAction, QAction *edi
|
|||||||
}
|
}
|
||||||
submitAction->setEnabled(m_d->m_filesChecked);
|
submitAction->setEnabled(m_d->m_filesChecked);
|
||||||
connect(this, SIGNAL(fileCheckStateChanged(bool)), submitAction, SLOT(setEnabled(bool)));
|
connect(this, SIGNAL(fileCheckStateChanged(bool)), submitAction, SLOT(setEnabled(bool)));
|
||||||
|
// Wire setText via QActionSetTextSlotHelper.
|
||||||
|
QActionSetTextSlotHelper *actionSlotHelper = submitAction->findChild<QActionSetTextSlotHelper *>();
|
||||||
|
if (!actionSlotHelper)
|
||||||
|
actionSlotHelper = new QActionSetTextSlotHelper(submitAction);
|
||||||
|
connect(this, SIGNAL(submitActionTextChanged(QString)), actionSlotHelper, SLOT(setText(QString)));
|
||||||
m_d->m_ui.buttonLayout->addWidget(new QActionPushButton(submitAction));
|
m_d->m_ui.buttonLayout->addWidget(new QActionPushButton(submitAction));
|
||||||
}
|
}
|
||||||
if (diffAction) {
|
if (diffAction) {
|
||||||
@@ -212,8 +240,11 @@ void SubmitEditorWidget::unregisterActions(QAction *editorUndoAction, QAction *
|
|||||||
disconnect(editorRedoAction, SIGNAL(triggered()), m_d->m_ui.description, SLOT(redo()));
|
disconnect(editorRedoAction, SIGNAL(triggered()), m_d->m_ui.description, SLOT(redo()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (submitAction)
|
if (submitAction) {
|
||||||
disconnect(this, SIGNAL(fileCheckStateChanged(bool)), submitAction, SLOT(setEnabled(bool)));
|
disconnect(this, SIGNAL(fileCheckStateChanged(bool)), submitAction, SLOT(setEnabled(bool)));
|
||||||
|
// Just deactivate the QActionSetTextSlotHelper on the action
|
||||||
|
disconnect(this, SIGNAL(submitActionTextChanged(QString)), 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
if (diffAction) {
|
if (diffAction) {
|
||||||
disconnect(this, SIGNAL(fileSelectionChanged(bool)), diffAction, SLOT(setEnabled(bool)));
|
disconnect(this, SIGNAL(fileSelectionChanged(bool)), diffAction, SLOT(setEnabled(bool)));
|
||||||
@@ -374,7 +405,7 @@ QStringList SubmitEditorWidget::checkedFiles() const
|
|||||||
return rc;
|
return rc;
|
||||||
const int count = model->rowCount();
|
const int count = model->rowCount();
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
if (listModelChecked(model, i, 0))
|
if (listModelChecked(model, i, checkableColumn))
|
||||||
rc.push_back(listModelText(model, i, fileNameColumn()));
|
rc.push_back(listModelText(model, i, fileNameColumn()));
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -414,11 +445,19 @@ void SubmitEditorWidget::updateActions()
|
|||||||
// Enable submit depending on having checked files
|
// Enable submit depending on having checked files
|
||||||
void SubmitEditorWidget::updateSubmitAction()
|
void SubmitEditorWidget::updateSubmitAction()
|
||||||
{
|
{
|
||||||
const bool newFilesCheckedState = hasCheckedFiles();
|
const unsigned checkedCount = checkedFilesCount();
|
||||||
|
const bool newFilesCheckedState = checkedCount;
|
||||||
|
// Emit signal to update action
|
||||||
if (m_d->m_filesChecked != newFilesCheckedState) {
|
if (m_d->m_filesChecked != newFilesCheckedState) {
|
||||||
m_d->m_filesChecked = newFilesCheckedState;
|
m_d->m_filesChecked = newFilesCheckedState;
|
||||||
emit fileCheckStateChanged(m_d->m_filesChecked);
|
emit fileCheckStateChanged(m_d->m_filesChecked);
|
||||||
}
|
}
|
||||||
|
// Update button text.
|
||||||
|
const int fileCount = m_d->m_ui.fileView->model()->rowCount();
|
||||||
|
const QString msg = checkedCount ?
|
||||||
|
tr("Commit %1/%2 Files").arg(checkedCount).arg(fileCount) :
|
||||||
|
tr("Commit");
|
||||||
|
emit submitActionTextChanged(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable diff depending on selected files
|
// Enable diff depending on selected files
|
||||||
@@ -439,11 +478,16 @@ bool SubmitEditorWidget::hasSelection() const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SubmitEditorWidget::hasCheckedFiles() const
|
unsigned SubmitEditorWidget::checkedFilesCount() const
|
||||||
{
|
{
|
||||||
if (const QAbstractItemModel *model = m_d->m_ui.fileView->model())
|
unsigned checkedCount = 0;
|
||||||
return listModelContainsCheckedItem(model);
|
if (const QAbstractItemModel *model = m_d->m_ui.fileView->model()) {
|
||||||
return false;
|
const int count = model->rowCount();
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
if (listModelChecked(model, i, checkableColumn))
|
||||||
|
checkedCount++;
|
||||||
|
}
|
||||||
|
return checkedCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubmitEditorWidget::changeEvent(QEvent *e)
|
void SubmitEditorWidget::changeEvent(QEvent *e)
|
||||||
@@ -496,7 +540,7 @@ void SubmitEditorWidget::insertDescriptionEditContextMenuAction(int pos, QAction
|
|||||||
|
|
||||||
void SubmitEditorWidget::editorCustomContextMenuRequested(const QPoint &pos)
|
void SubmitEditorWidget::editorCustomContextMenuRequested(const QPoint &pos)
|
||||||
{
|
{
|
||||||
QMenu *menu = m_d->m_ui.description->createStandardContextMenu();
|
QScopedPointer<QMenu> menu(m_d->m_ui.description->createStandardContextMenu());
|
||||||
// Extend
|
// Extend
|
||||||
foreach (const SubmitEditorWidgetPrivate::AdditionalContextMenuAction &a, m_d->descriptionEditContextMenuActions) {
|
foreach (const SubmitEditorWidgetPrivate::AdditionalContextMenuAction &a, m_d->descriptionEditContextMenuActions) {
|
||||||
if (a.second) {
|
if (a.second) {
|
||||||
@@ -508,7 +552,33 @@ void SubmitEditorWidget::editorCustomContextMenuRequested(const QPoint &pos)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
menu->exec(m_d->m_ui.description->mapToGlobal(pos));
|
menu->exec(m_d->m_ui.description->mapToGlobal(pos));
|
||||||
delete menu;
|
}
|
||||||
|
|
||||||
|
void SubmitEditorWidget::checkAll()
|
||||||
|
{
|
||||||
|
setListModelChecked(m_d->m_ui.fileView->model(), true, checkableColumn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SubmitEditorWidget::uncheckAll()
|
||||||
|
{
|
||||||
|
setListModelChecked(m_d->m_ui.fileView->model(), false, checkableColumn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SubmitEditorWidget::fileListCustomContextMenuRequested(const QPoint & pos)
|
||||||
|
{
|
||||||
|
// Execute menu offering to check/uncheck all
|
||||||
|
QMenu menu;
|
||||||
|
QAction *checkAllAction = menu.addAction(tr("Check All"));
|
||||||
|
QAction *uncheckAllAction = menu.addAction(tr("Uncheck All"));
|
||||||
|
QAction *action = menu.exec(m_d->m_ui.fileView->mapToGlobal(pos));
|
||||||
|
if (action == checkAllAction) {
|
||||||
|
checkAll();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (action == uncheckAllAction) {
|
||||||
|
uncheckAll();
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Utils
|
} // namespace Utils
|
||||||
|
@@ -80,6 +80,9 @@ public:
|
|||||||
explicit SubmitEditorWidget(QWidget *parent = 0);
|
explicit SubmitEditorWidget(QWidget *parent = 0);
|
||||||
virtual ~SubmitEditorWidget();
|
virtual ~SubmitEditorWidget();
|
||||||
|
|
||||||
|
// Register/Unregister actions that are managed by ActionManager with this widget.
|
||||||
|
// The submit action should have Core::Command::CA_UpdateText set as its text will
|
||||||
|
// be updated.
|
||||||
void registerActions(QAction *editorUndoAction, QAction *editorRedoAction,
|
void registerActions(QAction *editorUndoAction, QAction *editorRedoAction,
|
||||||
QAction *submitAction = 0, QAction *diffAction = 0);
|
QAction *submitAction = 0, QAction *diffAction = 0);
|
||||||
void unregisterActions(QAction *editorUndoAction, QAction *editorRedoAction,
|
void unregisterActions(QAction *editorUndoAction, QAction *editorRedoAction,
|
||||||
@@ -121,6 +124,11 @@ 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 submitActionTextChanged(const QString &);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void checkAll();
|
||||||
|
void uncheckAll();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void changeEvent(QEvent *e);
|
virtual void changeEvent(QEvent *e);
|
||||||
@@ -134,10 +142,11 @@ private slots:
|
|||||||
void updateSubmitAction();
|
void updateSubmitAction();
|
||||||
void updateDiffAction();
|
void updateDiffAction();
|
||||||
void editorCustomContextMenuRequested(const QPoint &);
|
void editorCustomContextMenuRequested(const QPoint &);
|
||||||
|
void fileListCustomContextMenuRequested(const QPoint & pos);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool hasSelection() const;
|
bool hasSelection() const;
|
||||||
bool hasCheckedFiles() const;
|
unsigned checkedFilesCount() const;
|
||||||
|
|
||||||
SubmitEditorWidgetPrivate *m_d;
|
SubmitEditorWidgetPrivate *m_d;
|
||||||
};
|
};
|
||||||
|
@@ -450,6 +450,7 @@ bool CVSPlugin::initialize(const QStringList & /*arguments */, QString *errorMes
|
|||||||
|
|
||||||
m_submitCurrentLogAction = new QAction(VCSBase::VCSBaseSubmitEditor::submitIcon(), tr("Commit"), this);
|
m_submitCurrentLogAction = new QAction(VCSBase::VCSBaseSubmitEditor::submitIcon(), tr("Commit"), this);
|
||||||
command = ami->registerAction(m_submitCurrentLogAction, Constants::SUBMIT_CURRENT, cvscommitcontext);
|
command = ami->registerAction(m_submitCurrentLogAction, Constants::SUBMIT_CURRENT, cvscommitcontext);
|
||||||
|
command->setAttribute(Core::Command::CA_UpdateText);
|
||||||
connect(m_submitCurrentLogAction, SIGNAL(triggered()), this, SLOT(submitCurrentLog()));
|
connect(m_submitCurrentLogAction, SIGNAL(triggered()), this, SLOT(submitCurrentLog()));
|
||||||
|
|
||||||
m_submitDiffAction = new QAction(VCSBase::VCSBaseSubmitEditor::diffIcon(), tr("Diff Selected Files"), this);
|
m_submitDiffAction = new QAction(VCSBase::VCSBaseSubmitEditor::diffIcon(), tr("Diff Selected Files"), this);
|
||||||
|
@@ -500,6 +500,7 @@ bool GitPlugin::initialize(const QStringList &arguments, QString *errorMessage)
|
|||||||
Core::Context submitContext(Constants::C_GITSUBMITEDITOR);
|
Core::Context submitContext(Constants::C_GITSUBMITEDITOR);
|
||||||
m_submitCurrentAction = new QAction(VCSBase::VCSBaseSubmitEditor::submitIcon(), tr("Commit"), this);
|
m_submitCurrentAction = new QAction(VCSBase::VCSBaseSubmitEditor::submitIcon(), tr("Commit"), this);
|
||||||
Core::Command *command = actionManager->registerAction(m_submitCurrentAction, Constants::SUBMIT_CURRENT, submitContext);
|
Core::Command *command = actionManager->registerAction(m_submitCurrentAction, Constants::SUBMIT_CURRENT, submitContext);
|
||||||
|
command->setAttribute(Core::Command::CA_UpdateText);
|
||||||
connect(m_submitCurrentAction, SIGNAL(triggered()), this, SLOT(submitCurrentLog()));
|
connect(m_submitCurrentAction, SIGNAL(triggered()), this, SLOT(submitCurrentLog()));
|
||||||
|
|
||||||
m_diffSelectedFilesAction = new QAction(VCSBase::VCSBaseSubmitEditor::diffIcon(), tr("Diff Selected Files"), this);
|
m_diffSelectedFilesAction = new QAction(VCSBase::VCSBaseSubmitEditor::diffIcon(), tr("Diff Selected Files"), this);
|
||||||
|
@@ -538,6 +538,7 @@ void MercurialPlugin::createSubmitEditorActions()
|
|||||||
|
|
||||||
editorCommit = new QAction(VCSBase::VCSBaseSubmitEditor::submitIcon(), tr("Commit"), this);
|
editorCommit = new QAction(VCSBase::VCSBaseSubmitEditor::submitIcon(), tr("Commit"), this);
|
||||||
command = actionManager->registerAction(editorCommit, QLatin1String(Constants::COMMIT), context);
|
command = actionManager->registerAction(editorCommit, QLatin1String(Constants::COMMIT), context);
|
||||||
|
command->setAttribute(Core::Command::CA_UpdateText);
|
||||||
connect(editorCommit, SIGNAL(triggered()), this, SLOT(commitFromEditor()));
|
connect(editorCommit, SIGNAL(triggered()), this, SLOT(commitFromEditor()));
|
||||||
|
|
||||||
editorDiff = new QAction(VCSBase::VCSBaseSubmitEditor::diffIcon(), tr("Diff Selected Files"), this);
|
editorDiff = new QAction(VCSBase::VCSBaseSubmitEditor::diffIcon(), tr("Diff Selected Files"), this);
|
||||||
|
@@ -435,6 +435,7 @@ bool PerforcePlugin::initialize(const QStringList & /* arguments */, QString *er
|
|||||||
|
|
||||||
m_submitCurrentLogAction = new QAction(VCSBase::VCSBaseSubmitEditor::submitIcon(), tr("Submit"), this);
|
m_submitCurrentLogAction = new QAction(VCSBase::VCSBaseSubmitEditor::submitIcon(), tr("Submit"), this);
|
||||||
command = am->registerAction(m_submitCurrentLogAction, Constants::SUBMIT_CURRENT, perforcesubmitcontext);
|
command = am->registerAction(m_submitCurrentLogAction, Constants::SUBMIT_CURRENT, perforcesubmitcontext);
|
||||||
|
command->setAttribute(Core::Command::CA_UpdateText);
|
||||||
connect(m_submitCurrentLogAction, SIGNAL(triggered()), this, SLOT(submitCurrentLog()));
|
connect(m_submitCurrentLogAction, SIGNAL(triggered()), this, SLOT(submitCurrentLog()));
|
||||||
|
|
||||||
m_diffSelectedFiles = new QAction(VCSBase::VCSBaseSubmitEditor::diffIcon(), tr("Diff Selected Files"), this);
|
m_diffSelectedFiles = new QAction(VCSBase::VCSBaseSubmitEditor::diffIcon(), tr("Diff Selected Files"), this);
|
||||||
|
@@ -458,6 +458,7 @@ bool SubversionPlugin::initialize(const QStringList & /*arguments */, QString *e
|
|||||||
|
|
||||||
m_submitCurrentLogAction = new QAction(VCSBase::VCSBaseSubmitEditor::submitIcon(), tr("Commit"), this);
|
m_submitCurrentLogAction = new QAction(VCSBase::VCSBaseSubmitEditor::submitIcon(), tr("Commit"), this);
|
||||||
command = ami->registerAction(m_submitCurrentLogAction, Constants::SUBMIT_CURRENT, svncommitcontext);
|
command = ami->registerAction(m_submitCurrentLogAction, Constants::SUBMIT_CURRENT, svncommitcontext);
|
||||||
|
command->setAttribute(Core::Command::CA_UpdateText);
|
||||||
connect(m_submitCurrentLogAction, SIGNAL(triggered()), this, SLOT(submitCurrentLog()));
|
connect(m_submitCurrentLogAction, SIGNAL(triggered()), this, SLOT(submitCurrentLog()));
|
||||||
|
|
||||||
m_submitDiffAction = new QAction(VCSBase::VCSBaseSubmitEditor::diffIcon(), tr("Diff Selected Files"), this);
|
m_submitDiffAction = new QAction(VCSBase::VCSBaseSubmitEditor::diffIcon(), tr("Diff Selected Files"), this);
|
||||||
|
Reference in New Issue
Block a user