From b4f437db53e01138ce797ce7fbc7bee77735c79e Mon Sep 17 00:00:00 2001 From: Luciano Montanaro Date: Sun, 24 Nov 2013 19:33:46 +0100 Subject: [PATCH] Moved StationListModel to AbstractListModel base This is a needed prerequisite for the favorites feature --- application/stationitem.cpp | 86 ++++++++++++++++++++++++++++++++++ application/stationitem.h | 56 ++++++++++++++++++++++ application/stationlistmodel.cpp | 96 ++++++++++++++++++++++++++++++++------ application/stationlistmodel.h | 22 +++++---- 4 files changed, 237 insertions(+), 23 deletions(-) create mode 100644 application/stationitem.cpp create mode 100644 application/stationitem.h diff --git a/application/stationitem.cpp b/application/stationitem.cpp new file mode 100644 index 0000000..74e6b4f --- /dev/null +++ b/application/stationitem.cpp @@ -0,0 +1,86 @@ +/* + +Copyright (C) 2013 Luciano Montanaro + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. + +*/ + +#include "stationitem.h" +#include +#include +#include + +class StationItemData : public QSharedData { +public: + QGeoCoordinate position; + QString name; + QString code; +}; + +StationItem::StationItem() : d(new StationItemData) +{ +} + +StationItem::StationItem(const StationItem &rhs) : d(rhs.d) +{ +} + +StationItem &StationItem::operator=(const StationItem &rhs) +{ + if (this != &rhs) + d.operator=(rhs.d); + return *this; +} + +StationItem::~StationItem() +{ +} + +QString &StationItem::name() +{ + return d->name; +} + +void StationItem::setName(const QString &value) +{ + d->name = value; +} + +QString &StationItem::code() +{ + return d->code; +} + +void StationItem::setCode(const QString &value) +{ + d->code = value; +} + +QGeoCoordinate &StationItem::position() +{ + return d->position; +} + +void StationItem::setPosition(const QGeoCoordinate &value) +{ + d->position = value; +} + +bool StationItem::isValid() +{ + return !d->name.isEmpty(); +} diff --git a/application/stationitem.h b/application/stationitem.h new file mode 100644 index 0000000..384df0d --- /dev/null +++ b/application/stationitem.h @@ -0,0 +1,56 @@ +/* + +Copyright (C) 2013 Luciano Montanaro + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. + +*/ + +#ifndef STATIONSCHEDULEITEM_H +#define STATIONSCHEDULEITEM_H + +#include +#include + +#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0)) +QTM_USE_NAMESPACE +#endif + +class StationItemData; + +class StationItem +{ +public: + StationItem(); + StationItem(const StationItem &); + StationItem &operator=(const StationItem &); + ~StationItem(); + + QString &name(); + void setName(const QString &value); + + QString &code(); + void setCode(const QString &value); + + QGeoCoordinate &position(); + void setPosition(const QGeoCoordinate &value); + + bool isValid(); +private: + QSharedDataPointer d; +}; + +#endif // STATIONSCHEDULEITEM_H diff --git a/application/stationlistmodel.cpp b/application/stationlistmodel.cpp index f739b02..d7b6561 100644 --- a/application/stationlistmodel.cpp +++ b/application/stationlistmodel.cpp @@ -20,6 +20,7 @@ Boston, MA 02110-1301, USA. */ #include "stationlistmodel.h" +#include "settings.h" #include #include @@ -33,12 +34,14 @@ Q_DECLARE_METATYPE(QGeoCoordinate) #endif StationListModel::StationListModel(QObject *parent) : - QStandardItemModel(parent) + QAbstractListModel(parent) { - setRowCount(0); #if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0)) setRoleNames(roleNames()); #endif + Settings *settings = Settings::instance(); + m_favorites = settings->favoriteStations().toSet(); + qDebug() << "favorites:" << m_favorites; } bool StationListModel::load(const QString &filename) @@ -95,10 +98,76 @@ QHash StationListModel::roleNames() const return roles; } -int StationListModel::rowCount(const QModelIndex &parent) const +int StationListModel::rowCount(const QModelIndex &) const { - return QStandardItemModel::rowCount(parent); + return m_stations.count(); +} + +QVariant StationListModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) return QVariant(); + if (index.row() < 0 || index.row() >= m_stations.count()) { + return QVariant(); + } + StationItem item = m_stations[index.row()]; + Settings *settings = Settings::instance(); + switch (role) { + case Qt::DisplayRole: + return QVariant::fromValue(item.name()); + case PositionRole: + return QVariant::fromValue(item.position()); + case RecentIndicatorRole: + return QVariant(settings->recentStations().contains(item.name())); + case FavoriteIndicatorRole: + return QVariant(m_favorites.contains(item.name())); + case StationCodeRole: + return QVariant::fromValue(item.code()); + case LatitudeRole: + return QVariant::fromValue(item.position().latitude()); + case LongitudeRole: + return QVariant::fromValue(item.position().longitude()); + case SectionRole: + if (m_favorites.contains(item.name())) + return QVariant::fromValue(tr("Favorites")); + else + return QVariant(item.name()[0]); + default: + return QVariant::fromValue(QString("Unknown role requested")); + } +} +bool StationListModel::setData(const QModelIndex &index, QVariant &value, int role) +{ + if (!index.isValid()) + return false; + if (role == FavoriteIndicatorRole) { + bool favorite = value.toBool(); + if (data(index, FavoriteIndicatorRole) != favorite) { + QString name = m_stations[index.row()].name(); + if (favorite) { + qDebug() << "adding" << name << "to favorites"; + m_favorites.insert(name); + } else { + qDebug() << "removing" << name << "from favorites"; + m_favorites.remove(name); + } + Settings *settings = Settings::instance(); + settings->setFavoriteStations(QStringList::fromSet(m_favorites)); + QVector changedRoles; + changedRoles << FavoriteIndicatorRole; + //emit dataChanged(index, index, changedRoles); + emit dataChanged(index, index); + } + return true; + } + return false; +} + +Qt::ItemFlags StationListModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return 0; + return Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsEnabled; } void StationListModel::readStationsElement() @@ -122,11 +191,11 @@ void StationListModel::readStationsElement() void StationListModel::readStationElement() { - QStandardItem *item = new QStandardItem; + StationItem item; m_reader.readNext(); while (!m_reader.atEnd()) { if (m_reader.isEndElement()) { - this->appendRow(item); + m_stations.append(item); m_reader.readNext(); break; } else if (m_reader.isStartElement()) { @@ -139,40 +208,37 @@ void StationListModel::readStationElement() } else { skipUnknownElement(m_reader.name().toString()); } - item->setData(QVariant::fromValue(false), FavoriteIndicatorRole); } else { m_reader.readNext(); } } } -void StationListModel::readPosElement(QStandardItem *item) +void StationListModel::readPosElement(StationItem &item) { QStringList coordinates = m_reader.readElementText().split(","); QGeoCoordinate pos = QGeoCoordinate(coordinates[0].toDouble(), coordinates[1].toDouble()); - item->setData(QVariant::fromValue(pos), PositionRole); - item->setData(QVariant::fromValue(pos.longitude()), LongitudeRole); - item->setData(QVariant::fromValue(pos.latitude()), LatitudeRole); + item.setPosition(pos); m_reader.readElementText(); if (m_reader.isEndElement()) { m_reader.readNext(); } } -void StationListModel::readNameElement(QStandardItem *item) +void StationListModel::readNameElement(StationItem &item) { - item->setText(m_reader.readElementText()); + item.setName(m_reader.readElementText()); if (m_reader.isEndElement()) { m_reader.readNext(); } } -void StationListModel::readCodeElement(QStandardItem *item) +void StationListModel::readCodeElement(StationItem &item) { const QString code = m_reader.readElementText(); qDebug() << "reading code element" << code; - item->setData(QVariant::fromValue(code), StationCodeRole); + item.setCode(code); if (m_reader.isEndElement()) { m_reader.readNext(); } diff --git a/application/stationlistmodel.h b/application/stationlistmodel.h index 785122b..2f68d41 100644 --- a/application/stationlistmodel.h +++ b/application/stationlistmodel.h @@ -22,13 +22,16 @@ Boston, MA 02110-1301, USA. */ -#include +#include +#include #include -class QStandardItem; +#include "stationitem.h" + +class StationItem; class StationListModel; -class StationListModel : public QStandardItemModel +class StationListModel : public QAbstractListModel { Q_OBJECT Q_ENUMS(StationListRole) @@ -51,9 +54,10 @@ public: QHash roleNames() const; - // Needed to make SectionScroller happy. + Q_INVOKABLE Qt::ItemFlags flags(const QModelIndex &index) const; Q_INVOKABLE int rowCount(const QModelIndex &parent = QModelIndex()) const; - + Q_INVOKABLE QVariant data(const QModelIndex &index, int role) const; + Q_INVOKABLE bool setData(const QModelIndex &index, QVariant &value, int role = Qt::EditRole); signals: @@ -62,12 +66,14 @@ public slots: private: void readStationsElement(); void readStationElement(); - void readPosElement(QStandardItem *item); - void readNameElement(QStandardItem *item); - void readCodeElement(QStandardItem *item); + void readPosElement(StationItem &item); + void readNameElement(StationItem &item); + void readCodeElement(StationItem &item); void skipUnknownElement(const QString &name = QString()); QXmlStreamReader m_reader; + QList m_stations; + QSet m_favorites; }; #endif // STATIONLISTMODEL_H -- 1.7.9.5