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/QPointer>
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtCore/QScopedPointer>
|
||||
|
||||
#include <QtGui/QPushButton>
|
||||
#include <QtGui/QMenu>
|
||||
@@ -44,6 +45,8 @@
|
||||
enum { debug = 0 };
|
||||
enum { defaultLineWidth = 72 };
|
||||
|
||||
enum { checkableColumn = 0 };
|
||||
|
||||
namespace Utils {
|
||||
|
||||
// QActionPushButton: A push button tied to an action
|
||||
@@ -68,10 +71,27 @@ QActionPushButton::QActionPushButton(QAction *a) :
|
||||
|
||||
void QActionPushButton::actionChanged()
|
||||
{
|
||||
if (const QAction *a = qobject_cast<QAction*>(sender()))
|
||||
if (const QAction *a = qobject_cast<QAction*>(sender())) {
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
const QModelIndex index = model->index(row, column, QModelIndex());
|
||||
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
|
||||
QList<int> selectedRows(const QAbstractItemView *view)
|
||||
{
|
||||
@@ -151,6 +171,9 @@ SubmitEditorWidget::SubmitEditorWidget(QWidget *parent) :
|
||||
this, SLOT(editorCustomContextMenuRequested(QPoint)));
|
||||
|
||||
// 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->setRootIsDecorated(false);
|
||||
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);
|
||||
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));
|
||||
}
|
||||
if (diffAction) {
|
||||
@@ -212,8 +240,11 @@ void SubmitEditorWidget::unregisterActions(QAction *editorUndoAction, QAction *
|
||||
disconnect(editorRedoAction, SIGNAL(triggered()), m_d->m_ui.description, SLOT(redo()));
|
||||
}
|
||||
|
||||
if (submitAction)
|
||||
if (submitAction) {
|
||||
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) {
|
||||
disconnect(this, SIGNAL(fileSelectionChanged(bool)), diffAction, SLOT(setEnabled(bool)));
|
||||
@@ -374,7 +405,7 @@ QStringList SubmitEditorWidget::checkedFiles() const
|
||||
return rc;
|
||||
const int count = model->rowCount();
|
||||
for (int i = 0; i < count; i++)
|
||||
if (listModelChecked(model, i, 0))
|
||||
if (listModelChecked(model, i, checkableColumn))
|
||||
rc.push_back(listModelText(model, i, fileNameColumn()));
|
||||
return rc;
|
||||
}
|
||||
@@ -414,11 +445,19 @@ void SubmitEditorWidget::updateActions()
|
||||
// Enable submit depending on having checked files
|
||||
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) {
|
||||
m_d->m_filesChecked = newFilesCheckedState;
|
||||
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
|
||||
@@ -439,11 +478,16 @@ bool SubmitEditorWidget::hasSelection() const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SubmitEditorWidget::hasCheckedFiles() const
|
||||
unsigned SubmitEditorWidget::checkedFilesCount() const
|
||||
{
|
||||
if (const QAbstractItemModel *model = m_d->m_ui.fileView->model())
|
||||
return listModelContainsCheckedItem(model);
|
||||
return false;
|
||||
unsigned checkedCount = 0;
|
||||
if (const QAbstractItemModel *model = m_d->m_ui.fileView->model()) {
|
||||
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)
|
||||
@@ -496,7 +540,7 @@ void SubmitEditorWidget::insertDescriptionEditContextMenuAction(int pos, QAction
|
||||
|
||||
void SubmitEditorWidget::editorCustomContextMenuRequested(const QPoint &pos)
|
||||
{
|
||||
QMenu *menu = m_d->m_ui.description->createStandardContextMenu();
|
||||
QScopedPointer<QMenu> menu(m_d->m_ui.description->createStandardContextMenu());
|
||||
// Extend
|
||||
foreach (const SubmitEditorWidgetPrivate::AdditionalContextMenuAction &a, m_d->descriptionEditContextMenuActions) {
|
||||
if (a.second) {
|
||||
@@ -508,7 +552,33 @@ void SubmitEditorWidget::editorCustomContextMenuRequested(const QPoint &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
|
||||
|
@@ -80,6 +80,9 @@ public:
|
||||
explicit SubmitEditorWidget(QWidget *parent = 0);
|
||||
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,
|
||||
QAction *submitAction = 0, QAction *diffAction = 0);
|
||||
void unregisterActions(QAction *editorUndoAction, QAction *editorRedoAction,
|
||||
@@ -121,6 +124,11 @@ signals:
|
||||
void diffSelected(const QStringList &);
|
||||
void fileSelectionChanged(bool someFileSelected);
|
||||
void fileCheckStateChanged(bool someFileChecked);
|
||||
void submitActionTextChanged(const QString &);
|
||||
|
||||
public slots:
|
||||
void checkAll();
|
||||
void uncheckAll();
|
||||
|
||||
protected:
|
||||
virtual void changeEvent(QEvent *e);
|
||||
@@ -134,10 +142,11 @@ private slots:
|
||||
void updateSubmitAction();
|
||||
void updateDiffAction();
|
||||
void editorCustomContextMenuRequested(const QPoint &);
|
||||
void fileListCustomContextMenuRequested(const QPoint & pos);
|
||||
|
||||
private:
|
||||
bool hasSelection() const;
|
||||
bool hasCheckedFiles() const;
|
||||
unsigned checkedFilesCount() const;
|
||||
|
||||
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);
|
||||
command = ami->registerAction(m_submitCurrentLogAction, Constants::SUBMIT_CURRENT, cvscommitcontext);
|
||||
command->setAttribute(Core::Command::CA_UpdateText);
|
||||
connect(m_submitCurrentLogAction, SIGNAL(triggered()), this, SLOT(submitCurrentLog()));
|
||||
|
||||
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);
|
||||
m_submitCurrentAction = new QAction(VCSBase::VCSBaseSubmitEditor::submitIcon(), tr("Commit"), this);
|
||||
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()));
|
||||
|
||||
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);
|
||||
command = actionManager->registerAction(editorCommit, QLatin1String(Constants::COMMIT), context);
|
||||
command->setAttribute(Core::Command::CA_UpdateText);
|
||||
connect(editorCommit, SIGNAL(triggered()), this, SLOT(commitFromEditor()));
|
||||
|
||||
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);
|
||||
command = am->registerAction(m_submitCurrentLogAction, Constants::SUBMIT_CURRENT, perforcesubmitcontext);
|
||||
command->setAttribute(Core::Command::CA_UpdateText);
|
||||
connect(m_submitCurrentLogAction, SIGNAL(triggered()), this, SLOT(submitCurrentLog()));
|
||||
|
||||
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);
|
||||
command = ami->registerAction(m_submitCurrentLogAction, Constants::SUBMIT_CURRENT, svncommitcontext);
|
||||
command->setAttribute(Core::Command::CA_UpdateText);
|
||||
connect(m_submitCurrentLogAction, SIGNAL(triggered()), this, SLOT(submitCurrentLog()));
|
||||
|
||||
m_submitDiffAction = new QAction(VCSBase::VCSBaseSubmitEditor::diffIcon(), tr("Diff Selected Files"), this);
|
||||
|
Reference in New Issue
Block a user