Commit 817d4370 authored by Friedemann Kleint's avatar Friedemann Kleint
Browse files

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
parent e3f7a402
......@@ -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,20 +99,20 @@ static inline bool listModelChecked(const QAbstractItemModel *model, int row, in
return model->data(checkableIndex, Qt::CheckStateRole).toInt() == Qt::Checked;
}
static inline QString listModelText(const QAbstractItemModel *model, int row, int column)
static void setListModelChecked(QAbstractItemModel *model, bool checked, int column = 0)
{
const QModelIndex index = model->index(row, column, QModelIndex());
return model->data(index, Qt::DisplayRole).toString();
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);
}
}
// Find a check item in a model
static bool listModelContainsCheckedItem(const QAbstractItemModel *model)
static inline QString listModelText(const QAbstractItemModel *model, int row, int column)
{
const int count = model->rowCount();
for (int i = 0; i < count; i++)
if (listModelChecked(model, i, 0))
return true;
return false;
const QModelIndex index = model->index(row, column, QModelIndex());
return model->data(index, Qt::DisplayRole).toString();
}
// Convenience to extract a list of selected indexes
......@@ -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);
......
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