Commit 291fd206 authored by Volker Krause's avatar Volker Krause
Browse files

Add a group by country mode to BackendModel

This removes the restriction of a backend only being associated with a
single country. We work around that with aggregate country codes (EU, UN)
in a few places, but that isn't really ideal. Instead we can now show
backend entries for each country they are associated with.

While already more correct, the result isn't perfect yet regarding the
ordering, and filtering out fallback backends for countries where we have
better local sources is also still missing.

The previous flat view remains the default to not break existing users,
the new mode is however fully compatible with existing view that use the
country as section header already.
parent 9880f41e
Pipeline #58151 passed with stage
in 55 seconds
......@@ -24,9 +24,12 @@ class BackendModelPrivate
{
public:
void repopulateModel(BackendModel *q);
void repopulateFlat();
void repopulateGrouped();
Manager *mgr = nullptr;
std::vector<BackendInfo> rows;
BackendModel::Mode mode = BackendModel::Flat;
};
}
......@@ -38,13 +41,50 @@ void BackendModelPrivate::repopulateModel(BackendModel *q)
q->beginResetModel();
rows.clear();
switch (mode) {
case BackendModel::Flat:
repopulateFlat();
break;
case BackendModel::GroupByCountry:
repopulateGrouped();
break;
}
std::sort(rows.begin(), rows.end(), [](const auto &lhs, const auto &rhs) {
if (lhs.country == rhs.country) {
return lhs.backend.name() < rhs.backend.name();
}
return lhs.country < rhs.country;
});
q->endResetModel();
}
void BackendModelPrivate::repopulateFlat()
{
rows.reserve(mgr->backends().size());
for (const auto &b : mgr->backends()) {
rows.push_back({ b, b.primaryCountryCode() });
}
q->endResetModel();
}
void BackendModelPrivate::repopulateGrouped()
{
for (const auto &b : mgr->backends()) {
for (const auto type : { CoverageArea::Realtime, CoverageArea::Regular, CoverageArea::Any }) {
const auto c = b.coverageArea(type);
if (c.isEmpty()) {
continue;
}
for (const auto &country : c.regions()) {
rows.push_back({ b, country.left(2) });
}
break;
}
}
}
BackendModel::BackendModel(QObject *parent)
: QAbstractListModel(parent)
, d(new BackendModelPrivate)
......@@ -72,6 +112,22 @@ void BackendModel::setManager(Manager *mgr)
emit managerChanged();
}
BackendModel::Mode BackendModel::mode() const
{
return d->mode;
}
void BackendModel::setMode(BackendModel::Mode mode)
{
if (d->mode == mode) {
return;
}
d->mode = mode;
emit modeChanged();
d->repopulateModel(this);
}
int BackendModel::rowCount(const QModelIndex &parent) const
{
if (parent.isValid()) {
......
......@@ -25,11 +25,22 @@ class KPUBLICTRANSPORT_EXPORT BackendModel : public QAbstractListModel
/** Sets the KPublicTransport::Manager instance. Necessary for this to work at all. */
Q_PROPERTY(KPublicTransport::Manager* manager READ manager WRITE setManager NOTIFY managerChanged)
/** Configures the grouping mode for the content of this model. */
Q_PROPERTY(Mode mode READ mode WRITE setMode NOTIFY modeChanged)
public:
explicit BackendModel(QObject *parent = nullptr);
~BackendModel();
/** Content grouping modes. */
enum Mode {
Flat, ///< Each backend appears exactly once, grouping by country is possible (the data is order by country), but multi-country operators might not be properly associated.
GroupByCountry, ///< A backend might occur multiple times, for each country it is associated with.
};
Q_ENUM(Mode)
Mode mode() const;
void setMode(Mode mode);
enum Roles {
NameRole = Qt::DisplayRole,
DescriptionRole = Qt::UserRole,
......@@ -51,6 +62,7 @@ public:
Q_SIGNALS:
void managerChanged();
void modeChanged();
private:
friend class BackendModelPrivate;
......
......@@ -86,6 +86,7 @@
"ES",
"FI",
"FR",
"GB",
"GH",
"HU",
"IE",
......@@ -99,7 +100,6 @@
"PT",
"RU",
"SE",
"UK",
"US"
]
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment