From a180af38797f23b975bc092cf75e9703c4c93921 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Sun, 12 May 2013 06:38:47 -0700 Subject: Modify selection changed slot to deal with trips correctly If a user clicks on a trip, all the dives in a trip should be selected. But if a user selects a range of dives that happens to have a trip header in it, then only the range of dives should be selected (the trip header is marked as 'selected' for visual consistency, even though not all dives in this trip are selected). This also changes the code to scrollTo the first selected dive instead of just expanding the parent. This seems to give us a more pleasant visual appearance (trying to keep the selected dive centered in the dive list) and as a side effect no longer hides the first dive trip at program start (before this change the first dive in the first trip would be the top entry in the dive list, with its trip just out of sight above). Signed-off-by: Dirk Hohndel --- qt-ui/mainwindow.cpp | 68 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 65 insertions(+), 3 deletions(-) (limited to 'qt-ui') diff --git a/qt-ui/mainwindow.cpp b/qt-ui/mainwindow.cpp index 863e35088..91de38a3f 100644 --- a/qt-ui/mainwindow.cpp +++ b/qt-ui/mainwindow.cpp @@ -87,19 +87,81 @@ void MainWindow::on_actionOpen_triggered() void MainWindow::dive_selection_changed(const QItemSelection& newSelection, const QItemSelection& oldSelection) { + int cnt, i; /* first deselect the dives that are no longer selected */ - Q_FOREACH(const QModelIndex& desselect, oldSelection.indexes()) { - struct dive *d = (struct dive*) desselect.data(TreeItemDT::DIVE_ROLE).value(); + Q_FOREACH(const QModelIndex& deselect, oldSelection.indexes()) { + struct dive *d = (struct dive*) deselect.data(TreeItemDT::DIVE_ROLE).value(); + if (!d) { + // this is a trip - if just the trip is deselected but not its children, + // then we manually need to deselect its children + const QAbstractItemModel *model = deselect.model(); + cnt = model->rowCount(deselect); + if (cnt == 0) + continue; + for (i = 0; i < cnt; i++) { + QModelIndex child = deselect.child(i,0); + if (oldSelection.contains(child)) + break; + } + // if none of the dives were in the deselect list (so the user only ctrl-clicked + // on the trip header) then manually deselect all the dives + if (i == model->rowCount(deselect)) { + QItemSelectionModel::SelectionFlags flags = (QItemSelectionModel::Deselect | + QItemSelectionModel::Rows); + QItemSelection removedDives = QItemSelection(); + removedDives.select(deselect.child(0,0), deselect.child(i - 1,0)); + ui->ListWidget->selectionModel()->select(removedDives,flags); + } + } if (!d || !d->selected) continue; deselect_dive(get_divenr(d)); } /* then select the newly selected dives */ + bool needToScroll = TRUE; Q_FOREACH(const QModelIndex& select, newSelection.indexes()) { struct dive *d = (struct dive*) select.data(TreeItemDT::DIVE_ROLE).value(); + if (!d) { + // this is a trip + const QAbstractItemModel *model = select.model(); + cnt = model->rowCount(select); + if (cnt == 0) + continue; + for (i = 0; i < cnt; i++) { + QModelIndex child = select.child(i,0); + if (newSelection.contains(child)) + break; + } + // if just the trip header was clicked and none of its children, + // select all of them + if (i == model->rowCount(select)) { + if (needToScroll) { + // make sure the trip header is visible + needToScroll = FALSE; + ui->ListWidget->scrollTo(select, QAbstractItemView::PositionAtCenter); + } + QItemSelectionModel::SelectionFlags flags = (QItemSelectionModel::Select | + QItemSelectionModel::Rows); + QItemSelection addedDives = QItemSelection(); + addedDives.select(select.child(0,0), select.child(i - 1,0)); + ui->ListWidget->selectionModel()->select(addedDives,flags); + } + } if (!d || d->selected) continue; select_dive(get_divenr(d)); + if (needToScroll) { + // make sure at least one of them is visible in the list + // and if this is the first dive of a trip, make the trip visible, too + needToScroll = FALSE; + if (select.row() == 0 && d->divetrip && select.parent().isValid()) + ui->ListWidget->scrollTo(select.parent(), QAbstractItemView::PositionAtCenter); + else + ui->ListWidget->scrollTo(select, QAbstractItemView::PositionAtCenter); + } else { + // but all selected dives should be in expanded trips + ui->ListWidget->expand(select.parent()); + } } redrawProfile(); ui->InfoWidget->updateDiveInfo(selected_dive); @@ -352,7 +414,7 @@ void MainWindow::readSettings() ui->ListWidget->resizeColumnToContents(i); } ui->ListWidget->collapseAll(); - ui->ListWidget->expand(sortModel->index(0,0)); + ui->ListWidget->scrollTo(sortModel->index(0,0), QAbstractItemView::PositionAtCenter); settings.endGroup(); settings.beginGroup("Units"); GET_UNIT(v, "feet", length, units::METERS, units::FEET); -- cgit v1.2.3-70-g09d2 From c729ae92ed1ea444ed2c9a38178ebe4cb22e54c4 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Sun, 12 May 2013 06:54:34 -0700 Subject: Allow walking the dive list with the cursor keys Figure out what is our first selected element (in case we start out from a multiple selection) and then move to the next logical element. So the code traverses an expanded tree (from a trip 'down' to its first dive or 'up' to the last dive of the previous trip - and similar from a first dive in a trip 'up' to its trip and from a last dive in a trip 'down' to the next trip. This does not take 'shift-cursor-up/down' into account (i.e. manual selection extension). Instead with just cursor up and down a single dive (or single trip) is selected. My guess is that the code will make someone's eyes bleed. Be warned. Signed-off-by: Dirk Hohndel --- qt-ui/mainwindow.cpp | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++ qt-ui/mainwindow.h | 8 +++++ 2 files changed, 106 insertions(+) (limited to 'qt-ui') diff --git a/qt-ui/mainwindow.cpp b/qt-ui/mainwindow.cpp index 91de38a3f..3ba4e6881 100644 --- a/qt-ui/mainwindow.cpp +++ b/qt-ui/mainwindow.cpp @@ -43,6 +43,14 @@ MainWindow::MainWindow() : ui(new Ui::MainWindow()), ui->ListWidget->setCurrentIndex(sortModel->index(0,0, firstDiveOrTrip)); else ui->ListWidget->setCurrentIndex(firstDiveOrTrip); + QAction *actionNextDive = new QAction(this); + addAction(actionNextDive); + actionNextDive->setShortcut(Qt::Key_Down); + connect(actionNextDive, SIGNAL(triggered()), this, SLOT(nextDive_triggered())); + QAction *actionPreviousDive = new QAction(this); + addAction(actionPreviousDive); + actionPreviousDive->setShortcut(Qt::Key_Up); + connect(actionPreviousDive, SIGNAL(triggered()), this, SLOT(previousDive_triggered())); } void MainWindow::redrawProfile() @@ -50,6 +58,96 @@ void MainWindow::redrawProfile() ui->ProfileWidget->plot(get_dive(selected_dive)); } +void MainWindow::nextDive_triggered() +{ + // Get the current Selection: + QItemSelectionModel *m = ui->ListWidget->selectionModel(); + QModelIndexList selection = m->selectedRows(); + + if (!selection.size()) + return; + + // check if it's a dive or trip: + QModelIndex index = selection.first(); + struct dive *d = (struct dive*) index.data(TreeItemDT::DIVE_ROLE).value(); + const QAbstractItemModel *model = index.model(); + + QItemSelectionModel::SelectionFlags flags = (QItemSelectionModel::Select | QItemSelectionModel::Rows); + + if (d) { + // it's a dive. + QModelIndex trip = index.parent(); + + // checks if it's the last dive on a trip list: + if (index.row() == model->rowCount(trip) - 1) { + // selects a trip. + QModelIndex nexttrip = model->index(trip.row()+1, trip.column(), trip.parent()); + if (nexttrip.isValid()) { + m->clear(); + m->select(nexttrip, flags); + } + } else { + m->clear(); + m->select(model->index(index.row()+1, index.column(), index.parent()), flags); + } + } else { + // it's a trip (and we have no empty trips, so there is a first child) + QModelIndex child = index.child(0,0); + m->select(model->index(0, index.column(), index), flags); + } +} + +void MainWindow::previousDive_triggered() +{ + // Get the current Selection: + QItemSelectionModel *m = ui->ListWidget->selectionModel(); + QModelIndexList selection = m->selectedRows(); + + if (!selection.size()) + return; + + // check if it's a dive or trip: + QModelIndex index = selection.first(); + struct dive *d = (struct dive*) index.data(TreeItemDT::DIVE_ROLE).value(); + const QAbstractItemModel *model = index.model(); + + QItemSelectionModel::SelectionFlags flags = (QItemSelectionModel::Select | QItemSelectionModel::Rows); + + if (d) { + // it's a dive. + QModelIndex trip = index.parent(); + + // checks if it's the first dive on a trip list: + if (index.row() == 0) { + if (trip.isValid()) { + // select the trip this dive is in + m->clear(); + m->select(model->index(trip.row(), trip.column(), trip.parent()),flags); + } + } else { + // select the previous dive + m->clear(); + m->select(model->index(index.row() - 1, index.column(), index.parent()), flags); + } + } else { + // it's a trip. + if (index.row() != 0) { + QModelIndex prevtrip = index.sibling(index.row() - 1, 0); + if (!prevtrip.isValid()) + return; + int cnt = prevtrip.model()->rowCount(); + QModelIndex child = prevtrip.child(prevtrip.model()->rowCount() - 1, 0); + /* I don't understand why this gives me incorrect rowCount... */ + while(!child.isValid() && cnt > 0) + child = prevtrip.child(--cnt, 0); + if (!child.isValid()) + return; + m->clear(); + m->select(model->index(child.row(), index.column(), prevtrip), flags); + } + } +} + void MainWindow::on_actionNew_triggered() { qDebug("actionNew"); diff --git a/qt-ui/mainwindow.h b/qt-ui/mainwindow.h index b76199a8b..8c07d048c 100644 --- a/qt-ui/mainwindow.h +++ b/qt-ui/mainwindow.h @@ -9,6 +9,7 @@ #include #include +#include class QSortFilterProxyModel; class DiveTripModel; @@ -68,6 +69,10 @@ private Q_SLOTS: void on_actionAboutSubsurface_triggered(); void on_actionUserManual_triggered(); + /* keyboard actions */ + void nextDive_triggered(); + void previousDive_triggered(); + void dive_selection_changed(const QItemSelection& newSelection, const QItemSelection& oldSelection); @@ -78,6 +83,9 @@ private: Ui::MainWindow *ui; DiveTripModel *model; QSortFilterProxyModel *sortModel; + QAction *actionNextDive; + QAction *actionPreviousDive; + QString filter(); bool askSaveChanges(); void readSettings(); -- cgit v1.2.3-70-g09d2