7#include "backendmodel.h"
9#include <KPublicTransport/Backend>
10#include <KPublicTransport/Manager>
25class BackendModelPrivate
29 void repopulateFlat();
30 void repopulateGrouped();
34 std::vector<BackendInfo> rows;
39void BackendModelPrivate::repopulateModel(
BackendModel *q)
60void BackendModelPrivate::repopulateFlat()
62 rows.reserve(mgr->
backends().size());
63 for (
const auto &b : mgr->
backends()) {
64 if (b.identifier().size() > 3 && b.identifier().at(2) ==
QLatin1Char(
'_')) {
65 rows.push_back({ b, b.identifier().left(2).toUpper(),
true, CoverageArea::Any });
70void BackendModelPrivate::repopulateGrouped()
72 for (
const auto &b : mgr->
backends()) {
73 for (
const auto type : { CoverageArea::Realtime, CoverageArea::Regular, CoverageArea::Any }) {
74 const auto c = b.coverageArea(type);
79 for (
const auto ®ion: c.regions()) {
80 const auto country = region.left(2);
81 if (!rows.empty() && rows.back().backend.identifier() == b.identifier() && rows.back().country == country) {
84 rows.push_back({ b, country, region.size() == 2, type });
90void BackendModelPrivate::sortModel()
93 const auto orderByCountry = [](
const auto &lhs,
const auto &rhs) {
94 return lhs.country < rhs.country;
96 std::sort(rows.begin(), rows.end(), orderByCountry);
99 for (
auto next = rows.begin(); next != rows.end();) {
100 const auto [begin, end] = std::equal_range(next, rows.end(), *next, orderByCountry);
105 for (
auto it = begin; it != end; ++it) {
106 if ((*it).isNationWide) {
107 bestCoverageType = std::min(bestCoverageType, (*it).coverageType);
112 std::sort(begin, end, [bestCoverageType](
const auto &lhs,
const auto &rhs) {
113 if (lhs.isNationWide && rhs.isNationWide) {
114 if ((lhs.coverageType > bestCoverageType && rhs.coverageType > bestCoverageType)
115 || (lhs.coverageType <= bestCoverageType && rhs.coverageType <= bestCoverageType)) {
116 return lhs.backend.name() < rhs.backend.name();
118 return lhs.coverageType < rhs.coverageType;
120 if (lhs.isNationWide && !rhs.isNationWide) {
121 return lhs.coverageType <= bestCoverageType;
123 if (!lhs.isNationWide && rhs.isNationWide) {
124 return rhs.coverageType > bestCoverageType;
126 assert(!lhs.isNationWide && !rhs.isNationWide);
127 return lhs.backend.name() < rhs.backend.name();
135 for (
auto it = begin; it != end; ++it) {
136 if (!(*it).isNationWide || (*it).coverageType <= bestCoverageType) {
140 for (
auto type : { CoverageArea::Realtime, CoverageArea::Regular }) {
141 if (type >= (*it).coverageType) {
144 if (!(*it).backend.coverageArea(type).isEmpty()) {
145 (*it).country.clear();
154 rows.erase(std::remove_if(rows.begin(), rows.end(), [](
const auto &r) { return r.country.isEmpty(); }), rows.end());
158BackendModel::BackendModel(
QObject *parent)
160 , d(new BackendModelPrivate)
164BackendModel::~BackendModel() =
default;
171void BackendModel::setManager(
Manager *mgr)
181 connect(mgr, &Manager::configurationChanged,
this, [
this]() {
184 connect(mgr, &Manager::backendsChanged,
this, [
this]() {
185 d->repopulateModel(
this);
187 d->repopulateModel(
this);
198 if (d->mode ==
mode) {
204 d->repopulateModel(
this);
207int BackendModel::rowCount(
const QModelIndex &parent)
const
212 return d->rows.size();
221 const auto &row = d->rows[
index.
row()];
224 return row.backend.name();
225 case DescriptionRole:
226 return row.backend.description();
228 return row.backend.identifier();
230 return row.backend.isSecure();
231 case ItemEnabledRole:
232 return row.backend.isSecure() || d->mgr->allowInsecureBackends();
233 case BackendEnabledRole:
234 if (!row.backend.isSecure() && !d->mgr->allowInsecureBackends()) {
237 return d->mgr->isBackendEnabled(row.backend.identifier());
239 if (!row.backend.isSecure() && !d->mgr->allowInsecureBackends()) {
253 const auto &row = d->rows[
index.
row()];
255 case BackendModel::BackendEnabledRole:
256 d->mgr->setBackendEnabled(row.backend.identifier(), value.toBool());
259 d->mgr->setBackendEnabled(row.backend.identifier(), value.toInt() ==
Qt::Checked);
273 const auto &row = d->rows[
index.
row()];
274 if (!d->mgr->allowInsecureBackends() && !row.backend.isSecure()) {
275 return f &
~Qt::ItemIsEnabled;
284 names.insert(NameRole,
"name");
285 names.insert(DescriptionRole,
"description");
286 names.insert(IdentifierRole,
"identifier");
287 names.insert(SecureRole,
"isSecure");
288 names.insert(ItemEnabledRole,
"itemEnabled");
289 names.insert(BackendEnabledRole,
"backendEnabled");
Model listing backends and allowing to configure which ones are active.
Mode mode
Configures the grouping mode for the content of this model.
Mode
Content grouping modes.
@ GroupByCountry
A backend might occur multiple times, for each country it is associated with.
@ Flat
Each backend appears exactly once, grouping by country is possible (the data is order by country),...
@ CountryCodeRole
a ISO 3166-1 code usable for grouping content by country
KPublicTransport::Manager * manager
Sets the KPublicTransport::Manager instance.
Information about a backend service queried for location/departure/journey data.
Type
Coverage quality as defined by the Transport API Repository format.
QVariantList backends
QML-compatible access to backends().
Query operations and data types for accessing realtime public transport information from online servi...
QAction * next(const QObject *recvr, const char *slot, QObject *parent)
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList< int > &roles)
virtual QHash< int, QByteArray > roleNames() const const
virtual Qt::ItemFlags flags(const QModelIndex &index) const const override
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const override
bool isValid() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool disconnect(const QMetaObject::Connection &connection)
QObject * parent() const const