summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--desktop-widgets/divelistview.cpp122
-rw-r--r--desktop-widgets/divelistview.h3
-rw-r--r--desktop-widgets/mainwindow.cpp2
-rw-r--r--desktop-widgets/modeldelegates.cpp2
-rw-r--r--qt-models/divetripmodel.cpp725
-rw-r--r--qt-models/divetripmodel.h127
-rw-r--r--qt-models/filtermodels.cpp17
-rw-r--r--qt-models/filtermodels.h5
8 files changed, 612 insertions, 391 deletions
diff --git a/desktop-widgets/divelistview.cpp b/desktop-widgets/divelistview.cpp
index c340b556b..3ba9ba58f 100644
--- a/desktop-widgets/divelistview.cpp
+++ b/desktop-widgets/divelistview.cpp
@@ -28,20 +28,20 @@
#include "desktop-widgets/simplewidgets.h"
DiveListView::DiveListView(QWidget *parent) : QTreeView(parent), mouseClickSelection(false),
- currentLayout(DiveTripModel::TREE), dontEmitDiveChangedSignal(false), selectionSaved(false),
- initialColumnWidths(DiveTripModel::COLUMNS, 50) // Set up with default length 50
+ currentLayout(DiveTripModelBase::TREE), dontEmitDiveChangedSignal(false), selectionSaved(false),
+ initialColumnWidths(DiveTripModelBase::COLUMNS, 50) // Set up with default length 50
{
setItemDelegate(new DiveListDelegate(this));
setUniformRowHeights(true);
- setItemDelegateForColumn(DiveTripModel::RATING, new StarWidgetsDelegate(this));
+ setItemDelegateForColumn(DiveTripModelBase::RATING, new StarWidgetsDelegate(this));
setModel(MultiFilterSortModel::instance());
setSortingEnabled(true);
setContextMenuPolicy(Qt::DefaultContextMenu);
setSelectionMode(ExtendedSelection);
header()->setContextMenuPolicy(Qt::ActionsContextMenu);
- connect(DiveTripModel::instance(), &DiveTripModel::selectionChanged, this, &DiveListView::diveSelectionChanged);
- connect(DiveTripModel::instance(), &DiveTripModel::newCurrentDive, this, &DiveListView::currentDiveChanged);
+
+ resetModel();
// Update selection if all selected dives were hidden by filter
connect(MultiFilterSortModel::instance(), &MultiFilterSortModel::filterFinished, this, &DiveListView::filterFinished);
@@ -53,7 +53,7 @@ DiveListView::DiveListView(QWidget *parent) : QTreeView(parent), mouseClickSelec
installEventFilter(this);
- for (int i = DiveTripModel::NR; i < DiveTripModel::COLUMNS; i++)
+ for (int i = DiveTripModelBase::NR; i < DiveTripModelBase::COLUMNS; i++)
calculateInitialColumnWidth(i);
setColumnWidths();
}
@@ -63,7 +63,7 @@ DiveListView::~DiveListView()
QSettings settings;
settings.beginGroup("ListWidget");
// don't set a width for the last column - location is supposed to be "the rest"
- for (int i = DiveTripModel::NR; i < DiveTripModel::COLUMNS - 1; i++) {
+ for (int i = DiveTripModelBase::NR; i < DiveTripModelBase::COLUMNS - 1; i++) {
if (isColumnHidden(i))
continue;
// we used to hardcode them all to 100 - so that might still be in the settings
@@ -72,41 +72,50 @@ DiveListView::~DiveListView()
else
settings.setValue(QString("colwidth%1").arg(i), columnWidth(i));
}
- settings.remove(QString("colwidth%1").arg(DiveTripModel::COLUMNS - 1));
+ settings.remove(QString("colwidth%1").arg(DiveTripModelBase::COLUMNS - 1));
settings.endGroup();
}
+void DiveListView::resetModel()
+{
+ MultiFilterSortModel::instance()->resetModel(currentLayout);
+ // If the model was reset, we have to reconnect the signals and tell
+ // the filter model to update its source model.
+ connect(DiveTripModelBase::instance(), &DiveTripModelBase::selectionChanged, this, &DiveListView::diveSelectionChanged);
+ connect(DiveTripModelBase::instance(), &DiveTripModelBase::newCurrentDive, this, &DiveListView::currentDiveChanged);
+}
+
void DiveListView::calculateInitialColumnWidth(int col)
{
const QFontMetrics metrics(defaultModelFont());
int em = metrics.width('m');
int zw = metrics.width('0');
- QString header_txt = DiveTripModel::instance()->headerData(col, Qt::Horizontal, Qt::DisplayRole).toString();
+ QString header_txt = DiveTripModelBase::instance()->headerData(col, Qt::Horizontal, Qt::DisplayRole).toString();
int width = metrics.width(header_txt);
int sw = 0;
switch (col) {
- case DiveTripModel::NR:
- case DiveTripModel::DURATION:
+ case DiveTripModelBase::NR:
+ case DiveTripModelBase::DURATION:
sw = 8*zw;
break;
- case DiveTripModel::DATE:
+ case DiveTripModelBase::DATE:
sw = 14*em;
break;
- case DiveTripModel::RATING:
+ case DiveTripModelBase::RATING:
sw = static_cast<StarWidgetsDelegate*>(itemDelegateForColumn(col))->starSize().width();
break;
- case DiveTripModel::SUIT:
- case DiveTripModel::SAC:
+ case DiveTripModelBase::SUIT:
+ case DiveTripModelBase::SAC:
sw = 7*em;
break;
- case DiveTripModel::PHOTOS:
+ case DiveTripModelBase::PHOTOS:
sw = 5*em;
break;
- case DiveTripModel::BUDDIES:
+ case DiveTripModelBase::BUDDIES:
sw = 50*em;
break;
- case DiveTripModel::LOCATION:
+ case DiveTripModelBase::LOCATION:
sw = 50*em;
break;
default:
@@ -126,7 +135,7 @@ void DiveListView::setColumnWidths()
/* if no width are set, use the calculated width for each column;
* for that to work we need to temporarily expand all rows */
expandAll();
- for (int i = DiveTripModel::NR; i < DiveTripModel::COLUMNS; i++) {
+ for (int i = DiveTripModelBase::NR; i < DiveTripModelBase::COLUMNS; i++) {
if (isColumnHidden(i))
continue;
QVariant width = settings.value(QString("colwidth%1").arg(i));
@@ -143,7 +152,7 @@ void DiveListView::setColumnWidths()
int DiveListView::lastVisibleColumn()
{
int lastColumn = -1;
- for (int i = DiveTripModel::NR; i < DiveTripModel::COLUMNS; i++) {
+ for (int i = DiveTripModelBase::NR; i < DiveTripModelBase::COLUMNS; i++) {
if (isColumnHidden(i))
continue;
lastColumn = i;
@@ -249,11 +258,11 @@ void DiveListView::rememberSelection()
Q_FOREACH (const QModelIndex &index, selection.indexes()) {
if (index.column() != 0) // We only care about the dives, so, let's stick to rows and discard columns.
continue;
- struct dive *d = index.data(DiveTripModel::DIVE_ROLE).value<struct dive *>();
+ struct dive *d = index.data(DiveTripModelBase::DIVE_ROLE).value<struct dive *>();
if (d) {
selectedDives.insert(d->divetrip, get_divenr(d));
} else {
- struct dive_trip *t = index.data(DiveTripModel::TRIP_ROLE).value<dive_trip *>();
+ struct dive_trip *t = index.data(DiveTripModelBase::TRIP_ROLE).value<dive_trip *>();
if (t)
selectedDives.insert(t, -1);
}
@@ -289,7 +298,7 @@ void DiveListView::selectTrip(dive_trip_t *trip)
return;
QAbstractItemModel *m = model();
- QModelIndexList match = m->match(m->index(0, 0), DiveTripModel::TRIP_ROLE, QVariant::fromValue(trip), 2, Qt::MatchRecursive);
+ QModelIndexList match = m->match(m->index(0, 0), DiveTripModelBase::TRIP_ROLE, QVariant::fromValue(trip), 2, Qt::MatchRecursive);
QItemSelectionModel::SelectionFlags flags;
if (!match.count())
return;
@@ -314,7 +323,7 @@ void DiveListView::clearTripSelection()
// we want to make sure no trips are selected
Q_FOREACH (const QModelIndex &index, selectionModel()->selectedRows()) {
- dive_trip_t *trip = index.data(DiveTripModel::TRIP_ROLE).value<dive_trip *>();
+ dive_trip_t *trip = index.data(DiveTripModelBase::TRIP_ROLE).value<dive_trip *>();
if (!trip)
continue;
selectionModel()->select(index, QItemSelectionModel::Deselect);
@@ -343,7 +352,7 @@ QList<dive_trip_t *> DiveListView::selectedTrips()
{
QList<dive_trip_t *> ret;
Q_FOREACH (const QModelIndex &index, selectionModel()->selectedRows()) {
- dive_trip_t *trip = index.data(DiveTripModel::TRIP_ROLE).value<dive_trip *>();
+ dive_trip_t *trip = index.data(DiveTripModelBase::TRIP_ROLE).value<dive_trip *>();
if (!trip)
continue;
ret.push_back(trip);
@@ -374,7 +383,7 @@ void DiveListView::selectDive(int i, bool scrollto, bool toggle)
if (i == -1)
return;
QAbstractItemModel *m = model();
- QModelIndexList match = m->match(m->index(0, 0), DiveTripModel::DIVE_IDX, i, 2, Qt::MatchRecursive);
+ QModelIndexList match = m->match(m->index(0, 0), DiveTripModelBase::DIVE_IDX, i, 2, Qt::MatchRecursive);
if (match.isEmpty())
return;
QModelIndex idx = match.first();
@@ -411,7 +420,7 @@ void DiveListView::selectDives(const QList<int> &newDiveSelection)
selectDive(newSelection);
}
QAbstractItemModel *m = model();
- QModelIndexList idxList = m->match(m->index(0, 0), DiveTripModel::DIVE_IDX, get_divenr(current_dive), 2, Qt::MatchRecursive);
+ QModelIndexList idxList = m->match(m->index(0, 0), DiveTripModelBase::DIVE_IDX, get_divenr(current_dive), 2, Qt::MatchRecursive);
if (!idxList.isEmpty()) {
QModelIndex idx = idxList.first();
if (idx.parent().isValid())
@@ -462,7 +471,7 @@ bool DiveListView::eventFilter(QObject *, QEvent *event)
void DiveListView::sortIndicatorChanged(int i, Qt::SortOrder order)
{
- DiveTripModel::Layout newLayout = i == (int)DiveTripModel::NR ? DiveTripModel::TREE : DiveTripModel::LIST;
+ DiveTripModelBase::Layout newLayout = i == (int)DiveTripModelBase::NR ? DiveTripModelBase::TREE : DiveTripModelBase::LIST;
/* No layout change? Just re-sort, and scroll to first selection, making sure all selections are expanded */
if (currentLayout == newLayout) {
sortByColumn(i, order);
@@ -470,12 +479,12 @@ void DiveListView::sortIndicatorChanged(int i, Qt::SortOrder order)
// clear the model, repopulate with new indexes.
rememberSelection();
unselectDives();
- if (currentLayout == DiveTripModel::TREE)
+ if (currentLayout == DiveTripModelBase::TREE)
backupExpandedRows();
currentLayout = newLayout;
- MultiFilterSortModel::instance()->setLayout(newLayout);
+ resetModel();
sortByColumn(i, order);
- if (newLayout == DiveTripModel::TREE)
+ if (newLayout == DiveTripModelBase::TREE)
restoreExpandedRows();
restoreSelection();
}
@@ -489,8 +498,7 @@ void DiveListView::setSortOrder(int i, Qt::SortOrder order)
void DiveListView::reload()
{
- // A side-effect of setting the layout is reloading the model data
- MultiFilterSortModel::instance()->setLayout(currentLayout);
+ resetModel();
if (amount_selected && current_dive != NULL)
selectDive(get_divenr(current_dive), true);
@@ -519,15 +527,15 @@ void DiveListView::reloadHeaderActions()
QString title = QString("%1").arg(model()->headerData(i, Qt::Horizontal).toString());
QString settingName = QString("showColumn%1").arg(i);
QAction *a = new QAction(title, header());
- bool showHeaderFirstRun = !(i == DiveTripModel::MAXCNS ||
- i == DiveTripModel::GAS ||
- i == DiveTripModel::OTU ||
- i == DiveTripModel::TEMPERATURE ||
- i == DiveTripModel::TOTALWEIGHT ||
- i == DiveTripModel::SUIT ||
- i == DiveTripModel::CYLINDER ||
- i == DiveTripModel::SAC ||
- i == DiveTripModel::TAGS);
+ bool showHeaderFirstRun = !(i == DiveTripModelBase::MAXCNS ||
+ i == DiveTripModelBase::GAS ||
+ i == DiveTripModelBase::OTU ||
+ i == DiveTripModelBase::TEMPERATURE ||
+ i == DiveTripModelBase::TOTALWEIGHT ||
+ i == DiveTripModelBase::SUIT ||
+ i == DiveTripModelBase::CYLINDER ||
+ i == DiveTripModelBase::SAC ||
+ i == DiveTripModelBase::TAGS);
bool shown = s.value(settingName, showHeaderFirstRun).toBool();
a->setCheckable(true);
a->setChecked(shown);
@@ -608,9 +616,9 @@ void DiveListView::selectionChanged(const QItemSelection &selected, const QItemS
if (index.column() != 0)
continue;
const QAbstractItemModel *model = index.model();
- struct dive *dive = model->data(index, DiveTripModel::DIVE_ROLE).value<struct dive *>();
+ struct dive *dive = model->data(index, DiveTripModelBase::DIVE_ROLE).value<struct dive *>();
if (!dive) // it's a trip!
- deselect_dives_in_trip(model->data(index, DiveTripModel::TRIP_ROLE).value<dive_trip *>());
+ deselect_dives_in_trip(model->data(index, DiveTripModelBase::TRIP_ROLE).value<dive_trip *>());
else
deselect_dive(dive);
}
@@ -619,11 +627,11 @@ void DiveListView::selectionChanged(const QItemSelection &selected, const QItemS
continue;
const QAbstractItemModel *model = index.model();
- struct dive *dive = model->data(index, DiveTripModel::DIVE_ROLE).value<struct dive *>();
+ struct dive *dive = model->data(index, DiveTripModelBase::DIVE_ROLE).value<struct dive *>();
if (!dive) { // it's a trip!
if (model->rowCount(index)) {
QItemSelection selection;
- select_dives_in_trip(model->data(index, DiveTripModel::TRIP_ROLE).value<dive_trip *>());
+ select_dives_in_trip(model->data(index, DiveTripModelBase::TRIP_ROLE).value<dive_trip *>());
selection.select(index.child(0, 0), index.child(model->rowCount(index) - 1, 0));
selectionModel()->select(selection, QItemSelectionModel::Select | QItemSelectionModel::Rows);
selectionModel()->setCurrentIndex(index, QItemSelectionModel::Select | QItemSelectionModel::NoUpdate);
@@ -725,8 +733,8 @@ void DiveListView::merge_trip(const QModelIndex &a, int offset)
int i = a.row() + offset;
QModelIndex b = a.sibling(i, 0);
- dive_trip_t *trip_a = a.data(DiveTripModel::TRIP_ROLE).value<dive_trip *>();
- dive_trip_t *trip_b = b.data(DiveTripModel::TRIP_ROLE).value<dive_trip *>();
+ dive_trip_t *trip_a = a.data(DiveTripModelBase::TRIP_ROLE).value<dive_trip *>();
+ dive_trip_t *trip_b = b.data(DiveTripModelBase::TRIP_ROLE).value<dive_trip *>();
if (trip_a == trip_b || !trip_a || !trip_b)
return;
Command::mergeTrips(trip_a, trip_b);
@@ -757,7 +765,7 @@ void DiveListView::removeFromTrip()
void DiveListView::newTripAbove()
{
- struct dive *d = contextMenuIndex.data(DiveTripModel::DIVE_ROLE).value<struct dive *>();
+ struct dive *d = contextMenuIndex.data(DiveTripModelBase::DIVE_ROLE).value<struct dive *>();
if (!d) // shouldn't happen as we only are setting up this action if this is a dive
return;
//TODO: port to c-code.
@@ -783,7 +791,7 @@ void DiveListView::addToTripAbove()
void DiveListView::addToTrip(int delta)
{
// d points to the row that has (mouse-)pointer focus, and there are nr rows selected
- struct dive *d = contextMenuIndex.data(DiveTripModel::DIVE_ROLE).value<struct dive *>();
+ struct dive *d = contextMenuIndex.data(DiveTripModelBase::DIVE_ROLE).value<struct dive *>();
int nr = selectionModel()->selectedRows().count();
QModelIndex t;
dive_trip_t *trip = NULL;
@@ -792,7 +800,7 @@ void DiveListView::addToTrip(int delta)
// check if its sibling is a trip.
for (int i = 1; i <= nr; i++) {
t = contextMenuIndex.sibling(contextMenuIndex.row() + (delta > 0 ? i: i * -1), 0);
- trip = t.data(DiveTripModel::TRIP_ROLE).value<dive_trip *>();
+ trip = t.data(DiveTripModelBase::TRIP_ROLE).value<dive_trip *>();
if (trip)
break;
}
@@ -815,7 +823,7 @@ void DiveListView::addToTrip(int delta)
void DiveListView::markDiveInvalid()
{
int i;
- struct dive *d = contextMenuIndex.data(DiveTripModel::DIVE_ROLE).value<struct dive *>();
+ struct dive *d = contextMenuIndex.data(DiveTripModelBase::DIVE_ROLE).value<struct dive *>();
if (!d)
return;
for_each_dive (i, d) {
@@ -834,7 +842,7 @@ void DiveListView::markDiveInvalid()
void DiveListView::deleteDive()
{
- struct dive *d = contextMenuIndex.data(DiveTripModel::DIVE_ROLE).value<struct dive *>();
+ struct dive *d = contextMenuIndex.data(DiveTripModelBase::DIVE_ROLE).value<struct dive *>();
if (!d)
return;
@@ -852,17 +860,17 @@ void DiveListView::contextMenuEvent(QContextMenuEvent *event)
QAction *collapseAction = NULL;
// let's remember where we are
contextMenuIndex = indexAt(event->pos());
- struct dive *d = contextMenuIndex.data(DiveTripModel::DIVE_ROLE).value<struct dive *>();
- dive_trip_t *trip = contextMenuIndex.data(DiveTripModel::TRIP_ROLE).value<dive_trip *>();
+ struct dive *d = contextMenuIndex.data(DiveTripModelBase::DIVE_ROLE).value<struct dive *>();
+ dive_trip_t *trip = contextMenuIndex.data(DiveTripModelBase::TRIP_ROLE).value<dive_trip *>();
QMenu popup(this);
- if (currentLayout == DiveTripModel::TREE) {
+ if (currentLayout == DiveTripModelBase::TREE) {
// verify if there is a node that`s not expanded.
bool needs_expand = false;
bool needs_collapse = false;
uint expanded_nodes = 0;
for(int i = 0, end = model()->rowCount(); i < end; i++) {
QModelIndex idx = model()->index(i, 0);
- if (idx.data(DiveTripModel::DIVE_ROLE).value<struct dive *>())
+ if (idx.data(DiveTripModelBase::DIVE_ROLE).value<struct dive *>())
continue;
if (!isExpanded(idx)) {
diff --git a/desktop-widgets/divelistview.h b/desktop-widgets/divelistview.h
index 85d8bd21c..830447d92 100644
--- a/desktop-widgets/divelistview.h
+++ b/desktop-widgets/divelistview.h
@@ -68,7 +68,7 @@ slots:
private:
bool mouseClickSelection;
QList<int> expandedRows;
- DiveTripModel::Layout currentLayout;
+ DiveTripModelBase::Layout currentLayout;
QModelIndex contextMenuIndex;
bool dontEmitDiveChangedSignal;
bool selectionSaved;
@@ -77,6 +77,7 @@ private:
/* if dive_trip_t is null, there's no problem. */
QMultiHash<dive_trip_t *, int> selectedDives;
+ void resetModel(); // Call after model changed
void merge_trip(const QModelIndex &a, const int offset);
void setColumnWidths();
void calculateInitialColumnWidth(int col);
diff --git a/desktop-widgets/mainwindow.cpp b/desktop-widgets/mainwindow.cpp
index 6c0b42c9d..aba1cfc63 100644
--- a/desktop-widgets/mainwindow.cpp
+++ b/desktop-widgets/mainwindow.cpp
@@ -702,7 +702,7 @@ void MainWindow::cleanUpEmpty()
mainTab->updateDiveInfo(true);
graphics->setEmptyState();
diveList->reload();
- diveList->setSortOrder(DiveTripModel::NR, Qt::DescendingOrder);
+ diveList->setSortOrder(DiveTripModelBase::NR, Qt::DescendingOrder);
MapWidget::instance()->reload();
if (!existing_filename)
setTitle();
diff --git a/desktop-widgets/modeldelegates.cpp b/desktop-widgets/modeldelegates.cpp
index 41fe1c083..a237c1306 100644
--- a/desktop-widgets/modeldelegates.cpp
+++ b/desktop-widgets/modeldelegates.cpp
@@ -52,7 +52,7 @@ void StarWidgetsDelegate::paint(QPainter *painter, const QStyleOptionViewItem &o
if (!index.isValid())
return;
- QVariant value = index.model()->data(index, DiveTripModel::STAR_ROLE);
+ QVariant value = index.model()->data(index, DiveTripModelBase::STAR_ROLE);
if (!value.isValid())
return;
diff --git a/qt-models/divetripmodel.cpp b/qt-models/divetripmodel.cpp
index 7a76ffbdb..46f0b712e 100644
--- a/qt-models/divetripmodel.cpp
+++ b/qt-models/divetripmodel.cpp
@@ -9,6 +9,10 @@
#include "core/subsurface-qt/DiveListNotifier.h"
#include <QIcon>
#include <QDebug>
+#include <memory>
+#include <algorithm>
+
+// 1) Base functions
static int nitrox_sort_value(const struct dive *dive)
{
@@ -20,33 +24,33 @@ static int nitrox_sort_value(const struct dive *dive)
static QVariant dive_table_alignment(int column)
{
switch (column) {
- case DiveTripModel::DEPTH:
- case DiveTripModel::DURATION:
- case DiveTripModel::TEMPERATURE:
- case DiveTripModel::TOTALWEIGHT:
- case DiveTripModel::SAC:
- case DiveTripModel::OTU:
- case DiveTripModel::MAXCNS:
+ case DiveTripModelBase::DEPTH:
+ case DiveTripModelBase::DURATION:
+ case DiveTripModelBase::TEMPERATURE:
+ case DiveTripModelBase::TOTALWEIGHT:
+ case DiveTripModelBase::SAC:
+ case DiveTripModelBase::OTU:
+ case DiveTripModelBase::MAXCNS:
// Right align numeric columns
return int(Qt::AlignRight | Qt::AlignVCenter);
// NR needs to be left aligned because its the indent marker for trips too
- case DiveTripModel::NR:
- case DiveTripModel::DATE:
- case DiveTripModel::RATING:
- case DiveTripModel::SUIT:
- case DiveTripModel::CYLINDER:
- case DiveTripModel::GAS:
- case DiveTripModel::TAGS:
- case DiveTripModel::PHOTOS:
- case DiveTripModel::COUNTRY:
- case DiveTripModel::BUDDIES:
- case DiveTripModel::LOCATION:
+ case DiveTripModelBase::NR:
+ case DiveTripModelBase::DATE:
+ case DiveTripModelBase::RATING:
+ case DiveTripModelBase::SUIT:
+ case DiveTripModelBase::CYLINDER:
+ case DiveTripModelBase::GAS:
+ case DiveTripModelBase::TAGS:
+ case DiveTripModelBase::PHOTOS:
+ case DiveTripModelBase::COUNTRY:
+ case DiveTripModelBase::BUDDIES:
+ case DiveTripModelBase::LOCATION:
return int(Qt::AlignLeft | Qt::AlignVCenter);
}
return QVariant();
}
-QVariant DiveTripModel::tripData(const dive_trip *trip, int column, int role)
+QVariant DiveTripModelBase::tripData(const dive_trip *trip, int column, int role)
{
if (role == TRIP_ROLE)
@@ -54,7 +58,7 @@ QVariant DiveTripModel::tripData(const dive_trip *trip, int column, int role)
if (role == Qt::DisplayRole) {
switch (column) {
- case DiveTripModel::NR:
+ case DiveTripModelBase::NR:
QString shownText;
bool oneDayTrip = trip_is_single_day(trip);
int countShown = trip_shown_dives(trip);
@@ -128,7 +132,7 @@ static QString displayWeight(const struct dive *d, bool units)
return s + gettextFromC::tr("lbs");
}
-QVariant DiveTripModel::diveData(const struct dive *d, int column, int role)
+QVariant DiveTripModelBase::diveData(const struct dive *d, int column, int role)
{
switch (role) {
case Qt::TextAlignmentRole:
@@ -251,89 +255,7 @@ QVariant DiveTripModel::diveData(const struct dive *d, int column, int role)
return QVariant();
}
-DiveTripModel *DiveTripModel::instance()
-{
- static DiveTripModel self;
- return &self;
-}
-
-DiveTripModel::DiveTripModel(QObject *parent) :
- QAbstractItemModel(parent),
- currentLayout(TREE)
-{
- // Stay informed of changes to the divelist
- connect(&diveListNotifier, &DiveListNotifier::divesAdded, this, &DiveTripModel::divesAdded);
- connect(&diveListNotifier, &DiveListNotifier::divesDeleted, this, &DiveTripModel::divesDeleted);
- connect(&diveListNotifier, &DiveListNotifier::divesChanged, this, &DiveTripModel::divesChanged);
- connect(&diveListNotifier, &DiveListNotifier::divesMovedBetweenTrips, this, &DiveTripModel::divesMovedBetweenTrips);
- connect(&diveListNotifier, &DiveListNotifier::divesTimeChanged, this, &DiveTripModel::divesTimeChanged);
- connect(&diveListNotifier, &DiveListNotifier::divesSelected, this, &DiveTripModel::divesSelected);
- connect(&diveListNotifier, &DiveListNotifier::divesDeselected, this, &DiveTripModel::divesDeselected);
- connect(&diveListNotifier, &DiveListNotifier::currentDiveChanged, this, &DiveTripModel::currentDiveChanged);
-}
-
-int DiveTripModel::columnCount(const QModelIndex&) const
-{
- return COLUMNS;
-}
-
-int DiveTripModel::rowCount(const QModelIndex &parent) const
-{
- // No parent means top level - return the number of top-level items
- if (!parent.isValid())
- return items.size();
-
- // If the parent has a parent, this is a dive -> no entries
- if (parent.parent().isValid())
- return 0;
-
- // If this is outside of our top-level list -> no entries
- int row = parent.row();
- if (row < 0 || row >= (int)items.size())
- return 0;
-
- // Only trips have items
- const Item &entry = items[parent.row()];
- return entry.d_or_t.trip ? entry.dives.size() : 0;
-}
-
-static const quintptr noParent = ~(quintptr)0; // This is the "internalId" marker for top-level item
-
-QModelIndex DiveTripModel::index(int row, int column, const QModelIndex &parent) const
-{
- if (!hasIndex(row, column, parent))
- return QModelIndex();
-
- // In the "internalId", we store either ~0 no top-level items or the
- // index of the parent item. A top-level item has an invalid parent.
- return createIndex(row, column, parent.isValid() ? parent.row() : noParent);
-}
-
-QModelIndex DiveTripModel::parent(const QModelIndex &index) const
-{
- if (!index.isValid())
- return QModelIndex();
-
- // In the "internalId", we store either ~0 for top-level items
- // or the index of the parent item.
- quintptr id = index.internalId();
- if (id == noParent)
- return QModelIndex();
-
- // Parent must be top-level item
- return createIndex(id, 0, noParent);
-}
-
-Qt::ItemFlags DiveTripModel::flags(const QModelIndex &index) const
-{
- dive *d = diveOrNull(index);
- Qt::ItemFlags base = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
-
- // Only dives have editable fields and only the number is editable
- return d && index.column() == NR ? base | Qt::ItemIsEditable : base;
-}
-
-QVariant DiveTripModel::headerData(int section, Qt::Orientation orientation, int role) const
+QVariant DiveTripModelBase::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Vertical)
return QVariant();
@@ -431,33 +353,75 @@ QVariant DiveTripModel::headerData(int section, Qt::Orientation orientation, int
return QVariant();
}
-DiveTripModel::Item::Item(dive_trip *t, const QVector<dive *> &divesIn) : d_or_t{nullptr, t},
- dives(divesIn.toStdVector())
+static std::unique_ptr<DiveTripModelBase> currentModel;
+DiveTripModelBase *DiveTripModelBase::instance()
{
+ if (!currentModel)
+ resetModel(TREE);
+ return currentModel.get();
}
-DiveTripModel::Item::Item(dive_trip *t, dive *d) : d_or_t{nullptr, t},
- dives({ d })
+void DiveTripModelBase::resetModel(DiveTripModelBase::Layout layout)
{
+ if (layout == TREE)
+ currentModel.reset(new DiveTripModelTree);
+ else
+ currentModel.reset(new DiveTripModelList);
}
-DiveTripModel::Item::Item(dive *d) : d_or_t{d, nullptr}
+DiveTripModelBase::DiveTripModelBase(QObject *parent) : QAbstractItemModel(parent)
{
}
-bool DiveTripModel::Item::isDive(const dive *d) const
+int DiveTripModelBase::columnCount(const QModelIndex&) const
{
- return d_or_t.dive == d;
+ return COLUMNS;
}
-dive *DiveTripModel::Item::getDive() const
+Qt::ItemFlags DiveTripModelBase::flags(const QModelIndex &index) const
{
- return d_or_t.dive;
+ dive *d = diveOrNull(index);
+ Qt::ItemFlags base = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
+
+ // Only dives have editable fields and only the number is editable
+ return d && index.column() == NR ? base | Qt::ItemIsEditable : base;
}
-timestamp_t DiveTripModel::Item::when() const
+bool DiveTripModelBase::setData(const QModelIndex &index, const QVariant &value, int role)
{
- return d_or_t.trip ? trip_date(d_or_t.trip) : d_or_t.dive->when;
+ // We only support setting of data for dives and there, only the number.
+ dive *d = diveOrNull(index);
+ if (!d)
+ return false;
+ if (role != Qt::EditRole)
+ return false;
+ if (index.column() != NR)
+ return false;
+
+ int v = value.toInt();
+ if (v == 0)
+ return false;
+
+ // Only accept numbers that are not already in use by other dives.
+ int i;
+ struct dive *dive;
+ for_each_dive (i, dive) {
+ if (dive->number == v)
+ return false;
+ }
+ d->number = v;
+ mark_divelist_changed(true);
+ return true;
+}
+
+void DiveTripModelBase::divesSelected(dive_trip *trip, const QVector<dive *> &dives)
+{
+ changeDiveSelection(trip, dives, true);
+}
+
+void DiveTripModelBase::divesDeselected(dive_trip *trip, const QVector<dive *> &dives)
+{
+ changeDiveSelection(trip, dives, false);
}
// Find a range of matching elements in a vector.
@@ -547,19 +511,64 @@ void processRangesZip(Vector1 &items1, Vector2 &items2, Predicate cond, Action a
});
}
-void DiveTripModel::setupModelData()
+// Add items from vector "v2" to vector "v1" in batches of contiguous objects.
+// The items are inserted at places according to a sort order determined by "comp".
+// "v1" and "v2" are supposed to be ordered accordingly.
+// TODO: We might use binary search with std::lower_bound(), but not sure if it's worth it.
+// Input parameters:
+// - v1: destination vector
+// - v2: source vector
+// - comp: compare-function, which is fed elements from v2 and v1. returns true for "insert here".
+// - adder: performs the insertion. Perameters: v1, v2, insertion index, from, to range in v2.
+template <typename Vector1, typename Vector2, typename Comparator, typename Inserter>
+void addInBatches(Vector1 &v1, const Vector2 &v2, Comparator comp, Inserter insert)
{
- beginResetModel();
+ int idx = 0; // Index where dives will be inserted
+ int i, j; // Begin and end of range to insert
+ for (i = 0; i < (int)v2.size(); i = j) {
+ for (; idx < (int)v1.size() && !comp(v2[i], v1[idx]); ++idx)
+ ; // Pass
+
+ // We found the index of the first item to add.
+ // Now search how many items we should insert there.
+ if (idx == (int)v1.size()) {
+ // We were at end -> insert the remaining items
+ j = v2.size();
+ } else {
+ for (j = i + 1; j < (int)v2.size() && comp(v2[j], v1[idx]); ++j)
+ ; // Pass
+ }
- items.clear();
+ // Now add the batch
+ insert(v1, v2, idx, i, j);
+
+ // Skip over inserted dives for searching the new insertion position plus one.
+ // If we added at the end, the loop will end anyway.
+ idx += j - i + 1;
+ }
+}
+// 2) TreeModel functions
+
+DiveTripModelTree::DiveTripModelTree(QObject *parent) : DiveTripModelBase(parent)
+{
+ // Stay informed of changes to the divelist
+ connect(&diveListNotifier, &DiveListNotifier::divesAdded, this, &DiveTripModelTree::divesAdded);
+ connect(&diveListNotifier, &DiveListNotifier::divesDeleted, this, &DiveTripModelTree::divesDeleted);
+ connect(&diveListNotifier, &DiveListNotifier::divesChanged, this, &DiveTripModelTree::divesChanged);
+ connect(&diveListNotifier, &DiveListNotifier::divesMovedBetweenTrips, this, &DiveTripModelTree::divesMovedBetweenTrips);
+ connect(&diveListNotifier, &DiveListNotifier::divesTimeChanged, this, &DiveTripModelTree::divesTimeChanged);
+ connect(&diveListNotifier, &DiveListNotifier::divesSelected, this, &DiveTripModelTree::divesSelected);
+ connect(&diveListNotifier, &DiveListNotifier::divesDeselected, this, &DiveTripModelTree::divesDeselected);
+ connect(&diveListNotifier, &DiveListNotifier::currentDiveChanged, this, &DiveTripModelTree::currentDiveChanged);
+
+ // Fill model
for (int i = 0; i < dive_table.nr ; ++i) {
dive *d = get_dive(i);
update_cylinder_related_info(d);
dive_trip_t *trip = d->divetrip;
- // If this dive doesn't have a trip or we are in list-mode, add
- // as top-level item.
- if (!trip || currentLayout == LIST) {
+ // If this dive doesn't have a trip, add as top-level item.
+ if (!trip) {
items.emplace_back(d);
continue;
}
@@ -576,17 +585,85 @@ void DiveTripModel::setupModelData()
it->dives.push_back(d);
}
}
+}
+
+int DiveTripModelTree::rowCount(const QModelIndex &parent) const
+{
+ // No parent means top level - return the number of top-level items
+ if (!parent.isValid())
+ return items.size();
+
+ // If the parent has a parent, this is a dive -> no entries
+ if (parent.parent().isValid())
+ return 0;
+
+ // If this is outside of our top-level list -> no entries
+ int row = parent.row();
+ if (row < 0 || row >= (int)items.size())
+ return 0;
- endResetModel();
+ // Only trips have items
+ const Item &entry = items[parent.row()];
+ return entry.d_or_t.trip ? entry.dives.size() : 0;
+}
+
+static const quintptr noParent = ~(quintptr)0; // This is the "internalId" marker for top-level item
+
+QModelIndex DiveTripModelTree::index(int row, int column, const QModelIndex &parent) const
+{
+ if (!hasIndex(row, column, parent))
+ return QModelIndex();
+
+ // In the "internalId", we store either ~0 for top-level items or the
+ // index of the parent item. A top-level item has an invalid parent.
+ return createIndex(row, column, parent.isValid() ? parent.row() : noParent);
+}
+
+QModelIndex DiveTripModelTree::parent(const QModelIndex &index) const
+{
+ if (!index.isValid())
+ return QModelIndex();
+
+ // In the "internalId", we store either ~0 for top-level items
+ // or the index of the parent item.
+ quintptr id = index.internalId();
+ if (id == noParent)
+ return QModelIndex();
+
+ // Parent must be top-level item
+ return createIndex(id, 0, noParent);
+}
+
+DiveTripModelTree::Item::Item(dive_trip *t, const QVector<dive *> &divesIn) : d_or_t{nullptr, t},
+ dives(divesIn.toStdVector())
+{
+}
+
+DiveTripModelTree::Item::Item(dive_trip *t, dive *d) : d_or_t{nullptr, t},
+ dives({ d })
+{
+}
+
+DiveTripModelTree::Item::Item(dive *d) : d_or_t{d, nullptr}
+{
+}
+
+bool DiveTripModelTree::Item::isDive(const dive *d) const
+{
+ return d_or_t.dive == d;
}
-void DiveTripModel::setLayout(DiveTripModel::Layout layout)
+dive *DiveTripModelTree::Item::getDive() const
{
- currentLayout = layout;
- setupModelData();
+ return d_or_t.dive;
}
-dive_or_trip DiveTripModel::tripOrDive(const QModelIndex &index) const
+timestamp_t DiveTripModelTree::Item::when() const
+{
+ return d_or_t.trip ? trip_date(d_or_t.trip) : d_or_t.dive->when;
+}
+
+dive_or_trip DiveTripModelTree::tripOrDive(const QModelIndex &index) const
{
if (!index.isValid())
return { nullptr, nullptr };
@@ -600,12 +677,12 @@ dive_or_trip DiveTripModel::tripOrDive(const QModelIndex &index) const
return { items[parent.row()].dives[index.row()], nullptr };
}
-dive *DiveTripModel::diveOrNull(const QModelIndex &index) const
+dive *DiveTripModelTree::diveOrNull(const QModelIndex &index) const
{
return tripOrDive(index).dive;
}
-QVariant DiveTripModel::data(const QModelIndex &index, int role) const
+QVariant DiveTripModelTree::data(const QModelIndex &index, int role) const
{
// Set the font for all items alike
if (role == Qt::FontRole)
@@ -620,71 +697,9 @@ QVariant DiveTripModel::data(const QModelIndex &index, int role) const
return QVariant();
}
-bool DiveTripModel::setData(const QModelIndex &index, const QVariant &value, int role)
-{
- // We only support setting of data for dives and there, only the number.
- dive *d = diveOrNull(index);
- if (!d)
- return false;
- if (role != Qt::EditRole)
- return false;
- if (index.column() != NR)
- return false;
-
- int v = value.toInt();
- if (v == 0)
- return false;
-
- // Only accept numbers that are not already in use by other dives.
- int i;
- struct dive *dive;
- for_each_dive (i, dive) {
- if (dive->number == v)
- return false;
- }
- d->number = v;
- mark_divelist_changed(true);
- return true;
-}
-
-int DiveTripModel::findTripIdx(const dive_trip *trip) const
-{
- for (int i = 0; i < (int)items.size(); ++i)
- if (items[i].d_or_t.trip == trip)
- return i;
- return -1;
-}
-
-int DiveTripModel::findDiveIdx(const dive *d) const
-{
- for (int i = 0; i < (int)items.size(); ++i)
- if (items[i].isDive(d))
- return i;
- return -1;
-}
-
-int DiveTripModel::findDiveInTrip(int tripIdx, const dive *d) const
-{
- const Item &item = items[tripIdx];
- for (int i = 0; i < (int)item.dives.size(); ++i)
- if (item.dives[i] == d)
- return i;
- return -1;
-}
-
-int DiveTripModel::findInsertionIndex(const dive_trip *trip) const
-{
- dive_or_trip d_or_t{ nullptr, (dive_trip *)trip };
- for (int i = 0; i < (int)items.size(); ++i) {
- if (dive_or_trip_less_than(d_or_t, items[i].d_or_t))
- return i;
- }
- return items.size();
-}
-
-// After a top-level item changed (notably a trip), it might
-// need to be reordered. Move the item and send a "data-changed" signal.
-void DiveTripModel::topLevelChanged(int idx)
+// After a trip changed, the top level might need to be reordered.
+// Move the item and send a "data-changed" signal.
+void DiveTripModelTree::topLevelChanged(int idx)
{
if (idx < 0 || idx >= (int)items.size())
return;
@@ -713,44 +728,7 @@ void DiveTripModel::topLevelChanged(int idx)
dataChanged(tripIdx, tripIdx);
}
-// Add items from vector "v2" to vector "v1" in batches of contiguous objects.
-// The items are inserted at places according to a sort order determined by "comp".
-// "v1" and "v2" are supposed to be ordered accordingly.
-// TODO: We might use binary search with std::lower_bound(), but not sure if it's worth it.
-// Input parameters:
-// - v1: destination vector
-// - v2: source vector
-// - comp: compare-function, which is fed elements from v2 and v1. returns true for "insert here".
-// - adder: performs the insertion. Perameters: v1, v2, insertion index, from, to range in v2.
-template <typename Vector1, typename Vector2, typename Comparator, typename Inserter>
-void addInBatches(Vector1 &v1, const Vector2 &v2, Comparator comp, Inserter insert)
-{
- int idx = 0; // Index where dives will be inserted
- int i, j; // Begin and end of range to insert
- for (i = 0; i < (int)v2.size(); i = j) {
- for (; idx < (int)v1.size() && !comp(v2[i], v1[idx]); ++idx)
- ; // Pass
-
- // We found the index of the first item to add.
- // Now search how many items we should insert there.
- if (idx == (int)v1.size()) {
- // We were at end -> insert the remaining items
- j = v2.size();
- } else {
- for (j = i + 1; j < (int)v2.size() && comp(v2[j], v1[idx]); ++j)
- ; // Pass
- }
-
- // Now add the batch
- insert(v1, v2, idx, i, j);
-
- // Skip over inserted dives for searching the new insertion position plus one.
- // If we added at the end, the loop will end anyway.
- idx += j - i + 1;
- }
-}
-
-void DiveTripModel::addDivesToTrip(int trip, const QVector<dive *> &dives)
+void DiveTripModelTree::addDivesToTrip(int trip, const QVector<dive *> &dives)
{
// Construct the parent index, ie. the index of the trip.
QModelIndex parent = createIndex(trip, 0, noParent);
@@ -769,22 +747,56 @@ void DiveTripModel::addDivesToTrip(int trip, const QVector<dive *> &dives)
topLevelChanged(trip);
}
+int DiveTripModelTree::findTripIdx(const dive_trip *trip) const
+{
+ for (int i = 0; i < (int)items.size(); ++i)
+ if (items[i].d_or_t.trip == trip)
+ return i;
+ return -1;
+}
+
+int DiveTripModelTree::findDiveIdx(const dive *d) const
+{
+ for (int i = 0; i < (int)items.size(); ++i)
+ if (items[i].isDive(d))
+ return i;
+ return -1;
+}
+
+int DiveTripModelTree::findDiveInTrip(int tripIdx, const dive *d) const
+{
+ const Item &item = items[tripIdx];
+ for (int i = 0; i < (int)item.dives.size(); ++i)
+ if (item.dives[i] == d)
+ return i;
+ return -1;
+}
+
+int DiveTripModelTree::findInsertionIndex(const dive_trip *trip) const
+{
+ dive_or_trip d_or_t{ nullptr, (dive_trip *)trip };
+ for (int i = 0; i < (int)items.size(); ++i) {
+ if (dive_or_trip_less_than(d_or_t, items[i].d_or_t))
+ return i;
+ }
+ return items.size();
+}
+
// This function is used to compare a dive to an arbitrary entry (dive or trip).
// For comparing two dives, use the core function dive_less_than_entry, which
// effectively sorts by timestamp.
// If comparing to a trip, the policy for equal-times is to place the dives
// before the trip in the case of equal timestamps.
-bool DiveTripModel::dive_before_entry(const dive *d, const Item &entry)
+bool DiveTripModelTree::dive_before_entry(const dive *d, const Item &entry)
{
dive_or_trip d_or_t { (dive *)d, nullptr };
return dive_or_trip_less_than(d_or_t, entry.d_or_t);
}
-void DiveTripModel::divesAdded(dive_trip *trip, bool addTrip, const QVector<dive *> &dives)
+void DiveTripModelTree::divesAdded(dive_trip *trip, bool addTrip, const QVector<dive *> &dives)
{
- if (!trip || currentLayout == LIST) {
- // Either this is outside of a trip or we're in list mode.
- // Thus, add dives at the top-level in batches
+ if (!trip) {
+ // This is outside of a trip. Add dives at the top-level in batches.
addInBatches(items, dives,
&dive_before_entry, // comp
[&](std::vector<Item> &items, const QVector<dive *> &dives, int idx, int from, int to) { // inserter
@@ -805,7 +817,7 @@ void DiveTripModel::divesAdded(dive_trip *trip, bool addTrip, const QVector<dive
if (idx < 0) {
// We don't know the trip - this shouldn't happen. We seem to have
// missed some signals!
- qWarning() << "DiveTripModel::divesAdded(): unknown trip";
+ qWarning() << "DiveTripModelTree::divesAdded(): unknown trip";
return;
}
@@ -814,11 +826,10 @@ void DiveTripModel::divesAdded(dive_trip *trip, bool addTrip, const QVector<dive
}
}
-void DiveTripModel::divesDeleted(dive_trip *trip, bool deleteTrip, const QVector<dive *> &dives)
+void DiveTripModelTree::divesDeleted(dive_trip *trip, bool deleteTrip, const QVector<dive *> &dives)
{
- if (!trip || currentLayout == LIST) {
- // Either this is outside of a trip or we're in list mode.
- // Thus, delete top-level dives. We do this range-wise.
+ if (!trip) {
+ // This is outside of a trip. Delete top-level dives in batches.
processRangesZip(items, dives,
[](const Item &e, dive *d) { return e.getDive() == d; }, // Condition
[&](std::vector<Item> &items, const QVector<dive *> &, int from, int to, int) -> int { // Action
@@ -833,7 +844,7 @@ void DiveTripModel::divesDeleted(dive_trip *trip, bool deleteTrip, const QVector
if (idx < 0) {
// We don't know the trip - this shouldn't happen. We seem to have
// missed some signals!
- qWarning() << "DiveTripModel::divesDeleted(): unknown trip";
+ qWarning() << "DiveTripModelTree::divesDeleted(): unknown trip";
return;
}
@@ -863,11 +874,10 @@ void DiveTripModel::divesDeleted(dive_trip *trip, bool deleteTrip, const QVector
}
}
-void DiveTripModel::divesChanged(dive_trip *trip, const QVector<dive *> &dives)
+void DiveTripModelTree::divesChanged(dive_trip *trip, const QVector<dive *> &dives)
{
- if (!trip || currentLayout == LIST) {
- // Either this is outside of a trip or we're in list mode.
- // Thus, these are top-level dives. We do this range-wise.
+ if (!trip) {
+ // This is outside of a trip. Process top-level items range-wise.
// Since we know that the dive list is sorted, we will only ever search for the first element
// in dives as this must be the first that we encounter. Once we find a range, increase the
@@ -885,13 +895,13 @@ void DiveTripModel::divesChanged(dive_trip *trip, const QVector<dive *> &dives)
if (idx < 0) {
// We don't know the trip - this shouldn't happen. We seem to have
// missed some signals!
- qWarning() << "DiveTripModel::divesChanged(): unknown trip";
+ qWarning() << "DiveTripModelTree::divesChanged(): unknown trip";
return;
}
// Change the dives in the trip. We do this range-wise.
processRangesZip(items[idx].dives, dives,
- [](dive *d1, dive *d2) { return d1 == d2; }, // Condition
+ [](const dive *d1, const dive *d2) { return d1 == d2; }, // Condition (std::equal_to only in C++14)
[&](const std::vector<dive *> &, const QVector<dive *> &, int from, int to, int) -> int { // Action
// TODO: We might be smarter about which columns changed!
dataChanged(createIndex(from, 0, idx), createIndex(to - 1, COLUMNS - 1, idx));
@@ -903,7 +913,7 @@ void DiveTripModel::divesChanged(dive_trip *trip, const QVector<dive *> &dives)
}
}
-QVector<dive *> filterSelectedDives(const QVector<dive *> &dives)
+static QVector<dive *> filterSelectedDives(const QVector<dive *> &dives)
{
QVector<dive *> res;
res.reserve(dives.size());
@@ -913,7 +923,7 @@ QVector<dive *> filterSelectedDives(const QVector<dive *> &dives)
return res;
}
-void DiveTripModel::divesMovedBetweenTrips(dive_trip *from, dive_trip *to, bool deleteFrom, bool createTo, const QVector<dive *> &dives)
+void DiveTripModelTree::divesMovedBetweenTrips(dive_trip *from, dive_trip *to, bool deleteFrom, bool createTo, const QVector<dive *> &dives)
{
// Move dives between trips. This is an "interesting" problem, as we might
// move from trip to trip, from trip to top-level or from top-level to trip.
@@ -922,9 +932,8 @@ void DiveTripModel::divesMovedBetweenTrips(dive_trip *from, dive_trip *to, bool
// functions. This *is* cheating. But let's just try this and see how graceful
// this is handled by Qt and if it gives some ugly UI behavior!
- // But first let's just rule out the trivial cases: same-to-same trip move
- // and list view (in which case we don't care).
- if (from == to || currentLayout == LIST)
+ // But first let's just rule out the trivial case: same-to-same trip move.
+ if (from == to)
return;
// Cheating!
@@ -936,13 +945,13 @@ void DiveTripModel::divesMovedBetweenTrips(dive_trip *from, dive_trip *to, bool
divesSelected(to, selectedDives);
}
-void DiveTripModel::divesTimeChanged(dive_trip *trip, timestamp_t delta, const QVector<dive *> &dives)
+void DiveTripModelTree::divesTimeChanged(dive_trip *trip, timestamp_t delta, const QVector<dive *> &dives)
{
// As in the case of divesMovedBetweenTrips(), this is a tricky, but solvable, problem.
// We have to consider the direction (delta < 0 or delta >0) and that dives at their destination
// position have different contiguous batches than at their original position. For now,
// cheat and simply do a remove/add pair. Note that for this to work it is crucial the the
- // order of the dives don't change. This is indeed the case, as all starting-times where
+ // order of the dives don't change. This is indeed the case, as all starting-times were
// moved by the same delta.
// Cheating!
@@ -954,25 +963,15 @@ void DiveTripModel::divesTimeChanged(dive_trip *trip, timestamp_t delta, const Q
divesSelected(trip, selectedDives);
}
-void DiveTripModel::divesSelected(dive_trip *trip, const QVector<dive *> &dives)
-{
- changeDiveSelection(trip, dives, true);
-}
-
-void DiveTripModel::divesDeselected(dive_trip *trip, const QVector<dive *> &dives)
-{
- changeDiveSelection(trip, dives, false);
-}
-
-void DiveTripModel::changeDiveSelection(dive_trip *trip, const QVector<dive *> &dives, bool select)
+void DiveTripModelTree::changeDiveSelection(dive_trip *trip, const QVector<dive *> &dives, bool select)
{
// We got a number of dives that have been selected. Turn this into QModelIndexes and
// emit a signal, so that views can change the selection.
QVector<QModelIndex> indexes;
indexes.reserve(dives.count());
- if (!trip || currentLayout == LIST) {
- // Either this is outside of a trip or we're in list mode.
+ if (!trip) {
+ // This is at the top level.
// Since both lists are sorted, we can do this linearly. Perhaps a binary search
// would be better?
int j = 0; // Index in items array
@@ -989,7 +988,7 @@ void DiveTripModel::changeDiveSelection(dive_trip *trip, const QVector<dive *> &
if (idx < 0) {
// We don't know the trip - this shouldn't happen. We seem to have
// missed some signals!
- qWarning() << "DiveTripModel::divesSelected(): unknown trip";
+ qWarning() << "DiveTripModelTree::changeDiveSelection(): unknown trip";
return;
}
// Locate the indices inside the trip.
@@ -1009,7 +1008,7 @@ void DiveTripModel::changeDiveSelection(dive_trip *trip, const QVector<dive *> &
emit selectionChanged(indexes, select);
}
-void DiveTripModel::currentDiveChanged()
+void DiveTripModelTree::currentDiveChanged()
{
// The current dive has changed. Transform the current dive into an index and pass it on to the view.
if (!current_dive) {
@@ -1018,12 +1017,12 @@ void DiveTripModel::currentDiveChanged()
}
dive_trip *trip = current_dive->divetrip;
- if (!trip || currentLayout == LIST) {
- // Either this is outside of a trip or we're in list mode.
+ if (!trip) {
+ // Outside of a trip - search top-level.
int idx = findDiveIdx(current_dive);
if (idx < 0) {
// We don't know this dive. Something is wrong. Warn and bail.
- qWarning() << "DiveTripModel::currentDiveChanged(): unknown top-level dive";
+ qWarning() << "DiveTripModelTree::currentDiveChanged(): unknown top-level dive";
emit newCurrentDive(QModelIndex());
return;
}
@@ -1032,14 +1031,14 @@ void DiveTripModel::currentDiveChanged()
int idx = findTripIdx(trip);
if (idx < 0) {
// We don't know the trip - this shouldn't happen. Warn and bail.
- qWarning() << "DiveTripModel::currentDiveChanged(): unknown trip";
+ qWarning() << "DiveTripModelTree::currentDiveChanged(): unknown trip";
emit newCurrentDive(QModelIndex());
return;
}
int diveIdx = findDiveInTrip(idx, current_dive);
if (diveIdx < 0) {
// We don't know this dive. Something is wrong. Warn and bail.
- qWarning() << "DiveTripModel::currentDiveChanged(): unknown top-level dive";
+ qWarning() << "DiveTripModelTree::currentDiveChanged(): unknown top-level dive";
emit newCurrentDive(QModelIndex());
return;
}
@@ -1047,18 +1046,175 @@ void DiveTripModel::currentDiveChanged()
}
}
-void DiveTripModel::filterFinished()
+void DiveTripModelTree::filterFinished()
{
// If the filter finished, update all trip items to show the correct number of displayed dives
// in each trip. Without doing this, only trip headers of expanded trips were updated.
- if (currentLayout == LIST)
- return; // No trips in list mode
for (int idx = 0; idx < (int)items.size(); ++idx) {
QModelIndex tripIndex = createIndex(idx, 0, noParent);
dataChanged(tripIndex, tripIndex);
}
}
+bool DiveTripModelTree::lessThan(const QModelIndex &i1, const QModelIndex &i2) const
+{
+ // In tree mode we don't support any sorting!
+ // Simply keep the original position.
+ return i1.row() < i2.row();
+}
+
+// 3) ListModel functions
+
+DiveTripModelList::DiveTripModelList(QObject *parent) : DiveTripModelBase(parent)
+{
+ // Stay informed of changes to the divelist
+ connect(&diveListNotifier, &DiveListNotifier::divesAdded, this, &DiveTripModelList::divesAdded);
+ connect(&diveListNotifier, &DiveListNotifier::divesDeleted, this, &DiveTripModelList::divesDeleted);
+ connect(&diveListNotifier, &DiveListNotifier::divesChanged, this, &DiveTripModelList::divesChanged);
+ // Does nothing in list-view
+ //connect(&diveListNotifier, &DiveListNotifier::divesMovedBetweenTrips, this, &DiveTripModelList::divesMovedBetweenTrips);
+ connect(&diveListNotifier, &DiveListNotifier::divesTimeChanged, this, &DiveTripModelList::divesTimeChanged);
+ connect(&diveListNotifier, &DiveListNotifier::divesSelected, this, &DiveTripModelList::divesSelected);
+ connect(&diveListNotifier, &DiveListNotifier::divesDeselected, this, &DiveTripModelList::divesDeselected);
+ connect(&diveListNotifier, &DiveListNotifier::currentDiveChanged, this, &DiveTripModelList::currentDiveChanged);
+
+ // Fill model
+ items.reserve(dive_table.nr);
+ for (int i = 0; i < dive_table.nr ; ++i)
+ items.push_back(get_dive(i));
+}
+
+int DiveTripModelList::rowCount(const QModelIndex &parent) const
+{
+ // In list-mode there is only one level, i.e only top-level
+ // (=invalid parent) has items.
+ return parent.isValid() ? 0 : items.size();
+}
+
+QModelIndex DiveTripModelList::index(int row, int column, const QModelIndex &parent) const
+{
+ if (!hasIndex(row, column, parent))
+ return QModelIndex();
+
+ return createIndex(row, column);
+}
+
+QModelIndex DiveTripModelList::parent(const QModelIndex &index) const
+{
+ // In list-mode there is only one level, i.e. no parent
+ return QModelIndex();
+}
+
+dive *DiveTripModelList::diveOrNull(const QModelIndex &index) const
+{
+ int row = index.row();
+ if (row < 0 || row > (int)items.size())
+ return nullptr;
+ return items[row];
+}
+
+QVariant DiveTripModelList::data(const QModelIndex &index, int role) const
+{
+ // Set the font for all items alike
+ if (role == Qt::FontRole)
+ return defaultModelFont();
+
+ dive *d = diveOrNull(index);
+ return d ? diveData(d, index.column(), role) : QVariant();
+}
+
+void DiveTripModelList::divesAdded(dive_trip *, bool, const QVector<dive *> &dives)
+{
+ addInBatches(items, dives,
+ &dive_less_than, // comp
+ [&](std::vector<dive *> &items, const QVector<dive *> &dives, int idx, int from, int to) { // inserter
+ beginInsertRows(QModelIndex(), idx, idx + to - from - 1);
+ items.insert(items.begin() + idx, dives.begin() + from, dives.begin() + to);
+ endInsertRows();
+ });
+}
+
+void DiveTripModelList::divesDeleted(dive_trip *trip, bool deleteTrip, const QVector<dive *> &dives)
+{
+ processRangesZip(items, dives,
+ [](const dive *d1, const dive *d2) { return d1 == d2; }, // Condition (std::equal_to only in C++14)
+ [&](std::vector<dive *> &items, const QVector<dive *> &, int from, int to, int) -> int { // Action
+ beginRemoveRows(QModelIndex(), from, to - 1);
+ items.erase(items.begin() + from, items.begin() + to);
+ endRemoveRows();
+ return from - to; // Delta: negate the number of items deleted
+ });
+}
+
+void DiveTripModelList::divesChanged(dive_trip *trip, const QVector<dive *> &dives)
+{
+ // Since we know that the dive list is sorted, we will only ever search for the first element
+ // in dives as this must be the first that we encounter. Once we find a range, increase the
+ // index accordingly.
+ processRangesZip(items, dives,
+ [](const dive *d1, const dive *d2) { return d1 == d2; }, // Condition (std::equal_to only in C++14)
+ [&](const std::vector<dive *> &, const QVector<dive *> &, int from, int to, int) -> int { // Action
+ // TODO: We might be smarter about which columns changed!
+ dataChanged(createIndex(from, 0, noParent), createIndex(to - 1, COLUMNS - 1, noParent));
+ return 0; // No items added or deleted
+ });
+}
+
+void DiveTripModelList::divesTimeChanged(dive_trip *trip, timestamp_t delta, const QVector<dive *> &dives)
+{
+ // See comment for DiveTripModelTree::divesTimeChanged above.
+ QVector<dive *> selectedDives = filterSelectedDives(dives);
+ divesDeleted(trip, false, dives);
+ divesAdded(trip, false, dives);
+ divesSelected(trip, selectedDives);
+}
+
+void DiveTripModelList::changeDiveSelection(dive_trip *trip, const QVector<dive *> &dives, bool select)
+{
+ // We got a number of dives that have been selected. Turn this into QModelIndexes and
+ // emit a signal, so that views can change the selection.
+ QVector<QModelIndex> indexes;
+ indexes.reserve(dives.count());
+
+ // Since both lists are sorted, we can do this linearly. Perhaps a binary search
+ // would be better?
+ int j = 0; // Index in items array
+ for (int i = 0; i < dives.size(); ++i) {
+ while (j < (int)items.size() && items[j] != dives[i])
+ ++j;
+ if (j >= (int)items.size())
+ break;
+ indexes.append(createIndex(j, 0, noParent));
+ }
+
+ emit selectionChanged(indexes, select);
+}
+
+void DiveTripModelList::currentDiveChanged()
+{
+ // The current dive has changed. Transform the current dive into an index and pass it on to the view.
+ if (!current_dive) {
+ emit newCurrentDive(QModelIndex()); // No current dive -> tell view to clear current index with an invalid index
+ return;
+ }
+
+ // Either this is outside of a trip or we're in list mode.
+ auto it = std::find(items.begin(), items.end(), current_dive);
+ if (it == items.end()) {
+ // We don't know this dive. Something is wrong. Warn and bail.
+ qWarning() << "DiveTripModelList::currentDiveChanged(): unknown top-level dive";
+ emit newCurrentDive(QModelIndex());
+ return;
+ }
+ emit newCurrentDive(createIndex(it - items.begin(), 0));
+}
+
+void DiveTripModelList::filterFinished()
+{
+ // In list mode, we don't have to change anything after filter finished.
+}
+
+
// Simple sorting helper for sorting against a criterium and if
// that is undefined against a different criterium.
// Return true if diff1 < 0, false if diff1 > 0.
@@ -1077,22 +1233,15 @@ static int strCmp(const char *s1, const char *s2)
return QString::localeAwareCompare(QString(s1), QString(s2)); // TODO: avoid copy
}
-bool DiveTripModel::lessThan(const QModelIndex &i1, const QModelIndex &i2) const
+bool DiveTripModelList::lessThan(const QModelIndex &i1, const QModelIndex &i2) const
{
- if (currentLayout != LIST) {
- // In tree mode we don't support any sorting!
- // Simply keep the original position.
- return i1.row() < i2.row();
- }
-
// We assume that i1.column() == i2.column().
- // We are in list mode, so we know that we only have dives.
int row1 = i1.row();
int row2 = i2.row();
if (row1 < 0 || row1 >= (int)items.size() || row2 < 0 || row2 >= (int)items.size())
return false;
- const dive *d1 = items[i1.row()].d_or_t.dive;
- const dive *d2 = items[i2.row()].d_or_t.dive;
+ const dive *d1 = items[row1];
+ const dive *d2 = items[row2];
// This is used as a second sort criterion: For equal values, sorting is chronologically *descending*.
int row_diff = row2 - row1;
switch (i1.column()) {
diff --git a/qt-models/divetripmodel.h b/qt-models/divetripmodel.h
index aab154069..67a4f090d 100644
--- a/qt-models/divetripmodel.h
+++ b/qt-models/divetripmodel.h
@@ -5,7 +5,23 @@
#include "core/dive.h"
#include <QAbstractItemModel>
-class DiveTripModel : public QAbstractItemModel {
+// There are two different representations of the dive list:
+// 1) Tree view: two-level model where dives are grouped by trips
+// 2) List view: one-level model where dives are sorted by one out
+// of many keys (e.g. date, depth, etc.).
+//
+// These two representations are realized by two classe, viz.
+// DiveTripModelTree and DiveTripModelList. Both classes derive
+// from DiveTripModelBase, which implements common features (e.g.
+// definition of the column types, access of data from the core
+// structures) and a common interface.
+//
+// The currently active model is set via DiveTripModelBase::resetModel().
+// This will create a new model. The model can be accessed with
+// DiveTripModelBase::instance(). Any pointer obtained by instance()
+// is invalid after a call to resetModel()! Yes, this is surprising
+// behavior, so care must be taken.
+class DiveTripModelBase : public QAbstractItemModel {
Q_OBJECT
public:
enum Column {
@@ -40,25 +56,28 @@ public:
enum Layout {
TREE,
LIST,
- CURRENT
};
- static DiveTripModel *instance();
+ // Functions implemented by base class
+ static DiveTripModelBase *instance();
+
+ // Reset the model using the given layout. After this call instance() will return
+ // a newly allocated object and the old model will have been destroyed! Thus, the
+ // caller is repsonsible of removing all references to any previous model obtained
+ // by insance().
+ static void resetModel(Layout layout);
+
Qt::ItemFlags flags(const QModelIndex &index) const;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
- DiveTripModel(QObject *parent = 0);
- void setLayout(Layout layout);
- QVariant data(const QModelIndex &index, int role) const;
+ DiveTripModelBase(QObject *parent = 0);
int columnCount(const QModelIndex&) const;
- int rowCount(const QModelIndex &parent) const;
- QModelIndex index(int row, int column, const QModelIndex &parent) const;
- QModelIndex parent(const QModelIndex &index) const;
- void filterFinished();
+ virtual void filterFinished() = 0;
// Used for sorting. This is a bit of a layering violation, as sorting should be performed
// by the higher-up QSortFilterProxyModel, but it makes things so much easier!
- bool lessThan(const QModelIndex &i1, const QModelIndex &i2) const;
+ virtual bool lessThan(const QModelIndex &i1, const QModelIndex &i2) const = 0;
+
signals:
// The propagation of selection changes is complex.
// The control flow of dive-selection goes:
@@ -69,17 +88,44 @@ signals:
// perform the appropriate actions.
void selectionChanged(const QVector<QModelIndex> &indexes, bool select);
void newCurrentDive(QModelIndex index);
-private slots:
+protected slots:
+ void divesSelected(dive_trip *trip, const QVector<dive *> &dives);
+ void divesDeselected(dive_trip *trip, const QVector<dive *> &dives);
+protected:
+ // Access trip and dive data
+ static QVariant diveData(const struct dive *d, int column, int role);
+ static QVariant tripData(const dive_trip *trip, int column, int role);
+
+ // Select or deselect dives
+ virtual void changeDiveSelection(dive_trip *trip, const QVector<dive *> &dives, bool select) = 0;
+
+ virtual dive *diveOrNull(const QModelIndex &index) const = 0; // Returns a dive if this index represents a dive, null otherwise
+};
+
+class DiveTripModelTree : public DiveTripModelBase
+{
+ Q_OBJECT
+public slots:
void divesAdded(dive_trip *trip, bool addTrip, const QVector<dive *> &dives);
void divesDeleted(dive_trip *trip, bool deleteTrip, const QVector<dive *> &dives);
void divesChanged(dive_trip *trip, const QVector<dive *> &dives);
void divesTimeChanged(dive_trip *trip, timestamp_t delta, const QVector<dive *> &dives);
void divesMovedBetweenTrips(dive_trip *from, dive_trip *to, bool deleteFrom, bool createTo, const QVector<dive *> &dives);
- void divesSelected(dive_trip *trip, const QVector<dive *> &dives);
- void divesDeselected(dive_trip *trip, const QVector<dive *> &dives);
void currentDiveChanged();
+
+public:
+ DiveTripModelTree(QObject *parent = nullptr);
private:
- // The model has up to two levels. At the top level, we have either trips or dives
+ int rowCount(const QModelIndex &parent) const override;
+ QModelIndex index(int row, int column, const QModelIndex &parent) const override;
+ QModelIndex parent(const QModelIndex &index) const override;
+ QVariant data(const QModelIndex &index, int role) const override;
+ void filterFinished() override;
+ bool lessThan(const QModelIndex &i1, const QModelIndex &i2) const override;
+ void changeDiveSelection(dive_trip *trip, const QVector<dive *> &dives, bool select) override;
+ dive *diveOrNull(const QModelIndex &index) const override;
+
+ // The tree model has two levels. At the top level, we have either trips or dives
// that do not belong to trips. Such a top-level item is represented by the "Item"
// struct, which is based on the dive_or_trip structure.
// If it is a trip, additionally, the dives are collected in a vector.
@@ -97,8 +143,14 @@ private:
dive *getDive() const; // Helper function: returns top-level-dive or null
timestamp_t when() const; // Helper function: start time of dive *or* trip
};
- // Comparison function between dive and arbitrary entry
- static bool dive_before_entry(const dive *d, const Item &entry);
+ std::vector<Item> items; // Use std::vector for convenience of emplace_back()
+
+ dive_or_trip tripOrDive(const QModelIndex &index) const;
+ // Returns either a pointer to a trip or a dive, or twice null of index is invalid
+ // null, something is really wrong
+ // Addition and deletion of dives
+ void addDivesToTrip(int idx, const QVector<dive *> &dives);
+ void topLevelChanged(int idx);
// Access trips and dives
int findTripIdx(const dive_trip *trip) const;
@@ -106,24 +158,35 @@ private:
int findDiveInTrip(int tripIdx, const dive *d) const; // Find dive inside trip. Second parameter is index of trip
int findInsertionIndex(const dive_trip *trip) const; // Where to insert trip
- // Access trip and dive data
- static QVariant diveData(const struct dive *d, int column, int role);
- static QVariant tripData(const dive_trip *trip, int column, int role);
+ // Comparison function between dive and arbitrary entry
+ static bool dive_before_entry(const dive *d, const Item &entry);
+};
- // Select or deselect dives
- void changeDiveSelection(dive_trip *trip, const QVector<dive *> &dives, bool select);
+class DiveTripModelList : public DiveTripModelBase
+{
+ Q_OBJECT
+public slots:
+ void divesAdded(dive_trip *trip, bool addTrip, const QVector<dive *> &dives);
+ void divesDeleted(dive_trip *trip, bool deleteTrip, const QVector<dive *> &dives);
+ void divesChanged(dive_trip *trip, const QVector<dive *> &dives);
+ void divesTimeChanged(dive_trip *trip, timestamp_t delta, const QVector<dive *> &dives);
+ // Does nothing in list view.
+ //void divesMovedBetweenTrips(dive_trip *from, dive_trip *to, bool deleteFrom, bool createTo, const QVector<dive *> &dives);
+ void currentDiveChanged();
- // Addition and deletion of dives
- void addDivesToTrip(int idx, const QVector<dive *> &dives);
- void topLevelChanged(int idx);
+public:
+ DiveTripModelList(QObject *parent = nullptr);
+private:
+ int rowCount(const QModelIndex &parent) const override;
+ QModelIndex index(int row, int column, const QModelIndex &parent) const override;
+ QModelIndex parent(const QModelIndex &index) const override;
+ QVariant data(const QModelIndex &index, int role) const override;
+ void filterFinished() override;
+ bool lessThan(const QModelIndex &i1, const QModelIndex &i2) const override;
+ void changeDiveSelection(dive_trip *trip, const QVector<dive *> &dives, bool select) override;
+ dive *diveOrNull(const QModelIndex &index) const override;
- dive *diveOrNull(const QModelIndex &index) const; // Returns a dive if this index represents a dive, null otherwise
- dive_or_trip tripOrDive(const QModelIndex &index) const;
- // Returns either a pointer to a trip or a dive, or twice null of index is invalid
- // null, something is really wrong
- void setupModelData();
- std::vector<Item> items; // Use std::vector for convenience of emplace_back()
- Layout currentLayout;
+ std::vector<dive *> items; // TODO: access core data directly
};
#endif
diff --git a/qt-models/filtermodels.cpp b/qt-models/filtermodels.cpp
index 785d36123..4e4134033 100644
--- a/qt-models/filtermodels.cpp
+++ b/qt-models/filtermodels.cpp
@@ -88,13 +88,14 @@ MultiFilterSortModel::MultiFilterSortModel(QObject *parent) : QSortFilterProxyMo
{
setFilterKeyColumn(-1); // filter all columns
setFilterCaseSensitivity(Qt::CaseInsensitive);
- setSourceModel(DiveTripModel::instance());
}
-void MultiFilterSortModel::setLayout(DiveTripModel::Layout layout)
+void MultiFilterSortModel::resetModel(DiveTripModelBase::Layout layout)
{
- DiveTripModel *tripModel = DiveTripModel::instance();
- tripModel->setLayout(layout); // Note: setLayout() resets the whole model
+ DiveTripModelBase::resetModel(layout);
+ // DiveTripModelBase::resetModel() generates a new instance.
+ // Thus, the source model must be reset.
+ setSourceModel(DiveTripModelBase::instance());
}
bool MultiFilterSortModel::showDive(const struct dive *d) const
@@ -143,14 +144,14 @@ bool MultiFilterSortModel::showDive(const struct dive *d) const
bool MultiFilterSortModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
QModelIndex index0 = sourceModel()->index(source_row, 0, source_parent);
- struct dive *d = sourceModel()->data(index0, DiveTripModel::DIVE_ROLE).value<struct dive *>();
+ struct dive *d = sourceModel()->data(index0, DiveTripModelBase::DIVE_ROLE).value<struct dive *>();
// For dives, simply check the hidden_by_filter flag
if (d)
return !d->hidden_by_filter;
// Since this is not a dive, it must be a trip
- dive_trip *trip = sourceModel()->data(index0, DiveTripModel::TRIP_ROLE).value<dive_trip *>();
+ dive_trip *trip = sourceModel()->data(index0, DiveTripModelBase::TRIP_ROLE).value<dive_trip *>();
if (!trip)
return false; // Oops. Neither dive nor trip, something is seriously wrong.
@@ -189,7 +190,7 @@ void MultiFilterSortModel::myInvalidate()
invalidateFilter();
// Tell the dive trip model to update the displayed-counts
- DiveTripModel::instance()->filterFinished();
+ DiveTripModelBase::instance()->filterFinished();
emit filterFinished();
#if !defined(SUBSURFACE_MOBILE)
@@ -218,7 +219,7 @@ void MultiFilterSortModel::stopFilterDiveSite()
bool MultiFilterSortModel::lessThan(const QModelIndex &i1, const QModelIndex &i2) const
{
// Hand sorting down to the source model.
- return DiveTripModel::instance()->lessThan(i1, i2);
+ return DiveTripModelBase::instance()->lessThan(i1, i2);
}
void MultiFilterSortModel::filterDataChanged(const FilterData& data)
diff --git a/qt-models/filtermodels.h b/qt-models/filtermodels.h
index 442bdec5e..a8a601ecc 100644
--- a/qt-models/filtermodels.h
+++ b/qt-models/filtermodels.h
@@ -2,7 +2,7 @@
#ifndef FILTERMODELS_H
#define FILTERMODELS_H
-#include "divetripmodel.h" // For DiveTripModel::Layout. TODO: remove in due course
+#include "divetripmodel.h"
#include <QStringListModel>
#include <QSortFilterProxyModel>
@@ -13,7 +13,6 @@
struct dive;
struct dive_trip;
-class DiveTripModel;
struct FilterData {
bool validFilter = false;
@@ -49,7 +48,7 @@ slots:
void startFilterDiveSite(struct dive_site *ds);
void stopFilterDiveSite();
void filterChanged(const QModelIndex &from, const QModelIndex &to, const QVector<int> &roles);
- void setLayout(DiveTripModel::Layout layout);
+ void resetModel(DiveTripModelBase::Layout layout);
void filterDataChanged(const FilterData& data);
signals: