[-]
[+]
|
Changed |
_service:tar_git:newsFish.spec
|
|
[-]
[+]
|
Changed |
_service
^
|
@@ -2,6 +2,6 @@
<service name="tar_git">
<param name="url">https://github.com/piggz/newsFish.git</param>
<param name="branch">main</param>
- <param name="revision"></param>
+ <param name="revision">0.5.0</param>
</service>
</services>
\ No newline at end of file
|
[-]
[+]
|
Deleted |
_service:tar_git:newsFish-0.4.2.tar.bz2/src/itemworker.cpp
^
|
@@ -1,116 +0,0 @@
-#include "itemworker.h"
-
-#include <QDebug>
-#include <QJsonArray>
-#include <QJsonDocument>
-#include <QJsonObject>
-#include <QSqlDatabase>
-#include <QSqlError>
-#include <QSqlQuery>
-#include <QVariant>
-
-ItemWorker::ItemWorker(const QByteArray &json, QObject *parent)
- : QObject(parent)
-{
- m_json = json;
-}
-
-void ItemWorker::process()
-{
- m_db = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), QStringLiteral("worker_connection"));
- m_db.setDatabaseName(QStringLiteral("ownnews.sqlite"));
-
- if (m_db.open()) {
- parseItems();
- Q_EMIT finished();
- } else {
- qDebug() << Q_FUNC_INFO << "Unable to open database" << m_db.lastError();
- }
-}
-
-void ItemWorker::parseItems()
-{
- auto data = QJsonDocument::fromJson(m_json);
- if (data.isNull() || !data.isObject()) {
- qWarning() << "Got invalid json";
- qDebug() << m_json;
- qDebug() << data;
- return;
- }
-
- const auto object = data.object();
-
- // OLD API QList<QVariant> items = data.toMap()["ocs"].toMap()["data"].toMap()["items"].toList();
- const auto items = object[QStringLiteral("items")].toArray();
-
- qDebug() << "Item Count" << items.size();
-
- for (const auto &item : items) {
- const auto map = item.toObject();
- addItem(map[QStringLiteral("id")].toInt(),
- map[QStringLiteral("feedId")].toInt(),
- map[QStringLiteral("title")].toString(),
- map[QStringLiteral("body")].toString(),
- map[QStringLiteral("url")].toString(),
- map[QStringLiteral("author")].toString(),
- map[QStringLiteral("pubDate")].toInt(),
- map[QStringLiteral("unread")].toBool(),
- map[QStringLiteral("starred")].toBool(),
- map[QStringLiteral("guid")].toString(),
- map[QStringLiteral("guidHash")].toString());
- }
-}
-
-void ItemWorker::addItem(int id,
- int feedid,
- const QString &title,
- const QString &body,
- const QString &link,
- const QString &author,
- unsigned int pubdate,
- bool unread,
- bool starred,
- const QString &guid,
- const QString &guidhash)
-{
-
- QSqlQuery qry(m_db);
- qry.prepare(
- QStringLiteral("INSERT OR REPLACE INTO items(id, feedid, title, body, link, author, pubdate, unread, starred, guid, guidhash) VALUES(:id, :feedid, "
- ":title, :body, :link, :author, :pubdate, :unread, :starred, :guid, :guidhash)"));
- qry.bindValue(QStringLiteral(":id"), id);
- qry.bindValue(QStringLiteral(":feedid"), feedid);
- qry.bindValue(QStringLiteral(":title"), title);
- qry.bindValue(QStringLiteral(":body"), body);
- qry.bindValue(QStringLiteral(":link"), link);
- qry.bindValue(QStringLiteral(":author"), author);
- qry.bindValue(QStringLiteral(":pubdate"), pubdate);
- qry.bindValue(QStringLiteral(":unread"), unread);
- qry.bindValue(QStringLiteral(":starred"), starred);
- qry.bindValue(QStringLiteral(":guid"), guid);
- qry.bindValue(QStringLiteral(":guidhash"), guidhash);
-
- // qDebug() << "Adding item " << feedid << title << pubdate;
-
- bool ret = qry.exec();
- if (!ret)
- qDebug() << qry.lastError();
- // else {
- // qDebug() << "item inserted!";
- // TODO
-#if 0
- QVariantMap item;
- item["id"] = id;
- item["feedid"] = feedid;
- item["title"] = title;
- item["body"] = body;
- item["link"] = link;
- item["author"] = author;
- item["pubdate"] = QDateTime::fromTime_t(pubdate);
- item["unread"] = unread;
- item["starred"] = starred;
-
- m_items << item;
-#endif
- // }
-}
|
[-]
[+]
|
Deleted |
_service:tar_git:newsFish-0.4.2.tar.bz2/src/itemworker.h
^
|
@@ -1,40 +0,0 @@
-#ifndef ITEMWORKER_H
-#define ITEMWORKER_H
-
-#include <QObject>
-#include <QSqlDatabase>
-
-class QSqlDatabase;
-
-class ItemWorker : public QObject
-{
- Q_OBJECT
-public:
- explicit ItemWorker(const QByteArray &json, QObject *parent = nullptr);
-
-public Q_SLOTS:
- void process();
-
-Q_SIGNALS:
- void finished();
- void error(QString err);
-
-private:
- void parseItems();
- void addItem(int id,
- int feedid,
- const QString &title,
- const QString &body,
- const QString &link,
- const QString &author,
- unsigned int pubdate,
- bool unread,
- bool starred,
- const QString &guid,
- const QString &guidhash);
-
- QSqlDatabase m_db;
- QByteArray m_json;
-};
-
-#endif // ITEMWORKER_H
|
[-]
[+]
|
Changed |
_service:tar_git:newsFish-0.5.0.tar.bz2/CMakeLists.txt
^
|
@@ -53,6 +53,7 @@
if (NOT ANDROID AND NOT SAILFISHOS)
find_package(KF${QT_MAJOR_VERSION}QQC2DesktopStyle REQUIRED)
+ find_package(KF${QT_MAJOR_VERSION}DBusAddons REQUIRED)
find_package(Qt${QT_MAJOR_VERSION}Svg REQUIRED)
find_package(Qt${QT_MAJOR_VERSION}Keychain)
set_package_properties(Qt${QT_MAJOR_VERSION}Keychain PROPERTIES
|
[-]
[+]
|
Changed |
_service:tar_git:newsFish-0.5.0.tar.bz2/src/CMakeLists.txt
^
|
@@ -16,7 +16,6 @@
Helper.cpp
feedsmodel.cpp
itemsmodel.cpp
- itemworker.cpp
main.cpp
newsinterface.cpp
)
@@ -54,7 +53,7 @@
)
else()
if(NOT SAILFISHOS)
- target_link_libraries(newsfish_static PUBLIC Qt::Widgets)
+ target_link_libraries(newsfish_static PUBLIC Qt::Widgets KF${QT_MAJOR_VERSION}::DBusAddons)
endif()
endif()
|
[-]
[+]
|
Changed |
_service:tar_git:newsFish-0.5.0.tar.bz2/src/Helper.cpp
^
|
@@ -1,6 +1,6 @@
#include "Helper.h"
#include <QDebug>
-#include <qstringliteral.h>
+#include <QRegularExpression>
Helper::Helper(QObject *parent) :
QObject(parent)
@@ -21,3 +21,34 @@
{
return settings.contains(QStringLiteral("settings/") + settingname);
}
+
+QString Helper::adjustedContent(const int width, const int fontSize, const QString &text)
+{
+ QString ret(text);
+ static QRegularExpression imgRegex(QStringLiteral("<img ((?!width=\"[0-9]+(px)?\").)*(width=\"([0-9]+)(px)?\")?[^>]*>"));
+
+ QRegularExpressionMatchIterator i = imgRegex.globalMatch(ret);
+ while (i.hasNext()) {
+ QRegularExpressionMatch match = i.next();
+
+ QString imgTag(match.captured());
+ if (imgTag.contains(QStringLiteral("wp-smiley")) || imgTag.contains(QStringLiteral("twemoji"))) {
+ imgTag.insert(4, QStringLiteral(" width=\"%1\"").arg(fontSize));
+ }
+
+ QString widthParameter = match.captured(4);
+
+ if (widthParameter.length() != 0) {
+ if (widthParameter.toInt() > width) {
+ imgTag.replace(match.captured(3), QStringLiteral("width=\"%1\"").arg(width));
+ imgTag.replace(QRegularExpression(QStringLiteral("height=\"([0-9]+)(px)?\"")), QString());
+ }
+ } else {
+ imgTag.insert(4, QStringLiteral(" width=\"%1\"").arg(width));
+ }
+ ret.replace(match.captured(), imgTag);
+ }
+
+ ret.replace(QStringLiteral("<img"), QStringLiteral("<br /> <img"));
+ return ret;
+}
|
[-]
[+]
|
Changed |
_service:tar_git:newsFish-0.5.0.tar.bz2/src/Helper.h
^
|
@@ -16,6 +16,8 @@
void setSetting(const QString& settingname, QVariant val);
bool settingExists(const QString &settingname);
+ QString adjustedContent(const int width, const int fontSize, const QString &text);
+
private:
QSettings settings;
|
[-]
[+]
|
Changed |
_service:tar_git:newsFish-0.5.0.tar.bz2/src/feedsmodel.cpp
^
|
@@ -6,19 +6,95 @@
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>
+#include <qsqldatabase.h>
+#include <qsqlquery.h>
-FeedsModel::FeedsModel(QObject *parent)
+FeedsModel::Feed FeedsModel::Feed::fromJson(const QJsonObject &object)
+{
+ return Feed{
+ object[QStringLiteral("id")].toInt(),
+ object[QStringLiteral("url")].toString(),
+ object[QStringLiteral("title")].toString(),
+ object[QStringLiteral("faviconLink")].toString(),
+ QDateTime::fromSecsSinceEpoch(object[QStringLiteral("added")].toInt()),
+ object[QStringLiteral("folderId")].toInt(),
+ object[QStringLiteral("unreadCount")].toInt(),
+ object[QStringLiteral("ordering")].toInt(),
+ object[QStringLiteral("link")].toString(),
+ object[QStringLiteral("pinned")].toBool(),
+ object[QStringLiteral("updateErrorCount")].toInt(),
+ object[QStringLiteral("lastUpdateError")].toString(),
+ };
+}
+
+FeedsModel::Feed FeedsModel::Feed::fromQuery(const QSqlQuery &query)
+{
+ return Feed{
+ query.value(0).toInt(),
+ query.value(1).toString(),
+ query.value(2).toString(),
+ query.value(3).toString(),
+ QDateTime::fromSecsSinceEpoch(query.value(4).toInt()),
+ query.value(5).toInt(),
+ query.value(6).toInt(),
+ query.value(7).toInt(),
+ query.value(8).toString(),
+ query.value(9).toBool(),
+ query.value(10).toInt(),
+ query.value(11).toString(),
+ };
+}
+
+FeedsModel::FeedsModel(const QSqlDatabase &db, QObject *parent)
: QAbstractListModel(parent)
+ , m_db(db)
{
+ if (!m_db.open()) {
+ qWarning() << Q_FUNC_INFO << "DB is not open:" << m_db.lastError();
+ return;
+ }
+
+ QSqlQuery qry;
+
+ qry.prepare(QStringLiteral(R"RAW(
+ CREATE TABLE IF NOT EXISTS feeds (
+ id INTEGER UNIQUE PRIMARY KEY,
+ feed_url VARCHAR(2048),
+ title VARCHAR(1024),
+ favicon_link VARCHAR(2048),
+ added INTEGER,
+ folder_id INTEGER,
+ unread_count INTEGER,
+ ordering INTEGER,
+ link VARCHAR(2048),
+ pinned INTEGER,
+ update_error_count INTEGER,
+ last_update_error VARCHAR(1024)
+ ))RAW"));
+
+ if (!qry.exec()) {
+ qWarning() << Q_FUNC_INFO << "Error trying to create feeds table" << qry.lastError();
+ return;
+ }
+
+ loadData();
}
QHash<int, QByteArray> FeedsModel::roleNames() const
{
return {
- {FeedId, "feedid"},
- {FeedTitle, "feedtitle"},
- {FeedURL, "feedurl"},
- {FeedIcon, "feedicon"},
+ {IdRole, "feedId"},
+ {FeedUrlRole, "feedUrl"},
+ {TitleRole, "title"},
+ {FaviconLinkRole, "faviconLink"},
+ {AddedRole, "added"},
+ {FolderIdRole, "folderId"},
+ {UnreadCountRole, "unreadCount"},
+ {OrderingRole, "ordering"},
+ {LinkRole, "link"},
+ {PinnedRole, "pinned"},
+ {UpdateErrorCountRole, "updateErrorCount"},
+ {LastUpdateErrorRole, "lastUpdateError"},
};
}
@@ -26,91 +102,90 @@
{
QList<int> ids;
- for (const QVariantMap &feed : std::as_const(m_feeds)) {
- ids << feed[QStringLiteral("id")].toInt();
+ for (const auto &feed : std::as_const(m_feeds)) {
+ ids << feed.id;
}
return ids;
}
-void FeedsModel::addFeed(int id, const QString &title, const QString &url, const QString &icon)
+void FeedsModel::loadData()
{
- if (m_db.isOpen()) {
- QSqlQuery qry(m_db);
- qry.prepare(QStringLiteral("INSERT OR REPLACE INTO feeds(id, title, url, icon) VALUES(:id, :title, :url, :icon)"));
- qry.bindValue(QStringLiteral(":id"), id);
- qry.bindValue(QStringLiteral(":title"), title);
- qry.bindValue(QStringLiteral(":url"), url);
- qry.bindValue(QStringLiteral(":icon"), icon);
-
- bool ret = qry.exec();
- if (!ret)
- qDebug() << qry.lastError();
- else {
- qDebug() << "feed inserted!";
- QVariantMap feed;
- feed[QStringLiteral("id")] = id;
- feed[QStringLiteral("title")] = title;
- feed[QStringLiteral("url")] = url;
- feed[QStringLiteral("icon")] = icon;
- m_feeds << feed;
- }
- } else {
- qDebug() << "Unable to add feed:" << m_db.lastError();
+ if (!m_db.isOpen()) {
+ qWarning() << Q_FUNC_INFO << "DB is not open:" << m_db.lastError();
+ return;
}
-}
-void FeedsModel::loadData()
-{
- if (m_db.isOpen()) {
- qDebug() << "Loading feed data";
- QSqlQuery qry(m_db);
- qry.prepare(QStringLiteral("SELECT id, title, url, icon FROM feeds"));
-
- bool ret = qry.exec();
- if (!ret) {
- qDebug() << qry.lastError();
- } else {
- beginResetModel();
- while (qry.next()) {
- QVariantMap feed;
- feed[QStringLiteral("id")] = qry.value(0).toInt();
- feed[QStringLiteral("title")] = qry.value(1).toString();
- feed[QStringLiteral("url")] = qry.value(2).toString();
- feed[QStringLiteral("icon")] = qry.value(3).toString();
- m_feeds << feed;
- }
- endResetModel();
- }
+ qDebug() << "Loading feed data from cache";
+
+ QSqlQuery query(m_db);
+ query.prepare(QStringLiteral(R"RAW(
+ SELECT
+ id,
+ feed_url,
+ title,
+ favicon_link,
+ added,
+ folder_id,
+ unread_count,
+ ordering,
+ link,
+ pinned,
+ update_error_count,
+ last_update_error
+ FROM
+ feeds
+ )RAW"));
+
+ if (!query.exec()) {
+ qWarning() << Q_FUNC_INFO << "Error trying to fetch data from cache" << query.lastError() << query.lastQuery();
+ return;
+ }
+
+ while (query.next()) {
+ m_feeds << Feed::fromQuery(query);
}
+ endResetModel();
}
void FeedsModel::checkFeeds(QList<int> feeds)
|
[-]
[+]
|
Changed |
_service:tar_git:newsFish-0.5.0.tar.bz2/src/feedsmodel.h
^
|
@@ -2,32 +2,64 @@
#define FEEDSMODEL_H
#include <QAbstractListModel>
+#include <QDateTime>
#include <QList>
#include <QMetaType>
#include <QSqlDatabase>
#include <QVariantMap>
+
class FeedsModel : public QAbstractListModel
{
Q_OBJECT
public:
- enum Roles { FeedId = Qt::UserRole + 1, FeedTitle, FeedURL, FeedIcon };
+ enum Roles {
+ IdRole = Qt::UserRole + 1,
+ FeedUrlRole,
+ TitleRole,
+ FaviconLinkRole,
+ AddedRole,
+ FolderIdRole,
+ UnreadCountRole,
+ OrderingRole,
+ LinkRole,
+ PinnedRole,
+ UpdateErrorCountRole,
+ LastUpdateErrorRole,
+ };
- explicit FeedsModel(QObject *parent = nullptr);
+ explicit FeedsModel(const QSqlDatabase &db, QObject *parent = nullptr);
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QHash<int, QByteArray> roleNames() const override;
void parseFeeds(const QByteArray &json);
- void setDatabase(const QString &dbname);
QList<int> feedIds() const;
private:
- QList<QVariantMap> m_feeds;
+ struct Feed {
+ int id;
+ QString feedUrl;
+ QString title;
+ QString faviconLink;
+ QDateTime added;
+ int folderId;
+ int unreadCount;
+ int ordering;
+ QString link;
+ bool pinned;
+ int updateErrorCount;
+ QString lastUpdateError;
+
+ static Feed fromJson(const QJsonObject &object);
+ static Feed fromQuery(const QSqlQuery &query);
+ };
+
+ QList<Feed> m_feeds;
QSqlDatabase m_db;
QString m_databaseName;
- void addFeed(int id, const QString &title, const QString &url, const QString &icon);
+ void addFeed(const Feed &feed);
void loadData();
void checkFeeds(QList<int> feeds);
};
|
[-]
[+]
|
Changed |
_service:tar_git:newsFish-0.5.0.tar.bz2/src/itemsmodel.cpp
^
|
@@ -1,19 +1,84 @@
#include "itemsmodel.h"
-#include "itemworker.h"
#include <QDateTime>
#include <QDebug>
+#include <QJsonArray>
+#include <QJsonDocument>
+#include <QJsonObject>
#include <QRegExp>
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>
#include <QTextDocument>
-#include <QThread>
-#include <qstringliteral.h>
-ItemsModel::ItemsModel(QObject *parent)
+ItemsModel::Item ItemsModel::Item::fromJson(const QJsonObject &object)
+{
+ QTextDocument textDocument;
+ textDocument.setHtml(object[QStringLiteral("body")].toString());
+
+ return {
+ object[QStringLiteral("id")].toInt(),
+ object[QStringLiteral("feedId")].toInt(),
+ object[QStringLiteral("title")].toString(),
+ object[QStringLiteral("guid")].toString(),
+ object[QStringLiteral("guidHash")].toString(),
+ object[QStringLiteral("body")].toString(),
+ object[QStringLiteral("url")].toString(),
+ object[QStringLiteral("author")].toString(),
+ QDateTime::fromSecsSinceEpoch(object[QStringLiteral("pubDate")].toInt()),
+ object[QStringLiteral("unread")].toBool(),
+ object[QStringLiteral("starred")].toBool(),
+ };
+}
+
+void ItemsModel::Item::cacheInDatabase(QSqlDatabase database) const
+{
+ QSqlQuery qry(database);
+ qry.prepare(
+ QStringLiteral("INSERT OR REPLACE INTO items(id, feedid, title, body, link, author, pubdate, unread, starred, guid, guidhash) VALUES(:id, :feedid, "
+ ":title, :body, :link, :author, :pubdate, :unread, :starred, :guid, :guidhash)"));
+ qry.bindValue(QStringLiteral(":id"), id);
+ qry.bindValue(QStringLiteral(":feedid"), feedId);
+ qry.bindValue(QStringLiteral(":title"), title);
+ qry.bindValue(QStringLiteral(":guid"), guid);
+ qry.bindValue(QStringLiteral(":guidhash"), guidHash);
+ qry.bindValue(QStringLiteral(":body"), body);
+ qry.bindValue(QStringLiteral(":link"), link);
+ qry.bindValue(QStringLiteral(":author"), author);
+ qry.bindValue(QStringLiteral(":pubdate"), publishDate.toSecsSinceEpoch());
+ qry.bindValue(QStringLiteral(":unread"), unread ? 1 : 0);
+ qry.bindValue(QStringLiteral(":starred"), starred ? 1 : 0);
+
+ if (!qry.exec()) {
+ qWarning() << Q_FUNC_INFO << "Error trying to cache a feed item" << qry.lastError();
+ }
+}
+
+ItemsModel::ItemsModel(const QSqlDatabase &db, QObject *parent)
: QAbstractListModel(parent)
{
+ m_db = db;
+ QSqlQuery qry(db);
+
+ qry.prepare(
+ QStringLiteral("CREATE TABLE IF NOT EXISTS items (id INTEGER UNIQUE PRIMARY KEY, \
+ feedid INTEGER, \
+ title VARCHAR(1024), \
+ guid VARCHAR(1024), \
+ guidhash VARCHAR(1024), \
+ body VARCHAR(2048), \
+ link VARCHAR(2048), \
+ author VARCHAR(1024), \
+ pubdate INTEGER, \
+ unread INTEGER, \
+ starred INTEGER)"));
+
+ bool ret = qry.exec();
+ if (!ret) {
+ qDebug() << qry.lastError();
+ } else {
+ qDebug() << "Items table created!";
+ }
}
QVariant ItemsModel::data(const QModelIndex &index, int role) const
@@ -31,8 +96,6 @@
return item.title;
case ItemBody:
return item.body;
- case ItemBodyHTML:
- return item.bodyHtml;
case ItemLink:
return item.link;
case ItemAuthor:
@@ -57,22 +120,48 @@
return parent.isValid() ? 0 : m_items.count();
}
-void ItemsModel::parseItems(const QByteArray &json)
+void ItemsModel::parseItems(const QString &feedId, const QByteArray &json)
{
- qDebug() << Q_FUNC_INFO;
+ auto data = QJsonDocument::fromJson(json);
+ if (data.isNull() || !data.isObject()) {
+ qWarning() << "Got invalid json" << json;
+ return;
+ }
+
+ QList<Item> feedItems;
+
+ const auto object = data.object();
+ const auto items = object[QStringLiteral("items")].toArray();
+
+ if (items.isEmpty()) {
+ return;
+ }
+
+ m_db.transaction();
+ for (const auto &value : items) {
+ const auto object = value.toObject();
+ const auto item = Item::fromJson(object);
+ feedItems << item;
+ item.cacheInDatabase(m_db);
+ }
+ m_db.commit();
+
+ if (feedItems.length() > 15) {
+ QSqlQuery query(m_db);
+ query.prepare(QStringLiteral("DELETE FROM items WHERE pubdate < :pubdate AND feedid = :feedid"));
+ query.bindValue(QStringLiteral(":pubdate"), feedItems[14].publishDate.toTime_t());
+ query.bindValue(QStringLiteral(":feedid"), feedId);
- m_items.clear();
+ if (!query.exec()) {
+ qWarning() << Q_FUNC_INFO << "Error trying to delete old items of the feed item" << query.lastError();
+ }
+ }
- auto thread = new QThread;
- auto worker = new ItemWorker(json);
- worker->moveToThread(thread);
- // connect(worker, SIGNAL(error(QString)), this, SLOT(errorString(QString)));
- connect(thread, &QThread::started, worker, &ItemWorker::process);
- connect(worker, &ItemWorker::finished, thread, &QThread::quit);
- connect(worker, &ItemWorker::finished, worker, &QObject::deleteLater);
- connect(worker, &ItemWorker::finished, this, &ItemsModel::slotWorkerFinished);
- connect(thread, &QThread::finished, thread, &QObject::deleteLater);
- thread->start();
+ if (m_feedId == feedId) {
+ beginResetModel();
+ m_items = feedItems;
+ endResetModel();
+ }
}
void ItemsModel::slotWorkerFinished()
@@ -80,38 +169,19 @@
Q_EMIT feedParseComplete();
}
-void ItemsModel::setDatabase(const QString &dbname)
+int ItemsModel::feedId() const
{
- m_databaseName = dbname;
- m_db = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), QStringLiteral("item_connection"));
- m_db.setDatabaseName(m_databaseName);
- if (m_db.open()) {
- QSqlQuery qry;
-
- qry.prepare(
- QStringLiteral("CREATE TABLE IF NOT EXISTS items (id INTEGER UNIQUE PRIMARY KEY, \
- feedid INTEGER, \
- title VARCHAR(1024), \
- guid VARCHAR(1024), \
- guidhash VARCHAR(1024), \
- body VARCHAR(2048), \
- link VARCHAR(2048), \
- author VARCHAR(1024), \
- pubdate INTEGER, \
- unread INTEGER, \
- starred INTEGER)"));
-
- bool ret = qry.exec();
- if (!ret) {
- qDebug() << qry.lastError();
- } else {
- qDebug() << "Items table created!";
- }
- }
+ return m_feedId;
}
-void ItemsModel::setFeed(int feedId)
+void ItemsModel::setFeedId(int feedId)
{
+ if (m_feedId == feedId) {
|
[-]
[+]
|
Changed |
_service:tar_git:newsFish-0.5.0.tar.bz2/src/itemsmodel.h
^
|
@@ -4,10 +4,15 @@
#include <QDateTime>
#include <QList>
#include <QSqlDatabase>
+#include <qsqldatabase.h>
class ItemsModel : public QAbstractListModel
{
Q_OBJECT
+
+ /// The if of feed that this ItemsModel will display
+ Q_PROPERTY(int feedId READ feedId WRITE setFeedId NOTIFY feedIdChanged)
+
public:
enum Roles {
ItemId = Qt::UserRole + 1,
@@ -16,7 +21,6 @@
ItemGUID,
ItemGUIDHash,
ItemBody,
- ItemBodyHTML,
ItemLink,
ItemAuthor,
ItemPubDate,
@@ -24,20 +28,23 @@
ItemStarred
};
- explicit ItemsModel(QObject *parent = nullptr);
+ explicit ItemsModel(const QSqlDatabase &db, QObject *parent = nullptr);
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
int rowCount(const QModelIndex &parent = {}) const override;
QHash<int, QByteArray> roleNames() const override;
- void parseItems(const QByteArray &json);
+ int feedId() const;
+ void setFeedId(int feedId);
+
+ void parseItems(const QString &feedId, const QByteArray &json);
void setDatabase(const QString &dbname);
- void setFeed(int feedId);
void recreateTable();
- void deleteOldData(int days);
+ void setItemRead(int itemId, bool read);
Q_SIGNALS:
void feedParseComplete();
+ void feedIdChanged();
private Q_SLOTS:
void slotWorkerFinished();
@@ -50,18 +57,20 @@
QString guid;
QString guidHash;
QString body;
- QString bodyHtml;
QString link;
QString author;
QDateTime publishDate;
bool unread;
bool starred;
+
+ static Item fromJson(const QJsonObject &object);
+ void cacheInDatabase(QSqlDatabase database) const;
};
QList<Item> m_items;
+ int m_feedId;
QSqlDatabase m_db;
- QString m_databaseName;
};
Q_DECLARE_METATYPE(ItemsModel *);
|
[-]
[+]
|
Changed |
_service:tar_git:newsFish-0.5.0.tar.bz2/src/main.cpp
^
|
@@ -31,8 +31,6 @@
// #include <sailfishapp.h>
#include "../newsfish-version.h"
#include "Helper.h"
-#include "feedsmodel.h"
-#include "itemsmodel.h"
#include "newsinterface.h"
#include <KAboutData>
#include <KLocalizedContext>
@@ -44,6 +42,7 @@
#if defined(Q_OS_ANDROID) || defined(Q_OS_SAILFISHOS)
#include <QGuiApplication>
#else
+#include <KDBusService>
#include <QApplication>
#endif
@@ -82,8 +81,10 @@
KAboutData::setApplicationData(about);
QGuiApplication::setWindowIcon(QIcon::fromTheme(QStringLiteral("uk.co.piggz.newsfish")));
- qmlRegisterType<FeedsModel>("uk.co.piggz", 1, 0, "FeedsModel");
- qmlRegisterType<ItemsModel>("uk.co.piggz", 1, 0, "ItemsModel");
+#if !(defined(Q_OS_ANDROID) || defined(Q_OS_SAILFISHOS))
+ KDBusService service(KDBusService::Unique);
+#endif
+
qmlRegisterSingletonType<Helper>("uk.co.piggz", 1, 0, "Helper", [](QQmlEngine *, QJSEngine *) {
return new Helper;
});
|
[-]
[+]
|
Changed |
_service:tar_git:newsFish-0.5.0.tar.bz2/src/newsinterface.cpp
^
|
@@ -2,8 +2,11 @@
#include <QAuthenticator>
#include <QDebug>
+#include <QDir>
+#include <QGuiApplication>
#include <QNetworkAccessManager>
#include <QNetworkReply>
+#include <QStandardPaths>
#include <QUrlQuery>
// const QString NewsInterface::rootPath = "/ocs/v1.php/apps/news/";
@@ -12,10 +15,11 @@
NewsInterface::NewsInterface(QObject *parent)
: QObject(parent)
+ , m_networkManager(new QNetworkAccessManager(this))
+ , m_db(QSqlDatabase::addDatabase(QStringLiteral("QSQLITE")))
+ , m_busy(false)
{
- m_networkManager = new QNetworkAccessManager();
-
- m_busy = false;
+ m_networkManager->setAutoDeleteReplies(true);
feedsPath = rootPath + QStringLiteral("feeds");
itemsPath = rootPath + QStringLiteral("items");
@@ -24,30 +28,25 @@
SIGNAL(authenticationRequired(QNetworkReply *, QAuthenticator *)),
this,
SLOT(slotAuthenticationRequired(QNetworkReply *, QAuthenticator *)));
- connect(m_networkManager, SIGNAL(finished(QNetworkReply *)), this, SLOT(slotReplyFinished(QNetworkReply *)));
-
- m_db = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"));
- m_db.setDatabaseName(QStringLiteral("ownnews.sqlite"));
- m_db.open(); // TODO error checking
+ if (QDir().mkpath(QDir::cleanPath(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)))) {
+ qCritical() << "Couldn't create directory for cache database";
+ }
+ const auto path = QDir::cleanPath(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + QLatin1Char('/') + qGuiApp->applicationName()
+ + QStringLiteral(".sqlite"));
+ qDebug() << "Storing cache in" << path;
+ m_db.setDatabaseName(path);
- m_feedsModel = new FeedsModel(this);
- m_feedsModel->setDatabase(QStringLiteral("ownnews.sqlite"));
+ m_db.open();
- m_itemsModel = new ItemsModel(this);
- m_itemsModel->setDatabase(QStringLiteral("ownnews.sqlite"));
+ m_feedsModel = new FeedsModel(m_db, this);
+ m_itemsModel = new ItemsModel(m_db, this);
connect(m_itemsModel, SIGNAL(feedParseComplete()), this, SLOT(slotItemProcessFinished()));
}
-void NewsInterface::sync(const QString &url, const QString &username, const QString &password, int daysToRetain, int numItemsToSync)
+void NewsInterface::sync()
{
- serverPath = url;
- m_username = username;
- m_password = password;
- m_daysToRetain = daysToRetain;
- m_numItemsToSync = numItemsToSync;
-
getFeeds();
}
@@ -58,49 +57,6 @@
authenticator->setPassword(m_password);
}
-void NewsInterface::slotReplyFinished(QNetworkReply *reply)
-{
- qDebug() << "Reply from " << reply->url().path();
-
- if (reply->url().path().endsWith(feedsPath)) {
- qDebug() << "Reply from feeds";
- m_feedsModel->parseFeeds(reply->readAll());
- m_feedsToSync = m_feedsModel->feedIds();
- syncNextFeed();
- return;
- }
-
- if (reply->url().path().endsWith(itemsPath)) {
- qDebug() << "Reply from items";
- m_itemsModel->parseItems(reply->readAll());
- return;
- }
-
- if (reply->url().path().endsWith(QStringLiteral("/read"))) {
- qDebug() << "Reply from item read";
- return;
- }
-
- if (reply->url().path().endsWith(QStringLiteral("/unread"))) {
- qDebug() << "Reply from item unread";
- return;
- }
-
- if (reply->url().path().endsWith(QStringLiteral("/star"))) {
- qDebug() << "Reply from item star" << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
-
- return;
- }
-
- if (reply->url().path().endsWith(QStringLiteral("/unstar"))) {
- qDebug() << "Reply from item unstar";
- return;
- }
-
- m_busy = false;
- Q_EMIT busyChanged(m_busy);
-}
-
void NewsInterface::slotItemProcessFinished()
{
syncNextFeed();
@@ -112,17 +68,26 @@
m_busy = true;
Q_EMIT busyChanged(m_busy);
- QUrl url(serverPath + feedsPath);
+ QUrl url(m_serverPath + feedsPath);
url.setUserName(m_username);
url.setPassword(m_password);
- qDebug() << url;
+ qDebug() << url << this;
QNetworkRequest r(url);
addAuthHeader(&r);
- QNetworkReply *reply = m_networkManager->get(r);
- connect(reply, SIGNAL(sslErrors(QList<QSslError>)), reply, SLOT(ignoreSslErrors()));
+ auto reply = m_networkManager->get(r);
+ connect(reply, &QNetworkReply::finished, this, [this, reply]() {
+ qDebug() << "Reply from feeds";
+ m_feedsModel->parseFeeds(reply->readAll());
+ m_feedsToSync = m_feedsModel->feedIds();
+ syncNextFeed();
+ });
+
+ connect(reply, &QNetworkReply::sslErrors, this, [reply](const QList<QSslError> &) {
+ reply->ignoreSslErrors();
+ });
}
}
@@ -134,7 +99,7 @@
}
qDebug() << "Getting items for feed " << feedId;
- QUrl url(serverPath + itemsPath);
+ QUrl url(m_serverPath + itemsPath);
url.setUserName(m_username);
url.setPassword(m_password);
@@ -146,13 +111,20 @@
q.addQueryItem(QStringLiteral("format"), format);
q.addQueryItem(QStringLiteral("getRead"), QStringLiteral("true"));
url.setQuery(q);
- qDebug() << url;
QNetworkRequest r(url);
addAuthHeader(&r);
- QNetworkReply *reply = m_networkManager->get(r);
- connect(reply, SIGNAL(sslErrors(QList<QSslError>)), reply, SLOT(ignoreSslErrors()));
+ auto reply = m_networkManager->get(r);
+ connect(reply, &QNetworkReply::finished, this, [this, reply, feedId]() {
+ m_itemsModel->parseItems(QString::number(feedId), reply->readAll());
+
+ syncNextFeed();
+ });
+
+ connect(reply, &QNetworkReply::sslErrors, this, [reply](const QList<QSslError> &) {
+ reply->ignoreSslErrors();
+ });
}
void NewsInterface::syncNextFeed()
@@ -165,7 +137,6 @@
return;
}
- m_itemsModel->deleteOldData(m_daysToRetain);
m_busy = false;
Q_EMIT busyChanged(m_busy);
}
@@ -186,12 +157,6 @@
return m_busy;
}
-void NewsInterface::viewItems(int feedId)
-{
- qDebug() << "Viewing feed" << feedId;
- m_itemsModel->setFeed(feedId);
-}
|
[-]
[+]
|
Changed |
_service:tar_git:newsFish-0.5.0.tar.bz2/src/newsinterface.h
^
|
@@ -18,6 +18,11 @@
Q_PROPERTY(FeedsModel *feedsModel READ feedsModel CONSTANT)
Q_PROPERTY(ItemsModel *itemsModel READ itemsModel CONSTANT)
Q_PROPERTY(bool busy READ isBusy NOTIFY busyChanged)
+ Q_PROPERTY(QString serverPath MEMBER m_serverPath NOTIFY serverPathChanged)
+ Q_PROPERTY(QString username MEMBER m_username NOTIFY usernameChanged)
+ Q_PROPERTY(QString password MEMBER m_password NOTIFY passwordChanged)
+ Q_PROPERTY(int daysToRetain MEMBER m_daysToRetain NOTIFY daysToRetainChanged)
+ Q_PROPERTY(int numItemsToSync MEMBER m_numItemsToSync NOTIFY numItemsToSyncChanged)
public:
explicit NewsInterface(QObject *parent = nullptr);
@@ -26,14 +31,18 @@
FeedsModel *feedsModel() const;
ItemsModel *itemsModel() const;
- Q_INVOKABLE void sync(const QString &url, const QString &username, const QString &password, int daysToRetain = 14, int numItemsToSync = 20);
- Q_INVOKABLE void viewItems(int feedId);
+ Q_INVOKABLE void sync();
Q_INVOKABLE void recreateDatabase();
Q_INVOKABLE void setItemRead(long itemId, bool read);
Q_INVOKABLE void setItemStarred(int feedId, const QString &itemGUIDHash, bool starred);
Q_SIGNALS:
void busyChanged(bool busy);
+ void serverPathChanged();
+ void usernameChanged();
+ void passwordChanged();
+ void daysToRetainChanged();
+ void numItemsToSyncChanged();
private:
QNetworkAccessManager *m_networkManager;
@@ -44,13 +53,13 @@
static const QString rootPath;
static const QString format;
- QString serverPath;
+ QString m_serverPath;
QString feedsPath;
QString itemsPath;
QString m_username;
QString m_password;
- int m_daysToRetain;
- int m_numItemsToSync;
+ int m_daysToRetain = 10;
+ int m_numItemsToSync = 20;
bool m_busy;
@@ -63,7 +72,6 @@
private Q_SLOTS:
void slotAuthenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator);
- void slotReplyFinished(QNetworkReply *);
void slotItemProcessFinished();
};
|
[-]
[+]
|
Changed |
_service:tar_git:newsFish-0.5.0.tar.bz2/src/qml/newsFish.qml
^
|
@@ -1,79 +1,89 @@
-import QtQuick 2.1
-import QtQuick.Controls 2.0 as QQC2
-import org.kde.kirigami 2.4 as Kirigami
+import QtQuick 2.15
+import QtQuick.Controls 2.15 as QQC2
+import org.kde.kirigami 2.20 as Kirigami
import "pages"
import uk.co.piggz 1.0
-Kirigami.ApplicationWindow
-{
+Kirigami.ApplicationWindow {
+ id: root
+
+ property string _ownCloudURL: ""
+ property string _username: ""
+ property string _password: ""
+
+ pageStack {
+ defaultColumnWidth: Kirigami.Units.gridUnit * 20
+ globalToolBar {
+ style: Kirigami.ApplicationHeaderStyle.ToolBar
+ showNavigationButtons: if (root.pageStack.currentIndex > 0 || root.pageStack.layers.currentIndex > 0) {
+ return Kirigami.ApplicationHeaderStyle.ShowBackButton
+ } else {
+ return 0
+ }
+ }
+ }
+
globalDrawer: Kirigami.GlobalDrawer {
isMenu: true
actions: Kirigami.Action {
text: i18nc("@action:button", "Settings")
icon.name: "configure"
onTriggered: {
- pageStack.replace( Qt.resolvedUrl("pages/SettingsPage.qml") )
+ root.pageStack.pushDialogLayer(Qt.resolvedUrl("pages/SettingsPage.qml"))
}
}
}
- ItemView {
- id: itemView
- }
-
- ItemPage {
- id: itemPage
- }
-
Component.onCompleted: {
- console.log("Loading Settings");
- _ownCloudURL = Helper.getSetting("ownCloudURL", "");
- _username = Helper.getSetting("username", "");
- _password = Helper.getSetting("password", "");
-
- if (!_ownCloudURL || !_username || !_password) {
- pageStack.push( Qt.resolvedUrl("pages/SettingsPage.qml") )
- } else {
- pageStack.push( Qt.resolvedUrl("pages/FeedPage.qml") )
- }
+ console.log("Loading Settings");
+ _ownCloudURL = Helper.getSetting("ownCloudURL", "");
+ _username = Helper.getSetting("username", "");
+ _password = Helper.getSetting("password", "");
+
+ NewsInterface.serverPath = _ownCloudURL;
+ NewsInterface.username = _username;
+ NewsInterface.password = _password;
+
+ if (!_ownCloudURL || !_username || !_password) {
+ pageStack.push(Qt.resolvedUrl("pages/SettingsPage.qml"), {
+ initial: true
+ })
+ } else {
+ pageStack.push(Qt.resolvedUrl("pages/FeedPage.qml"))
+ }
}
- pageStack.popHiddenPages: true
- property string _ownCloudURL: ""
- property string _username: ""
- property string _password: ""
-
function timeDifference(current, previous) {
- var msPerMinute = 60 * 1000;
- var msPerHour = msPerMinute * 60;
- var msPerDay = msPerHour * 24;
- var msPerMonth = msPerDay * 30;
- var msPerYear = msPerDay * 365;
+ const msPerMinute = 60 * 1000;
+ const msPerHour = msPerMinute * 60;
+ const msPerDay = msPerHour * 24;
+ const msPerMonth = msPerDay * 30;
+ const msPerYear = msPerDay * 365;
- var elapsed = current - previous;
+ const elapsed = current - previous;
if (elapsed < msPerMinute) {
- return Math.round(elapsed/1000) + ' seconds ago';
+ return i18n("%1 seconds ago", Math.round(elapsed/1000));
}
else if (elapsed < msPerHour) {
- return Math.round(elapsed/msPerMinute) + ' minutes ago';
+ return i18n("%1 minutes ago", Math.round(elapsed/msPerMinute));
}
else if (elapsed < msPerDay ) {
- return Math.round(elapsed/msPerHour ) + ' hours ago';
+ return i18n("%1 hours ago", Math.round(elapsed/msPerHour));
}
else if (elapsed < msPerMonth) {
- return 'approximately ' + Math.round(elapsed/msPerDay) + ' days ago';
+ return i18n("Approximately %1 days ago", Math.round(elapsed / msPerDay));
}
else if (elapsed < msPerYear) {
- return 'approximately ' + Math.round(elapsed/msPerMonth) + ' months ago';
+ return i18n("Approximately %1 months ago", Math.round(elapsed / msPerMonth));
}
else {
- return 'approximately ' + Math.round(elapsed/msPerYear ) + ' years ago';
+ return i18n("Approximately %1 years ago", Math.round(elapsed / msPerYear));
}
}
}
|
[-]
[+]
|
Changed |
_service:tar_git:newsFish-0.5.0.tar.bz2/src/qml/pages/FeedPage.qml
^
|
@@ -5,24 +5,23 @@
Kirigami.ScrollablePage {
id: feedpage
- title: "Feeds"
+ title: i18n("Feeds")
actions.main: Kirigami.Action {
- id: addAction
- // Name of icon associated with the action
+ id: refreshAction
icon.name: "view-refresh"
- // Action text, i18n function returns translated string
- text: "Sync"
- // What to do when triggering the action
- onTriggered: NewsInterface.sync(_ownCloudURL, _username, _password, 10)
+ text: i18n("Sync")
+ onTriggered: if (!NewsInterface.busy) {
+ NewsInterface.serverPath = _ownCloudURL;
+ NewsInterface.username = _username;
+ NewsInterface.password = _password;
+ NewsInterface.sync();
+ }
}
- supportsRefreshing: !NewsInterface.busy
- onRefreshingChanged: {
- if (refreshing) {
- NewsInterface.sync(_ownCloudURL, _username, _password, 10)
- }
- }
+ onRefreshingChanged: if (feedpage.refreshing) {
+ refreshAction.trigger();
+ }
ListView {
id: listView
@@ -34,37 +33,42 @@
anchors.centerIn: parent
running: NewsInterface.busy
}
+
+ Kirigami.PlaceholderMessage {
+ anchors.centerIn: parent
+ text: i18n("No feeds found")
+ visible: listView.count === 0 && !NewsInterface.busy
+ width: parent.width - Kirigami.Units.gridUnit * 4
+ }
}
Component {
id: feedDelegate
Kirigami.BasicListItem {
+ id: delegate
+
+ required property int index
+ required property string feedId
+ required property string title
+ required property string link
+ required property string faviconLink
+
+ leading: Image {
+ source: delegate.faviconLink
+ width: height
+ }
- onClicked: {
- if (!NewsInterface.busy) {
- console.log("click", feedid);
- NewsInterface.viewItems(feedid);
- var found = false;
- for (var idx = 0; idx < pageStack.depth; ++idx) {
- if (pageStack.get(idx) == itemPage) {
- found = true;
- console.log("Found itemPage in stack");
- break;
- }
- }
-
- if (!found) {
- pageStack.push(itemPage)
- }
- itemPage.feedTitle = feedtitle
- }
+ onClicked: if (!NewsInterface.busy) {
+ NewsInterface.itemsModel.feedId = delegate.feedId;
+ applicationWindow().pageStack.push("qrc:/qml/pages/ItemPage.qml", {
+ title: title,
+ });
}
- label: feedtitle
+ label: title
bold: true
- subtitle: feedurl
- icon: feedicon
+ subtitle: link
}
}
}
|
[-]
[+]
|
Changed |
_service:tar_git:newsFish-0.5.0.tar.bz2/src/qml/pages/ItemPage.qml
^
|
@@ -1,97 +1,76 @@
import QtQuick 2.15
import QtQuick.Controls 2.15 as Controls
+import QtQuick.Layouts 1.15
import org.kde.kirigami 2.20 as Kirigami
import uk.co.piggz 1.0
Kirigami.ScrollablePage {
id: itempage
- property string feedTitle: ""
- title: feedTitle
ListView {
id: listView
model: NewsInterface.itemsModel
- delegate: itemDelegate
- }
-
- Component {
- id: itemDelegate
-
- Kirigami.AbstractListItem {
- id: col
- width: listView.width - (2*Kirigami.Units.largeSpacing)
+ delegate: Kirigami.AbstractListItem {
+ id: delegate
+ required property int index
+ required property string itemid
+ required property string itemtitle
+ required property string itemauthor
+ required property string itemlink
+ required property string itembody
+ required property date itempubdate
+ required property bool itemunread
+ required property bool itemstarred
+
+ separatorVisible: true
+ activeBackgroundColor: Qt.rgba(Kirigami.Theme.highlightColor.r, Kirigami.Theme.highlightColor.g, Kirigami.Theme.highlightColor.b, 0.5)
+ topPadding: Kirigami.Units.largeSpacing
+ bottomPadding: Kirigami.Units.largeSpacing
onClicked: {
- var found = false;
- for (var idx = 0; idx < pageStack.depth; ++idx) {
- if (pageStack.get(idx) === itemView) {
- found = true;
- console.log("Found itemView in stack");
- break;
- }
- }
- if (!found) {
- pageStack.push(itemView)
- }
- itemView.title = itemtitle;
- itemView.body = itembodyhtml;
- itemView.link = itemlink;
- itemView.author = itemauthor;
- itemView.pubdate = timeDifference(new Date(), itempubdate);
- itemView.unread = itemunread;
- itemView.starred = itemstarred;
+ applicationWindow().pageStack.push("qrc:/qml/pages/ItemView.qml", {
+ title: itemtitle,
+ body: itembody,
+ link: itemlink,
+ author: itemauthor,
+ pubdate: timeDifference(new Date(), itempubdate),
+ unread: itemunread,
+ starred: itemstarred,
+ })
NewsInterface.setItemRead(itemid, true);
+
+ ListView.view.currentIndex = index;
+
+ // Hack force navigation to the next page on desktop
+ applicationWindow().pageStack.currentIndex = 1
+ applicationWindow().pageStack.currentIndex = 2
}
- Column {
- id: itm
- spacing: Kirigami.Units.largeSpacing
- width: listView.width - (2* Kirigami.Units.largeSpacing)
- anchors.margins: Kirigami.Units.largeSpacing
- Controls.Label{
- text: itemtitle
- font.bold: true
- width: parent.width
- elide: Text.ElideRight
- }
- Row {
- width: parent.width
+ contentItem: ColumnLayout {
+ spacing: Kirigami.Units.smallSpacing * 2
- Controls.Label {
- text: itemauthor
- width: parent.width / 2
- }
- Controls.Label {
- text: itempubdate
- width: parent.width / 2
- horizontalAlignment: Text.AlignRight
- }
- }
- Text {
- id: txtBody
- text: itembody
+ Controls.Label {
+ Layout.fillWidth: true
+ text: delegate.itemtitle
+ font.pointSize: Math.round(Kirigami.Theme.defaultFont.pointSize * 1)
+ font.bold: true
wrapMode: Text.Wrap
- clip: true
+ elide: Text.ElideRight
maximumLineCount: 3
- width:parent.width
+ opacity: delegate.itemunread ? 1 : 0.7
}
- Rectangle {
- height: 2
- width: parent.width
- x: Kirigami.Units.largeSpacing
- border.color: Kirigami.Theme.activeTextColor
- border.width: 1
+
+ Controls.Label {
+ Layout.fillWidth: true
+ elide: Text.ElideRight
+ font.pointSize: Kirigami.Theme.smallFont.pointSize
+ opacity: 0.9
+ text: delegate.itempubdate.toLocaleString(Qt.locale(), Locale.ShortFormat) + (delegate.itemauthor.length === 0 ? "" : " " + i18nc("by <author(s)>", "by") + " " + delegate.itemauthor)
}
}
}
-
}
}
-
-
-
-
-
|
[-]
[+]
|
Changed |
_service:tar_git:newsFish-0.5.0.tar.bz2/src/qml/pages/ItemView.qml
^
|
@@ -1,95 +1,61 @@
import QtQuick 2.15
+import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15 as Controls
import org.kde.kirigami 2.20 as Kirigami
import uk.co.piggz 1.0
Kirigami.ScrollablePage {
- id: itemView
+ id: root
- property string ititle: ""
- property string body: ""
- property string link: ""
- property string author: ""
- property string pubdate: ""
- property bool unread: false
- property bool starred: false
-
- title: ititle
-
- background: Rectangle {
- color: Kirigami.Theme.backgroundColor
- anchors.fill: parent
- }
+ required property string body
+ required property string link
+ required property string author
+ required property string pubdate
+ required property bool unread
+ required property bool starred
+
+ Kirigami.Theme.colorSet: Kirigami.Theme.View
+ Kirigami.Theme.inherit: false
actions.main: Kirigami.Action {
id: addAction
- // Name of icon associated with the action
- icon.name: "applications-internet"
- // Action text, i18n function returns translated string
- text: "Open in Browser"
- // What to do when triggering the action
+ icon.name: "globe"
+ text: i18n("Open in Browser")
onTriggered: Qt.openUrlExternally(link)
}
+ ColumnLayout {
+ Kirigami.Heading {
+ text: root.author
+ wrapMode: Text.WordWrap
+ Layout.fillWidth: true
+ type: Kirigami.Heading.Primary
+ visible: text.length > 0
+ }
- Column {
- id:column
- width: parent.width
-
- Item {
- id: authorRow
- anchors.left: parent.left
- anchors.right: parent.right
-
- height: childrenRect.height
- anchors.margins: 5
- Controls.Label {
- id: txtAuthor
- text: author
- anchors.left: parent.left
- width: parent.width / 2
- clip: true
- wrapMode: Text.WordWrap
- font.bold: true
- }
-
- Controls.Label {
- id: txtPubDate
- text: pubdate
- anchors.right: parent.right
- width: parent.width / 2
- clip: true
- wrapMode: Text.WordWrap
- horizontalAlignment: Text.AlignRight
- }
+ Kirigami.Heading {
+ text: root.pubdate
+ wrapMode: Text.WordWrap
+ opacity: 0.8
+ level: 3
+ Layout.fillWidth: true
+ visible: text.length > 0
}
Controls.Label {
+ text: Helper.adjustedContent(width, font.pixelSize, root.body)
- id: txtBody
- text: "<html>" + strip_tags(body, "<a><b><p><strong><em><i>") + "</html>"
+ onWidthChanged: text = Helper.adjustedContent(width, font.pixelSize, root.body)
textFormat: Text.RichText
- font.pointSize: 12
- wrapMode: Text.Wrap
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.margins: 5
-
- onLinkActivated: {
- console.log(link, ".activated");
- Qt.openUrlExternally(link);
- }
-
- function strip_tags (input, allowed) {
- allowed = (((allowed || "") + "").toLowerCase().match(/<[a-z][a-z0-9]*>/g) || []).join(''); // making sure the allowed arg is a string containing only tags in lowercase (<a><b><c>)
- var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi,
- commentsAndPhpTags = /<!--[\s\S]*?-->|<\?(?:php)?[\s\S]*?\?>/gi;
- return input.replace(commentsAndPhpTags, '').replace(tags, function ($0, $1) {
- return allowed.indexOf('<' + $1.toLowerCase() + '>') > -1 ? $0 : '';
- });
- }
+ font.pixelSize: Kirigami.Theme.defaultFont.pixelSize + 2
+ wrapMode: Text.WordWrap
+
+ leftPadding: 0
+ rightPadding: 0
+
+ Layout.fillWidth: true
+
+ onLinkActivated: Qt.openUrlExternally(link);
}
}
-
}
-
|
[-]
[+]
|
Changed |
_service:tar_git:newsFish-0.5.0.tar.bz2/src/qml/pages/SettingsPage.qml
^
|
@@ -11,6 +11,9 @@
Kirigami.ScrollablePage {
id: page
+
+ property bool initial: false
+
title: i18n("News Fish for Nextcloud")
leftPadding: 0
@@ -65,7 +68,11 @@
saveSettings();
- pageStack.replace(Qt.resolvedUrl("FeedPage.qml"))
+ if (page.initial) {
+ applicationWindow().pageStack.replace(Qt.resolvedUrl("FeedPage.qml"))
+ } else {
+ page.closeDialog();
+ }
}
}
}
|