diff --git a/desktop-widgets/tab-widgets/TabDiveSite.cpp b/desktop-widgets/tab-widgets/TabDiveSite.cpp index 81736bc77..5e2831c93 100644 --- a/desktop-widgets/tab-widgets/TabDiveSite.cpp +++ b/desktop-widgets/tab-widgets/TabDiveSite.cpp @@ -8,7 +8,10 @@ TabDiveSite::TabDiveSite(QWidget *parent) : TabBase(parent) { ui.setupUi(this); ui.diveSites->setTitle(tr("Dive sites")); - ui.diveSites->setModel(LocationInformationModel::instance()); + ui.diveSites->setModel(&model); + // Default: sort by name + ui.diveSites->view()->sortByColumn(LocationInformationModel::NAME, Qt::AscendingOrder); + ui.diveSites->view()->setSortingEnabled(true); // Show only the first few columns for (int i = LocationInformationModel::COORDS; i < LocationInformationModel::COLUMNS; ++i) diff --git a/desktop-widgets/tab-widgets/TabDiveSite.h b/desktop-widgets/tab-widgets/TabDiveSite.h index 60b3abd76..f0bf2d5d5 100644 --- a/desktop-widgets/tab-widgets/TabDiveSite.h +++ b/desktop-widgets/tab-widgets/TabDiveSite.h @@ -4,6 +4,7 @@ #include "TabBase.h" #include "ui_TabDiveSite.h" +#include "qt-models/divelocationmodel.h" class TabDiveSite : public TabBase { Q_OBJECT @@ -13,6 +14,7 @@ public: void clear() override; private: Ui::TabDiveSite ui; + DiveSiteSortedModel model; }; #endif diff --git a/mobile-widgets/qmlmanager.cpp b/mobile-widgets/qmlmanager.cpp index d312fac00..9b52ee211 100644 --- a/mobile-widgets/qmlmanager.cpp +++ b/mobile-widgets/qmlmanager.cpp @@ -223,6 +223,9 @@ QMLManager::QMLManager() : m_locationServiceEnabled(false), set_git_update_cb(&gitProgressCB); LOG_STP("qmlmgr git update"); + // present dive site lists sorted by name + locationModel.sort(LocationInformationModel::NAME); + // make sure we know if the current cloud repo has been successfully synced syncLoadFromCloud(); LOG_STP("qmlmgr sync load cloud"); @@ -334,7 +337,8 @@ void QMLManager::updateAllGlobalLists() buddyModel.updateModel(); emit buddyListChanged(); suitModel.updateModel(); emit suitListChanged(); divemasterModel.updateModel(); emit divemasterListChanged(); - locationModel.update(); emit locationListChanged(); + // TODO: Probably not needed anymore, as the dive site list is generated on the fly! + LocationInformationModel::instance()->update(); emit locationListChanged(); } void QMLManager::mergeLocalRepo() diff --git a/mobile-widgets/qmlmanager.h b/mobile-widgets/qmlmanager.h index 7d10f78b2..ff09661c6 100644 --- a/mobile-widgets/qmlmanager.h +++ b/mobile-widgets/qmlmanager.h @@ -209,7 +209,7 @@ private: BuddyCompletionModel buddyModel; SuitCompletionModel suitModel; DiveMasterCompletionModel divemasterModel; - LocationInformationModel locationModel; + DiveSiteSortedModel locationModel; QString m_startPageText; QString m_logText; QString m_lastError; diff --git a/qt-models/divelocationmodel.cpp b/qt-models/divelocationmodel.cpp index 0a0eacaaf..383de43ca 100644 --- a/qt-models/divelocationmodel.cpp +++ b/qt-models/divelocationmodel.cpp @@ -11,11 +11,6 @@ #include #include -static bool dive_site_less_than(dive_site *a, dive_site *b) -{ - return QString(a->name) < QString(b->name); -} - LocationInformationModel *LocationInformationModel::instance() { static LocationInformationModel *self = new LocationInformationModel(); @@ -133,18 +128,9 @@ QVariant LocationInformationModel::data(const QModelIndex &index, int role) cons void LocationInformationModel::update() { beginResetModel(); - std::sort(dive_site_table.dive_sites, dive_site_table.dive_sites + dive_site_table.nr, dive_site_less_than); - locationNames.clear(); - for (int i = 0; i < dive_site_table.nr; i++) - locationNames << QString(dive_site_table.dive_sites[i]->name); endResetModel(); } -QStringList LocationInformationModel::allSiteNames() const -{ - return locationNames; -} - bool LocationInformationModel::removeRows(int row, int, const QModelIndex&) { if(row >= rowCount()) @@ -183,6 +169,56 @@ void LocationInformationModel::diveSiteDeleted(struct dive_site *, int idx) endRemoveRows(); } +bool DiveSiteSortedModel::filterAcceptsRow(int sourceRow, const QModelIndex &source_parent) const +{ + // TODO: filtering + return true; +} + +bool DiveSiteSortedModel::lessThan(const QModelIndex &i1, const QModelIndex &i2) const +{ + // The source indices correspond to indices in the global dive site table. + // Let's access them directly without going via the source model. + // Kind of dirty, but less effort. + struct dive_site *ds1 = get_dive_site(i1.row(), &dive_site_table); + struct dive_site *ds2 = get_dive_site(i2.row(), &dive_site_table); + if (!ds1 || !ds2) // Invalid dive sites compare as different + return false; + switch (i1.column()) { + case LocationInformationModel::NAME: + default: + return QString::localeAwareCompare(QString(ds1->name), QString(ds2->name)) < 0; // TODO: avoid copy + case LocationInformationModel::DESCRIPTION: { + int cmp = QString::localeAwareCompare(QString(ds1->description), QString(ds2->description)); // TODO: avoid copy + return cmp != 0 ? cmp < 0 : + QString::localeAwareCompare(QString(ds1->name), QString(ds2->name)) < 0; // TODO: avoid copy + } + case LocationInformationModel::NUM_DIVES: { + int cmp = ds1->dives.nr - ds2->dives.nr; + // Since by default nr dives is descending, invert sort direction of names, such that + // the names are listed as ascending. + return cmp != 0 ? cmp < 0 : + QString::localeAwareCompare(QString(ds1->name), QString(ds2->name)) < 0; // TODO: avoid copy + } + } +} + +DiveSiteSortedModel::DiveSiteSortedModel() +{ + setSourceModel(LocationInformationModel::instance()); +} + +QStringList DiveSiteSortedModel::allSiteNames() const +{ + QStringList locationNames; + int num = rowCount(); + for (int i = 0; i < num; i++) { + int idx = mapToSource(index(i, 0)).row(); + locationNames << QString(dive_site_table.dive_sites[idx]->name); + } + return locationNames; +} + GeoReferencingOptionsModel *GeoReferencingOptionsModel::instance() { static GeoReferencingOptionsModel *self = new GeoReferencingOptionsModel(); diff --git a/qt-models/divelocationmodel.h b/qt-models/divelocationmodel.h index 65fabca96..f2bcc7cf7 100644 --- a/qt-models/divelocationmodel.h +++ b/qt-models/divelocationmodel.h @@ -32,12 +32,19 @@ public: public slots: void update(); - QStringList allSiteNames() const; void diveSiteDiveCountChanged(struct dive_site *ds); void diveSiteAdded(struct dive_site *ds, int idx); void diveSiteDeleted(struct dive_site *ds, int idx); +}; + +class DiveSiteSortedModel : public QSortFilterProxyModel { + Q_OBJECT private: - QStringList locationNames; + bool filterAcceptsRow(int sourceRow, const QModelIndex &source_parent) const override; + bool lessThan(const QModelIndex &i1, const QModelIndex &i2) const override; +public: + DiveSiteSortedModel(); + QStringList allSiteNames() const; }; // To access only divesites at the given GPS coordinates with the exception of a given dive site