Fixes: Use a model for the submit file list (to resolve the git diff mess)

This commit is contained in:
Friedemann Kleint
2009-01-12 17:44:04 +01:00
parent 349c055d47
commit 17daca603a
21 changed files with 602 additions and 343 deletions

View File

@@ -36,6 +36,7 @@
#include <QtCore/QDebug>
#include <QtCore/QPointer>
#include <QtCore/QTimer>
#include <QtGui/QPushButton>
@@ -70,6 +71,42 @@ void QActionPushButton::actionChanged()
setEnabled(a->isEnabled());
}
// Helpers to retrieve model data
static inline bool listModelChecked(const QAbstractItemModel *model, int row, int column = 0)
{
const QModelIndex checkableIndex = model->index(row, column, QModelIndex());
return model->data(checkableIndex, Qt::CheckStateRole).toInt() == Qt::Checked;
}
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)
{
const QModelIndexList indexList = view->selectionModel()->selectedRows(0);
if (indexList.empty())
return QList<int>();
QList<int> rc;
const QModelIndexList::const_iterator cend = indexList.constEnd();
for (QModelIndexList::const_iterator it = indexList.constBegin(); it != cend; ++it)
rc.push_back(it->row());
return rc;
}
// ----------- SubmitEditorWidgetPrivate
struct SubmitEditorWidgetPrivate
{
@@ -78,11 +115,15 @@ struct SubmitEditorWidgetPrivate
Ui::SubmitEditorWidget m_ui;
bool m_filesSelected;
bool m_filesChecked;
int m_fileNameColumn;
int m_activatedRow;
};
SubmitEditorWidgetPrivate::SubmitEditorWidgetPrivate() :
m_filesSelected(false),
m_filesChecked(false)
m_filesChecked(false),
m_fileNameColumn(1),
m_activatedRow(-1)
{
}
@@ -92,10 +133,10 @@ SubmitEditorWidget::SubmitEditorWidget(QWidget *parent) :
{
m_d->m_ui.setupUi(this);
// File List
m_d->m_ui.fileList->setSelectionMode(QAbstractItemView::ExtendedSelection);
connect(m_d->m_ui.fileList, SIGNAL(itemActivated(QListWidgetItem*)), this, SLOT(triggerDiffSelected()));
connect(m_d->m_ui.fileList, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(fileItemChanged(QListWidgetItem*)));
connect(m_d->m_ui.fileList, SIGNAL(itemSelectionChanged()), this, SLOT(fileSelectionChanged()));
m_d->m_ui.fileView->setSelectionMode(QAbstractItemView::ExtendedSelection);
m_d->m_ui.fileView->setRootIsDecorated(false);
connect(m_d->m_ui.fileView, SIGNAL(doubleClicked(QModelIndex)),
this, SLOT(diffActivated(QModelIndex)));
// Text
m_d->m_ui.description->setFont(QFont(QLatin1String("Courier")));
@@ -124,8 +165,12 @@ void SubmitEditorWidget::registerActions(QAction *editorUndoAction, QAction *ed
}
if (submitAction) {
if (debug)
qDebug() << submitAction << m_d->m_ui.fileList->count() << "items" << m_d->m_filesChecked;
if (debug) {
int count = 0;
if (const QAbstractItemModel *model = m_d->m_ui.fileView->model())
count = model->rowCount();
qDebug() << submitAction << count << "items" << m_d->m_filesChecked;
}
submitAction->setEnabled(m_d->m_filesChecked);
connect(this, SIGNAL(fileCheckStateChanged(bool)), submitAction, SLOT(setEnabled(bool)));
m_d->m_ui.buttonLayout->addWidget(new QActionPushButton(submitAction));
@@ -161,7 +206,6 @@ void SubmitEditorWidget::unregisterActions(QAction *editorUndoAction, QAction *
}
}
QString SubmitEditorWidget::trimmedDescriptionText() const
{
// Make sure we have one terminating NL
@@ -180,91 +224,70 @@ void SubmitEditorWidget::setDescriptionText(const QString &text)
m_d->m_ui.description->setPlainText(text);
}
QStringList SubmitEditorWidget::fileList() const
int SubmitEditorWidget::fileNameColumn() const
{
QStringList rc;
const int count = m_d->m_ui.fileList->count();
for (int i = 0; i < count; i++)
rc.push_back(m_d->m_ui.fileList->item(i)->text());
return rc;
return m_d->m_fileNameColumn;
}
void SubmitEditorWidget::addFilesUnblocked(const QStringList &list, bool checked, bool userCheckable)
void SubmitEditorWidget::setFileNameColumn(int c)
{
if (debug)
qDebug() << Q_FUNC_INFO << list << checked << userCheckable;
foreach (const QString &f, list) {
QListWidgetItem *item = new QListWidgetItem(f);
item->setCheckState(checked ? Qt::Checked : Qt::Unchecked);
if (!userCheckable)
item->setFlags(item->flags() & ~Qt::ItemIsUserCheckable);
m_d->m_ui.fileList->addItem(item);
m_d->m_fileNameColumn = c;
}
void SubmitEditorWidget::setFileModel(QAbstractItemModel *model)
{
m_d->m_ui.fileView->clearSelection(); // trigger the change signals
m_d->m_ui.fileView->setModel(model);
if (model->rowCount()) {
const int columnCount = model->columnCount();
for (int c = 0; c < columnCount; c++)
m_d->m_ui.fileView->resizeColumnToContents(c);
}
connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
this, SLOT(updateSubmitAction()));
connect(model, SIGNAL(modelReset()),
this, SLOT(updateSubmitAction()));
connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
this, SLOT(updateSubmitAction()));
connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
this, SLOT(updateSubmitAction()));
connect(m_d->m_ui.fileView->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
this, SLOT(updateDiffAction()));
updateActions();
}
void SubmitEditorWidget::addFiles(const QStringList &list, bool checked, bool userCheckable)
QAbstractItemModel *SubmitEditorWidget::fileModel() const
{
if (list.empty())
return;
const bool blocked = m_d->m_ui.fileList->blockSignals(true);
addFilesUnblocked(list, checked, userCheckable);
m_d->m_ui.fileList->blockSignals(blocked);
// Did we gain any checked files..update action accordingly
if (!m_d->m_filesChecked && checked) {
m_d->m_filesChecked = true;
emit fileCheckStateChanged(m_d->m_filesChecked);
}
}
void SubmitEditorWidget::setFileList(const QStringList &list)
{
// Trigger enabling of menu action
m_d->m_ui.fileList->clearSelection();
const bool blocked = m_d->m_ui.fileList->blockSignals(true);
m_d->m_ui.fileList->clear();
if (!list.empty()) {
addFilesUnblocked(list, true, true);
// Checked files added?
if (!m_d->m_filesChecked) {
m_d->m_filesChecked = true;
emit fileCheckStateChanged(m_d->m_filesChecked);
}
}
m_d->m_ui.fileList->blockSignals(blocked);
}
static bool containsCheckState(const QListWidget *lw, Qt::CheckState cs)
{
const int count = lw->count();
for (int i = 0; i < count; i++)
if (lw->item(i)->checkState() == cs)
return true;
return false;
return m_d->m_ui.fileView->model();
}
QStringList SubmitEditorWidget::selectedFiles() const
{
const QList<int> selection = selectedRows(m_d->m_ui.fileView);
if (selection.empty())
return QStringList();
QStringList rc;
const int count = m_d->m_ui.fileList->count();
for (int i = 0; i < count; i++) {
const QListWidgetItem *item = m_d->m_ui.fileList->item(i);
if (item->isSelected())
rc.push_back(item->text());
}
const QAbstractItemModel *model = m_d->m_ui.fileView->model();
const int count = selection.size();
for (int i = 0; i < count; i++)
rc.push_back(listModelText(model, selection.at(i), fileNameColumn()));
return rc;
}
QStringList SubmitEditorWidget::checkedFiles() const
{
QStringList rc;
const int count = m_d->m_ui.fileList->count();
for (int i = 0; i < count; i++) {
const QListWidgetItem *item = m_d->m_ui.fileList->item(i);
if (item->checkState() == Qt::Checked)
rc.push_back(item->text());
}
const QAbstractItemModel *model = m_d->m_ui.fileView->model();
if (!model)
return rc;
const int count = model->rowCount();
for (int i = 0; i < count; i++)
if (listModelChecked(model, i, 0))
rc.push_back(listModelText(model, i, fileNameColumn()));
return rc;
}
@@ -280,44 +303,61 @@ void SubmitEditorWidget::triggerDiffSelected()
emit diffSelected(sel);
}
void SubmitEditorWidget::fileItemChanged(QListWidgetItem *item)
void SubmitEditorWidget::diffActivatedDelayed()
{
const Qt::CheckState st = item->checkState();
if (debug)
qDebug() << Q_FUNC_INFO << st << item->text() << m_d->m_filesChecked;
// Enable the actions according to check state
switch (st) {
case Qt::Unchecked: // Item was unchecked: Any checked items left?
if (m_d->m_filesChecked && !containsCheckState(m_d->m_ui.fileList, Qt::Checked)) {
m_d->m_filesChecked = false;
emit fileCheckStateChanged(m_d->m_filesChecked);
}
break;
case Qt::Checked:
// Item was Checked. First one?
if (!m_d->m_filesChecked) {
m_d->m_filesChecked = true;
emit fileCheckStateChanged(m_d->m_filesChecked);
}
break;
case Qt::PartiallyChecked: // Errm?
break;
const QStringList files = QStringList(listModelText(m_d->m_ui.fileView->model(), m_d->m_activatedRow, fileNameColumn()));
emit diffSelected(files);
}
void SubmitEditorWidget::diffActivated(const QModelIndex &index)
{
// We need to delay the signal, otherwise, the diff editor will not
// be in the foreground.
m_d->m_activatedRow = index.row();
QTimer::singleShot(0, this, SLOT(diffActivatedDelayed()));
}
void SubmitEditorWidget::updateActions()
{
updateSubmitAction();
updateDiffAction();
}
// Enable submit depending on having checked files
void SubmitEditorWidget::updateSubmitAction()
{
const bool newFilesCheckedState = hasCheckedFiles();
if (m_d->m_filesChecked != newFilesCheckedState) {
m_d->m_filesChecked = newFilesCheckedState;
emit fileCheckStateChanged(m_d->m_filesChecked);
}
}
void SubmitEditorWidget::fileSelectionChanged()
// Enable diff depending on selected files
void SubmitEditorWidget::updateDiffAction()
{
const bool newFilesSelected = !m_d->m_ui.fileList->selectedItems().empty();
if (debug)
qDebug() << Q_FUNC_INFO << newFilesSelected;
if (m_d->m_filesSelected != newFilesSelected) {
m_d->m_filesSelected = newFilesSelected;
const bool filesSelected = hasSelection();
if (m_d->m_filesSelected != filesSelected) {
m_d->m_filesSelected = filesSelected;
emit fileSelectionChanged(m_d->m_filesSelected);
if (debug)
qDebug() << Q_FUNC_INFO << m_d->m_filesSelected;
}
}
bool SubmitEditorWidget::hasSelection() const
{
// Not present until model is set
if (const QItemSelectionModel *sm = m_d->m_ui.fileView->selectionModel())
return sm->hasSelection();
return false;
}
bool SubmitEditorWidget::hasCheckedFiles() const
{
if (const QAbstractItemModel *model = m_d->m_ui.fileView->model())
return listModelContainsCheckedItem(model);
return false;
}
void SubmitEditorWidget::changeEvent(QEvent *e)
{
switch (e->type()) {