7#include "backendmodel.h"
9#include <KPublicTransport/Backend>
10#include <KPublicTransport/Manager>
25class BackendModelPrivate
28 void repopulateModel(BackendModel *q);
29 void repopulateFlat();
30 void repopulateGrouped();
33 Manager *mgr =
nullptr;
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)
159 : QAbstractListModel(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();
215QVariant BackendModel::data(
const QModelIndex &index,
int role)
const
217 if (!
index.isValid() || !d->mgr) {
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()) {
251bool BackendModel::setData(
const QModelIndex &index,
const QVariant &value,
int role)
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);
265Qt::ItemFlags BackendModel::flags(
const QModelIndex &index)
const
268 if (!d->mgr || !
index.isValid()) {
273 const auto &row = d->rows[
index.row()];
274 if (!d->mgr->allowInsecureBackends() && !row.backend.isSecure()) {
275 return f & ~Qt::ItemIsEnabled;
281QHash<int, QByteArray> BackendModel::roleNames()
const
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");
295#include "moc_backendmodel.cpp"
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.
Type
Coverage quality as defined by the Transport API Repository format.
Entry point for starting public transport queries.
Query operations and data types for accessing realtime public transport information from online servi...
const QList< QKeySequence > & next()
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList< int > &roles)
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const=0
virtual QModelIndex parent(const QModelIndex &index) const const=0
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
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool disconnect(const QMetaObject::Connection &connection)