Merge branch 'master' of bitbucket.org:skunkos/rssguard
This commit is contained in:
commit
a49fd801d9
@ -279,8 +279,6 @@ set(APP_SOURCES
|
||||
src/gui/shortcutcatcher.cpp
|
||||
src/gui/shortcutbutton.cpp
|
||||
src/gui/dynamicshortcutswidget.cpp
|
||||
src/gui/webbrowser.cpp
|
||||
src/gui/webview.cpp
|
||||
src/gui/baselineedit.cpp
|
||||
src/gui/locationlineedit.cpp
|
||||
src/gui/tabwidget.cpp
|
||||
@ -307,10 +305,6 @@ set(APP_SOURCES
|
||||
src/core/systemfactory.cpp
|
||||
src/core/localization.cpp
|
||||
src/core/dynamicshortcuts.cpp
|
||||
src/core/basenetworkaccessmanager.cpp
|
||||
src/core/webpage.cpp
|
||||
src/core/webbrowsernetworkaccessmanager.cpp
|
||||
src/core/silentnetworkaccessmanager.cpp
|
||||
src/core/textfactory.cpp
|
||||
src/core/databasefactory.cpp
|
||||
src/core/messagesmodel.cpp
|
||||
@ -320,14 +314,20 @@ set(APP_SOURCES
|
||||
src/core/feedsmodelcategory.cpp
|
||||
src/core/feedsmodelrootitem.cpp
|
||||
src/core/feedsmodelfeed.cpp
|
||||
src/core/feedsmodelstandardcategory.cpp
|
||||
src/core/feedsmodelstandardfeed.cpp
|
||||
src/core/parsingfactory.cpp
|
||||
src/core/feeddownloader.cpp
|
||||
src/core/networkfactory.cpp
|
||||
src/core/webfactory.cpp
|
||||
|
||||
# Basic application sources.
|
||||
# NETWORK-WEB sources.
|
||||
src/network-web/basenetworkaccessmanager.cpp
|
||||
src/network-web/webpage.cpp
|
||||
src/network-web/webbrowsernetworkaccessmanager.cpp
|
||||
src/network-web/silentnetworkaccessmanager.cpp
|
||||
src/network-web/networkfactory.cpp
|
||||
src/network-web/webfactory.cpp
|
||||
src/network-web/webbrowser.cpp
|
||||
src/network-web/webview.cpp
|
||||
|
||||
# MAIN sources.
|
||||
src/main.cpp
|
||||
)
|
||||
|
||||
@ -349,8 +349,6 @@ set(APP_HEADERS
|
||||
src/gui/shortcutcatcher.h
|
||||
src/gui/shortcutbutton.h
|
||||
src/gui/dynamicshortcutswidget.h
|
||||
src/gui/webbrowser.h
|
||||
src/gui/webview.h
|
||||
src/gui/baselineedit.h
|
||||
src/gui/locationlineedit.h
|
||||
src/gui/tabwidget.h
|
||||
@ -373,10 +371,7 @@ set(APP_HEADERS
|
||||
# CORE headers.
|
||||
src/core/settings.h
|
||||
src/core/localization.h
|
||||
src/core/basenetworkaccessmanager.h
|
||||
src/core/webbrowsernetworkaccessmanager.h
|
||||
src/core/silentnetworkaccessmanager.h
|
||||
src/core/webpage.h
|
||||
src/network-web/webpage.h
|
||||
src/core/systemfactory.h
|
||||
src/core/databasefactory.h
|
||||
src/core/messagesmodel.h
|
||||
@ -384,7 +379,14 @@ set(APP_HEADERS
|
||||
src/core/feedsmodel.h
|
||||
src/core/feedsproxymodel.h
|
||||
src/core/feeddownloader.h
|
||||
src/core/webfactory.h
|
||||
|
||||
# NETWORK-WEB headers.
|
||||
src/network-web/basenetworkaccessmanager.h
|
||||
src/network-web/webbrowsernetworkaccessmanager.h
|
||||
src/network-web/silentnetworkaccessmanager.h
|
||||
src/network-web/webfactory.h
|
||||
src/network-web/webbrowser.h
|
||||
src/network-web/webview.h
|
||||
)
|
||||
|
||||
# Add form files.
|
||||
@ -454,6 +456,7 @@ endif(${USE_QT_5})
|
||||
include_directories (
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/gui
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/network-web
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/src
|
||||
)
|
||||
|
@ -5,6 +5,7 @@ Fixed:
|
||||
<ul>
|
||||
<li>Informative buttons now do not accept focus.</li>
|
||||
<li>Button for resetting keyboard shortcut now works.</li>
|
||||
<li>Fixed web browser tab title/icon handling (bug #39).</li>
|
||||
</ul>
|
||||
|
||||
Added:
|
||||
@ -19,6 +20,7 @@ Added:
|
||||
|
||||
Changed:
|
||||
<ul>
|
||||
<li>Massive code cleanups.</li>
|
||||
<li>Removed "progress bar" from address text edit of web browser.</li>
|
||||
<li>Removed "blau" skin due to its slowness.</li>
|
||||
<li>Tab order and default widget changed for category/feed add/edit dialogs.</li>
|
||||
|
@ -19,8 +19,8 @@
|
||||
|
||||
#include "core/defs.h"
|
||||
#include "core/databasefactory.h"
|
||||
#include "core/feedsmodelstandardcategory.h"
|
||||
#include "core/feedsmodelstandardfeed.h"
|
||||
#include "core/feedsmodelcategory.h"
|
||||
#include "core/feedsmodelfeed.h"
|
||||
#include "core/textfactory.h"
|
||||
#include "gui/iconthemefactory.h"
|
||||
#include "gui/iconfactory.h"
|
||||
@ -177,7 +177,7 @@ bool FeedsModel::removeItem(const QModelIndex &index) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FeedsModel::addStandardCategory(FeedsModelStandardCategory *category,
|
||||
bool FeedsModel::addCategory(FeedsModelCategory *category,
|
||||
FeedsModelRootItem *parent) {
|
||||
// Get index of parent item (parent standard category).
|
||||
QModelIndex parent_index = indexForItem(parent);
|
||||
@ -225,8 +225,8 @@ bool FeedsModel::addStandardCategory(FeedsModelStandardCategory *category,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FeedsModel::editStandardCategory(FeedsModelStandardCategory *original_category,
|
||||
FeedsModelStandardCategory *new_category) {
|
||||
bool FeedsModel::editCategory(FeedsModelCategory *original_category,
|
||||
FeedsModelCategory *new_category) {
|
||||
QSqlDatabase database = DatabaseFactory::instance()->connection(objectName(),
|
||||
DatabaseFactory::FromSettings);
|
||||
QSqlQuery query_update_category(database);
|
||||
@ -281,7 +281,7 @@ bool FeedsModel::editStandardCategory(FeedsModelStandardCategory *original_categ
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FeedsModel::addStandardFeed(FeedsModelStandardFeed *feed,
|
||||
bool FeedsModel::addFeed(FeedsModelFeed *feed,
|
||||
FeedsModelRootItem *parent) {
|
||||
// Get index of parent item (parent standard category).
|
||||
QModelIndex parent_index = indexForItem(parent);
|
||||
@ -336,8 +336,8 @@ bool FeedsModel::addStandardFeed(FeedsModelStandardFeed *feed,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FeedsModel::editStandardFeed(FeedsModelStandardFeed *original_feed,
|
||||
FeedsModelStandardFeed *new_feed) {
|
||||
bool FeedsModel::editFeed(FeedsModelFeed *original_feed,
|
||||
FeedsModelFeed *new_feed) {
|
||||
QSqlDatabase database = DatabaseFactory::instance()->connection(objectName(),
|
||||
DatabaseFactory::FromSettings);
|
||||
QSqlQuery query_update_feed(database);
|
||||
@ -413,34 +413,32 @@ QList<FeedsModelFeed*> FeedsModel::feedsForScheduledUpdate(bool auto_update_now)
|
||||
QList<FeedsModelFeed*> feeds_for_update;
|
||||
|
||||
foreach (FeedsModelFeed *feed, allFeeds()) {
|
||||
FeedsModelStandardFeed *std_feed = static_cast<FeedsModelStandardFeed*>(feed);
|
||||
|
||||
switch (std_feed->autoUpdateType()) {
|
||||
case FeedsModelStandardFeed::DontAutoUpdate:
|
||||
switch (feed->autoUpdateType()) {
|
||||
case FeedsModelFeed::DontAutoUpdate:
|
||||
// Do not auto-update this feed ever.
|
||||
continue;
|
||||
|
||||
case FeedsModelStandardFeed::DefaultAutoUpdate:
|
||||
case FeedsModelFeed::DefaultAutoUpdate:
|
||||
if (auto_update_now) {
|
||||
feeds_for_update.append(feed);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case FeedsModelStandardFeed::SpecificAutoUpdate:
|
||||
case FeedsModelFeed::SpecificAutoUpdate:
|
||||
default:
|
||||
int remaining_interval = std_feed->autoUpdateRemainingInterval();
|
||||
int remaining_interval = feed->autoUpdateRemainingInterval();
|
||||
|
||||
if (--remaining_interval <= 0) {
|
||||
// Interval of this feed passed, include this feed in the output list
|
||||
// and reset the interval.
|
||||
feeds_for_update.append(feed);
|
||||
std_feed->setAutoUpdateRemainingInterval(std_feed->autoUpdateInitialInterval());
|
||||
feed->setAutoUpdateRemainingInterval(feed->autoUpdateInitialInterval());
|
||||
}
|
||||
else {
|
||||
// Interval did not pass, set new decremented interval and do NOT
|
||||
// include this feed in the output list.
|
||||
std_feed->setAutoUpdateRemainingInterval(remaining_interval);
|
||||
feed->setAutoUpdateRemainingInterval(remaining_interval);
|
||||
}
|
||||
|
||||
break;
|
||||
@ -613,13 +611,12 @@ void FeedsModel::loadFromDatabase() {
|
||||
case FeedsModelCategory::Standard: {
|
||||
CategoryAssignmentItem pair;
|
||||
pair.first = query_categories.value(CAT_DB_PARENT_ID_INDEX).toInt();
|
||||
pair.second = FeedsModelStandardCategory::loadFromRecord(query_categories.record());
|
||||
pair.second = FeedsModelCategory::loadFromRecord(query_categories.record());
|
||||
|
||||
categories << pair;
|
||||
break;
|
||||
}
|
||||
|
||||
case FeedsModelCategory::Feedly:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -639,13 +636,13 @@ void FeedsModel::loadFromDatabase() {
|
||||
FeedsModelFeed::Type type = static_cast<FeedsModelFeed::Type>(query_feeds.value(FDS_DB_TYPE_INDEX).toInt());
|
||||
|
||||
switch (type) {
|
||||
case FeedsModelFeed::StandardAtom10:
|
||||
case FeedsModelFeed::StandardRdf:
|
||||
case FeedsModelFeed::StandardRss0X:
|
||||
case FeedsModelFeed::StandardRss2X: {
|
||||
case FeedsModelFeed::Atom10:
|
||||
case FeedsModelFeed::Rdf:
|
||||
case FeedsModelFeed::Rss0X:
|
||||
case FeedsModelFeed::Rss2X: {
|
||||
FeedAssignmentItem pair;
|
||||
pair.first = query_feeds.value(FDS_DB_CATEGORY_INDEX).toInt();
|
||||
pair.second = FeedsModelStandardFeed::loadFromRecord(query_feeds.record());
|
||||
pair.second = FeedsModelFeed::loadFromRecord(query_feeds.record());
|
||||
pair.second->setType(type);
|
||||
|
||||
feeds << pair;
|
||||
|
@ -28,8 +28,6 @@
|
||||
|
||||
class FeedsModelCategory;
|
||||
class FeedsModelFeed;
|
||||
class FeedsModelStandardCategory;
|
||||
class FeedsModelStandardFeed;
|
||||
|
||||
typedef QList<QPair<int, FeedsModelCategory*> > CategoryAssignment;
|
||||
typedef QPair<int, FeedsModelCategory*> CategoryAssignmentItem;
|
||||
@ -72,20 +70,20 @@ class FeedsModel : public QAbstractItemModel {
|
||||
bool removeItem(const QModelIndex &index);
|
||||
|
||||
// Standard category manipulators.
|
||||
bool addStandardCategory(FeedsModelStandardCategory *category,
|
||||
FeedsModelRootItem *parent);
|
||||
bool editStandardCategory(FeedsModelStandardCategory *original_category,
|
||||
FeedsModelStandardCategory *new_category);
|
||||
bool addCategory(FeedsModelCategory *category,
|
||||
FeedsModelRootItem *parent);
|
||||
bool editCategory(FeedsModelCategory *original_category,
|
||||
FeedsModelCategory *new_category);
|
||||
|
||||
// Standard feed manipulators.
|
||||
bool addStandardFeed(FeedsModelStandardFeed *feed,
|
||||
FeedsModelRootItem *parent);
|
||||
bool addFeed(FeedsModelFeed *feed,
|
||||
FeedsModelRootItem *parent);
|
||||
|
||||
// New feed is just temporary feed, it is not added to the model.
|
||||
// It is used to fetch its data to the original feed
|
||||
// and the original feed is moved if needed.
|
||||
bool editStandardFeed(FeedsModelStandardFeed *original_feed,
|
||||
FeedsModelStandardFeed *new_feed);
|
||||
bool editFeed(FeedsModelFeed *original_feed,
|
||||
FeedsModelFeed *new_feed);
|
||||
|
||||
// Returns the list of updates which should be updated
|
||||
// according to auto-update schedule.
|
||||
|
@ -17,12 +17,20 @@
|
||||
|
||||
#include "core/feedsmodelcategory.h"
|
||||
|
||||
#include "core/feedsmodelstandardcategory.h"
|
||||
#include "core/feedsmodelstandardfeed.h"
|
||||
#include "core/defs.h"
|
||||
#include "core/databasefactory.h"
|
||||
#include "core/textfactory.h"
|
||||
#include "core/settings.h"
|
||||
#include "gui/iconthemefactory.h"
|
||||
#include "gui/iconfactory.h"
|
||||
|
||||
#include <QVariant>
|
||||
#include <QSqlQuery>
|
||||
|
||||
|
||||
FeedsModelCategory::FeedsModelCategory(FeedsModelRootItem *parent_item)
|
||||
: FeedsModelRootItem(parent_item) {
|
||||
m_type = Standard;
|
||||
m_kind = FeedsModelRootItem::Category;
|
||||
}
|
||||
|
||||
@ -40,4 +48,113 @@ FeedsModelCategory::FeedsModelCategory(const FeedsModelCategory &other)
|
||||
}
|
||||
|
||||
FeedsModelCategory::~FeedsModelCategory() {
|
||||
qDebug("Destroying FeedsModelCategory instance.");
|
||||
}
|
||||
|
||||
QVariant FeedsModelCategory::data(int column, int role) const {
|
||||
switch (role) {
|
||||
case Qt::ToolTipRole:
|
||||
if (column == FDS_MODEL_TITLE_INDEX) {
|
||||
//: Tooltip for standard feed.
|
||||
return tr("%1 (category)\n"
|
||||
"%2%3").arg(m_title,
|
||||
m_description,
|
||||
m_childItems.size() == 0 ?
|
||||
tr("\n\nThis category does not contain any nested items.") :
|
||||
"");
|
||||
}
|
||||
else if (column == FDS_MODEL_COUNTS_INDEX) {
|
||||
//: Tooltip for "unread" column of feed list.
|
||||
return tr("%n unread message(s).", "", countOfUnreadMessages());
|
||||
}
|
||||
else {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
case Qt::EditRole:
|
||||
if (column == FDS_MODEL_TITLE_INDEX) {
|
||||
return m_title;
|
||||
}
|
||||
else if (column == FDS_MODEL_COUNTS_INDEX) {
|
||||
return countOfUnreadMessages();
|
||||
}
|
||||
else {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
case Qt::FontRole:
|
||||
return countOfUnreadMessages() > 0 ? m_boldFont : m_normalFont;
|
||||
|
||||
case Qt::DisplayRole:
|
||||
if (column == FDS_MODEL_TITLE_INDEX) {
|
||||
return m_title;
|
||||
}
|
||||
else if (column == FDS_MODEL_COUNTS_INDEX) {
|
||||
return Settings::instance()->value(APP_CFG_FEEDS,
|
||||
"count_format",
|
||||
"(%unread)").toString()
|
||||
.replace("%unread", QString::number(countOfUnreadMessages()))
|
||||
.replace("%all", QString::number(countOfAllMessages()));
|
||||
}
|
||||
else {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
case Qt::DecorationRole:
|
||||
if (column == FDS_MODEL_TITLE_INDEX) {
|
||||
return m_icon;
|
||||
}
|
||||
else {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
case Qt::TextAlignmentRole:
|
||||
if (column == FDS_MODEL_COUNTS_INDEX) {
|
||||
return Qt::AlignCenter;
|
||||
}
|
||||
else {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
bool FeedsModelCategory::removeItself() {
|
||||
bool result = true;
|
||||
|
||||
// Remove all child items (feeds, categories.)
|
||||
foreach (FeedsModelRootItem *child, m_childItems) {
|
||||
result &= child->removeItself();
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Children are removed, remove this standard category too.
|
||||
QSqlDatabase database = DatabaseFactory::instance()->connection("FeedsModelCategory",
|
||||
DatabaseFactory::FromSettings);
|
||||
QSqlQuery query_remove(database);
|
||||
|
||||
query_remove.setForwardOnly(true);
|
||||
|
||||
// Remove all messages from this standard feed.
|
||||
query_remove.prepare("DELETE FROM Categories WHERE id = :category;");
|
||||
query_remove.bindValue(":category", id());
|
||||
|
||||
return query_remove.exec();
|
||||
}
|
||||
|
||||
FeedsModelCategory *FeedsModelCategory::loadFromRecord(const QSqlRecord &record) {
|
||||
FeedsModelCategory *category = new FeedsModelCategory(NULL);
|
||||
|
||||
category->setId(record.value(CAT_DB_ID_INDEX).toInt());
|
||||
category->setTitle(record.value(CAT_DB_TITLE_INDEX).toString());
|
||||
category->setDescription(record.value(CAT_DB_DESCRIPTION_INDEX).toString());
|
||||
category->setCreationDate(TextFactory::parseDateTime(record.value(CAT_DB_DCREATED_INDEX).value<qint64>()).toLocalTime());
|
||||
category->setIcon(IconFactory::fromByteArray(record.value(CAT_DB_ICON_INDEX).toByteArray()));
|
||||
|
||||
return category;
|
||||
}
|
||||
|
@ -20,6 +20,9 @@
|
||||
|
||||
#include "core/feedsmodelrootitem.h"
|
||||
|
||||
#include <QSqlRecord>
|
||||
#include <QApplication>
|
||||
|
||||
|
||||
class FeedsModelFeed;
|
||||
|
||||
@ -27,12 +30,13 @@ class FeedsModelFeed;
|
||||
// NOTE: This class should be derived to create PARTICULAR category types.
|
||||
// NOTE: This class should not be instantiated directly.
|
||||
class FeedsModelCategory : public FeedsModelRootItem {
|
||||
Q_DECLARE_TR_FUNCTIONS(FeedsModelCategory)
|
||||
|
||||
public:
|
||||
// Describes possible types of categories.
|
||||
// NOTE: This is equivavelnt to Categories(type).
|
||||
enum Type {
|
||||
Standard = 0,
|
||||
Feedly = 1
|
||||
Standard = 0
|
||||
};
|
||||
|
||||
// Constructors and destructors
|
||||
@ -40,6 +44,13 @@ class FeedsModelCategory : public FeedsModelRootItem {
|
||||
explicit FeedsModelCategory(const FeedsModelCategory &other);
|
||||
virtual ~FeedsModelCategory();
|
||||
|
||||
// Returns the actual data representation of standard category.
|
||||
QVariant data(int column, int role) const;
|
||||
|
||||
// Removes category and all its children from persistent
|
||||
// database.
|
||||
bool removeItself();
|
||||
|
||||
// All types of categories offer these getters/setters.
|
||||
inline Type type() const {
|
||||
return m_type;
|
||||
@ -49,6 +60,9 @@ class FeedsModelCategory : public FeedsModelRootItem {
|
||||
m_type = type;
|
||||
}
|
||||
|
||||
// Loads particular "standard category" from given sql record.
|
||||
static FeedsModelCategory *loadFromRecord(const QSqlRecord &record);
|
||||
|
||||
protected:
|
||||
Type m_type;
|
||||
};
|
||||
|
@ -17,23 +17,38 @@
|
||||
|
||||
#include "core/feedsmodelfeed.h"
|
||||
|
||||
#include "core/defs.h"
|
||||
#include "core/settings.h"
|
||||
#include "core/parsingfactory.h"
|
||||
#include "core/databasefactory.h"
|
||||
#include "core/textfactory.h"
|
||||
#include "network-web/networkfactory.h"
|
||||
#include "gui/iconfactory.h"
|
||||
#include "gui/iconthemefactory.h"
|
||||
|
||||
#include <QSqlDatabase>
|
||||
#include <QSqlQuery>
|
||||
#include <QSqlError>
|
||||
#include <QVariant>
|
||||
#include <QTextCodec>
|
||||
#include <QDomDocument>
|
||||
#include <QDomNode>
|
||||
#include <QDomElement>
|
||||
#include <QXmlStreamReader>
|
||||
|
||||
|
||||
FeedsModelFeed::FeedsModelFeed(FeedsModelRootItem *parent_item)
|
||||
: FeedsModelRootItem(parent_item),
|
||||
m_type(StandardRss0X),
|
||||
m_type(Rss0X),
|
||||
m_totalCount(0),
|
||||
m_unreadCount(0) {
|
||||
m_unreadCount(0),
|
||||
m_autoUpdateType(DontAutoUpdate),
|
||||
m_autoUpdateInitialInterval(DEFAULT_AUTO_UPDATE_INTERVAL) {
|
||||
m_kind = FeedsModelRootItem::Feed;
|
||||
}
|
||||
|
||||
FeedsModelFeed::~FeedsModelFeed() {
|
||||
qDebug("Destroying FeedsModelFeed instance.");
|
||||
}
|
||||
|
||||
int FeedsModelFeed::childCount() const {
|
||||
@ -51,16 +66,16 @@ int FeedsModelFeed::countOfUnreadMessages() const {
|
||||
|
||||
QString FeedsModelFeed::typeToString(FeedsModelFeed::Type type) {
|
||||
switch (type) {
|
||||
case StandardAtom10:
|
||||
case Atom10:
|
||||
return "ATOM 1.0";
|
||||
|
||||
case StandardRdf:
|
||||
return "RDF";
|
||||
case Rdf:
|
||||
return "RDF (RSS 1.0)";
|
||||
|
||||
case StandardRss0X:
|
||||
case Rss0X:
|
||||
return "RSS 0.91/0.92/0.93";
|
||||
|
||||
case StandardRss2X:
|
||||
case Rss2X:
|
||||
default:
|
||||
return "RSS 2.0/2.0.1";
|
||||
}
|
||||
@ -88,5 +103,384 @@ void FeedsModelFeed::updateCounts(bool including_total_count) {
|
||||
}
|
||||
}
|
||||
|
||||
FeedsModelFeed *FeedsModelFeed::loadFromRecord(const QSqlRecord &record) {
|
||||
FeedsModelFeed *feed = new FeedsModelFeed();
|
||||
|
||||
feed->setTitle(record.value(FDS_DB_TITLE_INDEX).toString());
|
||||
feed->setId(record.value(FDS_DB_ID_INDEX).toInt());
|
||||
feed->setDescription(record.value(FDS_DB_DESCRIPTION_INDEX).toString());
|
||||
feed->setCreationDate(TextFactory::parseDateTime(record.value(FDS_DB_DCREATED_INDEX).value<qint64>()).toLocalTime());
|
||||
feed->setIcon(IconFactory::fromByteArray(record.value(FDS_DB_ICON_INDEX).toByteArray()));
|
||||
feed->setEncoding(record.value(FDS_DB_ENCODING_INDEX).toString());
|
||||
feed->setUrl(record.value(FDS_DB_URL_INDEX).toString());
|
||||
feed->setPasswordProtected(record.value(FDS_DB_PROTECTED_INDEX).toBool());
|
||||
feed->setUsername(record.value(FDS_DB_USERNAME_INDEX).toString());
|
||||
feed->setPassword(record.value(FDS_DB_PASSWORD_INDEX).toString());
|
||||
feed->setAutoUpdateType(static_cast<FeedsModelFeed::AutoUpdateType>(record.value(FDS_DB_UPDATE_TYPE_INDEX).toInt()));
|
||||
feed->setAutoUpdateInitialInterval(record.value(FDS_DB_UPDATE_INTERVAL_INDEX).toInt());
|
||||
feed->updateCounts();
|
||||
|
||||
return feed;
|
||||
}
|
||||
|
||||
QPair<FeedsModelFeed*, QNetworkReply::NetworkError> FeedsModelFeed::guessFeed(const QString &url,
|
||||
const QString &username,
|
||||
const QString &password) {
|
||||
QPair<FeedsModelFeed*, QNetworkReply::NetworkError> result; result.first = NULL;
|
||||
|
||||
// Try to obtain icon.
|
||||
QIcon icon_data;
|
||||
|
||||
if ((result.second = NetworkFactory::downloadIcon(url, 5000, icon_data)) ==
|
||||
QNetworkReply::NoError) {
|
||||
// Icon for feed was downloaded and is stored now in _icon_data.
|
||||
result.first = new FeedsModelFeed();
|
||||
result.first->setIcon(icon_data);
|
||||
}
|
||||
|
||||
QByteArray feed_contents;
|
||||
if ((result.second = NetworkFactory::downloadFeedFile(url,
|
||||
Settings::instance()->value(APP_CFG_FEEDS, "feed_update_timeout", DOWNLOAD_TIMEOUT).toInt(),
|
||||
feed_contents,
|
||||
!username.isEmpty(),
|
||||
username,
|
||||
password)) == QNetworkReply::NoError) {
|
||||
// Feed XML was obtained, now we need to try to guess
|
||||
// its encoding before we can read further data.
|
||||
QString xml_schema_encoding;
|
||||
QString xml_contents_encoded;
|
||||
QRegExp encoding_rexp("encoding=\"[^\"]\\S+\"");
|
||||
|
||||
if (encoding_rexp.indexIn(feed_contents) != -1 &&
|
||||
!(xml_schema_encoding = encoding_rexp.cap(0)).isEmpty()) {
|
||||
// Some "encoding" attribute was found get the encoding
|
||||
// out of it.
|
||||
encoding_rexp.setPattern("[^\"]\\S+[^\"]");
|
||||
encoding_rexp.indexIn(xml_schema_encoding, 9);
|
||||
xml_schema_encoding = encoding_rexp.cap(0);
|
||||
}
|
||||
|
||||
if (result.first == NULL) {
|
||||
result.first = new FeedsModelFeed();
|
||||
}
|
||||
|
||||
QTextCodec *custom_codec = QTextCodec::codecForName(xml_schema_encoding.toLocal8Bit());
|
||||
|
||||
if (custom_codec != NULL) {
|
||||
// Feed encoding was probably guessed.
|
||||
xml_contents_encoded = custom_codec->toUnicode(feed_contents);
|
||||
result.first->setEncoding(xml_schema_encoding);
|
||||
}
|
||||
else {
|
||||
// Feed encoding probably not guessed, set it as
|
||||
// default.
|
||||
xml_contents_encoded = feed_contents;
|
||||
result.first->setEncoding(DEFAULT_FEED_ENCODING);
|
||||
}
|
||||
|
||||
// Feed XML was obtained, guess it now.
|
||||
QDomDocument xml_document;
|
||||
QString error_msg;
|
||||
int error_line, error_column;
|
||||
|
||||
if (!xml_document.setContent(xml_contents_encoded,
|
||||
&error_msg,
|
||||
&error_line,
|
||||
&error_column)) {
|
||||
qDebug("XML of feed '%s' is not valid and cannot be loaded. Error: '%s' "
|
||||
"(line %d, column %d).",
|
||||
qPrintable(url),
|
||||
qPrintable(error_msg),
|
||||
error_line, error_column);
|
||||
|
||||
result.second = QNetworkReply::UnknownContentError;
|
||||
|
||||
// XML is invalid, exit.
|
||||
return result;
|
||||
}
|
||||
|
||||
QDomElement root_element = xml_document.documentElement();
|
||||
QString root_tag_name = root_element.tagName();
|
||||
|
||||
if (root_tag_name == "rdf:RDF") {
|
||||
// We found RDF feed.
|
||||
QDomElement channel_element = root_element.namedItem("channel").toElement();
|
||||
|
||||
result.first->setType(Rdf);
|
||||
result.first->setTitle(channel_element.namedItem("title").toElement().text());
|
||||
result.first->setDescription(channel_element.namedItem("description").toElement().text());
|
||||
}
|
||||
else if (root_tag_name == "rss") {
|
||||
// We found RSS 0.91/0.92/0.93/2.0/2.0.1 feed.
|
||||
QString rss_type = root_element.attribute("version", "2.0");
|
||||
|
||||
if (rss_type == "0.91" || rss_type == "0.92" || rss_type == "0.93") {
|
||||
result.first->setType(Rss0X);
|
||||
}
|
||||
else {
|
||||
result.first->setType(Rss2X);
|
||||
}
|
||||
|
||||
QDomElement channel_element = root_element.namedItem("channel").toElement();
|
||||
|
||||
result.first->setTitle(channel_element.namedItem("title").toElement().text());
|
||||
result.first->setDescription(channel_element.namedItem("description").toElement().text());
|
||||
}
|
||||
else if (root_tag_name == "feed") {
|
||||
// We found ATOM feed.
|
||||
result.first->setType(Atom10);
|
||||
result.first->setTitle(root_element.namedItem("title").toElement().text());
|
||||
result.first->setDescription(root_element.namedItem("subtitle").toElement().text());
|
||||
}
|
||||
else {
|
||||
// File was downloaded and it really was XML file
|
||||
// but feed format was NOT recognized.
|
||||
result.second = QNetworkReply::UnknownContentError;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QVariant FeedsModelFeed::data(int column, int role) const {
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
if (column == FDS_MODEL_TITLE_INDEX) {
|
||||
return m_title;
|
||||
}
|
||||
else if (column == FDS_MODEL_COUNTS_INDEX) {
|
||||
return Settings::instance()->value(APP_CFG_FEEDS,
|
||||
"count_format",
|
||||
"(%unread)").toString()
|
||||
.replace("%unread", QString::number(countOfUnreadMessages()))
|
||||
.replace("%all", QString::number(countOfAllMessages()));
|
||||
}
|
||||
else {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
case Qt::EditRole:
|
||||
if (column == FDS_MODEL_TITLE_INDEX) {
|
||||
return m_title;
|
||||
}
|
||||
else if (column == FDS_MODEL_COUNTS_INDEX) {
|
||||
return countOfUnreadMessages();
|
||||
}
|
||||
else {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
case Qt::DecorationRole:
|
||||
if (column == FDS_MODEL_TITLE_INDEX) {
|
||||
return m_icon;
|
||||
}
|
||||
else {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
case Qt::ToolTipRole:
|
||||
if (column == FDS_MODEL_TITLE_INDEX) {
|
||||
QString auto_update_string;
|
||||
|
||||
switch (m_autoUpdateType) {
|
||||
case DontAutoUpdate:
|
||||
//: Describes feed auto-update status.
|
||||
auto_update_string = tr("does not use auto-update");
|
||||
break;
|
||||
|
||||
case DefaultAutoUpdate:
|
||||
//: Describes feed auto-update status.
|
||||
auto_update_string = tr("uses global settings");
|
||||
break;
|
||||
|
||||
case SpecificAutoUpdate:
|
||||
default:
|
||||
//: Describes feed auto-update status.
|
||||
auto_update_string = tr("uses specific settings "
|
||||
"(%n minute(s) to next auto-update)",
|
||||
0,
|
||||
m_autoUpdateRemainingInterval);
|
||||
break;
|
||||
}
|
||||
|
||||
//: Tooltip for feed.
|
||||
return tr("%1 (%2)\n"
|
||||
"%3\n\n"
|
||||
"Encoding: %4\n"
|
||||
"Auto-update status: %5").arg(m_title,
|
||||
FeedsModelFeed::typeToString(m_type),
|
||||
m_description,
|
||||
m_encoding,
|
||||
auto_update_string);
|
||||
}
|
||||
else if (column == FDS_MODEL_COUNTS_INDEX) {
|
||||
//: Tooltip for "unread" column of feed list.
|
||||
return tr("%n unread message(s).", 0, countOfUnreadMessages());
|
||||
}
|
||||
else {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
case Qt::TextAlignmentRole:
|
||||
if (column == FDS_MODEL_COUNTS_INDEX) {
|
||||
return Qt::AlignCenter;
|
||||
}
|
||||
else {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
case Qt::FontRole:
|
||||
return countOfUnreadMessages() > 0 ? m_boldFont : m_normalFont;
|
||||
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
void FeedsModelFeed::update() {
|
||||
QByteArray feed_contents;
|
||||
int download_timeout = Settings::instance()->value(APP_CFG_FEEDS, "feed_update_timeout", DOWNLOAD_TIMEOUT).toInt();
|
||||
QNetworkReply::NetworkError download_result = NetworkFactory::downloadFeedFile(url(),
|
||||
download_timeout,
|
||||
feed_contents,
|
||||
passwordProtected(),
|
||||
username(),
|
||||
password());
|
||||
|
||||
if (download_result != QNetworkReply::NoError) {
|
||||
qWarning("Error during fetching of new messages for feed '%s' (id %d).",
|
||||
qPrintable(url()),
|
||||
id());
|
||||
return;
|
||||
}
|
||||
|
||||
// Encode downloaded data for further parsing.
|
||||
QTextCodec *codec = QTextCodec::codecForName(encoding().toLocal8Bit());
|
||||
QString formatted_feed_contents;
|
||||
|
||||
if (codec == NULL) {
|
||||
// No suitable codec for this encoding was found.
|
||||
// Use non-converted data.
|
||||
formatted_feed_contents = feed_contents;
|
||||
}
|
||||
else {
|
||||
formatted_feed_contents = codec->toUnicode(feed_contents);
|
||||
}
|
||||
|
||||
// Feed data are downloaded and encoded.
|
||||
// Parse data and obtain messages.
|
||||
QList<Message> messages;
|
||||
|
||||
switch (type()) {
|
||||
case FeedsModelFeed::Rss0X:
|
||||
case FeedsModelFeed::Rss2X:
|
||||
messages = ParsingFactory::parseAsRSS20(formatted_feed_contents);
|
||||
break;
|
||||
|
||||
case FeedsModelFeed::Rdf:
|
||||
messages = ParsingFactory::parseAsRDF(formatted_feed_contents);
|
||||
break;
|
||||
|
||||
case FeedsModelFeed::Atom10:
|
||||
messages = ParsingFactory::parseAsATOM10(formatted_feed_contents);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
updateMessages(messages);
|
||||
}
|
||||
|
||||
bool FeedsModelFeed::removeItself() {
|
||||
QSqlDatabase database = DatabaseFactory::instance()->connection("FeedsModelFeed",
|
||||
DatabaseFactory::FromSettings);
|
||||
QSqlQuery query_remove(database);
|
||||
|
||||
query_remove.setForwardOnly(true);
|
||||
|
||||
// Remove all messages from this standard feed.
|
||||
query_remove.prepare("DELETE FROM Messages WHERE feed = :feed;");
|
||||
query_remove.bindValue(":feed", id());
|
||||
|
||||
if (!query_remove.exec()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove feed itself.
|
||||
query_remove.prepare("DELETE FROM Feeds WHERE id = :feed;");
|
||||
query_remove.bindValue(":feed", id());
|
||||
|
||||
return query_remove.exec();
|
||||
}
|
||||
|
||||
void FeedsModelFeed::updateMessages(const QList<Message> &messages) {
|
||||
int feed_id = id();
|
||||
QSqlDatabase database = DatabaseFactory::instance()->connection("FeedsModelFeed",
|
||||
DatabaseFactory::FromSettings);
|
||||
|
||||
// Prepare queries.
|
||||
QSqlQuery query_select(database);
|
||||
QSqlQuery query_insert(database);
|
||||
|
||||
// Used to check if give feed contains with message with given
|
||||
// title, url and date_created.
|
||||
// WARNING: One feed CANNOT contain two (or more) messages with same
|
||||
// AUTHOR AND TITLE AND URL AND DATE_CREATED.
|
||||
query_select.setForwardOnly(true);
|
||||
query_select.prepare("SELECT id, feed, date_created FROM Messages "
|
||||
"WHERE feed = :feed AND title = :title AND url = :url AND author = :author;");
|
||||
|
||||
// Used to insert new messages.
|
||||
query_insert.setForwardOnly(true);
|
||||
query_insert.prepare("INSERT INTO Messages "
|
||||
"(feed, title, url, author, date_created, contents) "
|
||||
"VALUES (:feed, :title, :url, :author, :date_created, :contents);");
|
||||
|
||||
if (!database.transaction()) {
|
||||
database.rollback();
|
||||
|
||||
qDebug("Transaction start for message downloader failed.");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (const Message &message, messages) {
|
||||
query_select.bindValue(":feed", feed_id);
|
||||
query_select.bindValue(":title", message.m_title);
|
||||
query_select.bindValue(":url", message.m_url);
|
||||
query_select.bindValue(":author", message.m_author);
|
||||
query_select.exec();
|
||||
|
||||
QList<qint64> datetime_stamps;
|
||||
|
||||
while (query_select.next()) {
|
||||
datetime_stamps << query_select.value(2).value<qint64>();
|
||||
}
|
||||
|
||||
query_select.finish();
|
||||
|
||||
if (datetime_stamps.size() == 0 ||
|
||||
(message.m_createdFromFeed &&
|
||||
!datetime_stamps.contains(message.m_created.toMSecsSinceEpoch()))) {
|
||||
// Message is not fetched in this feed yet
|
||||
// or it is. If it is, then go
|
||||
// through datetime stamps of stored messages
|
||||
// and check if new (not auto-generated timestamp
|
||||
// is among them and add this message if it is not.
|
||||
query_insert.bindValue(":feed", feed_id);
|
||||
query_insert.bindValue(":title", message.m_title);
|
||||
query_insert.bindValue(":url", message.m_url);
|
||||
query_insert.bindValue(":author", message.m_author);
|
||||
query_insert.bindValue(":date_created", message.m_created.toMSecsSinceEpoch());
|
||||
query_insert.bindValue(":contents", message.m_contents);
|
||||
|
||||
query_insert.exec();
|
||||
query_insert.finish();
|
||||
}
|
||||
}
|
||||
|
||||
if (!database.commit()) {
|
||||
database.rollback();
|
||||
|
||||
qDebug("Transaction commit for message downloader failed.");
|
||||
}
|
||||
}
|
||||
|
@ -21,19 +21,36 @@
|
||||
#include "core/feedsmodelrootitem.h"
|
||||
|
||||
#include <QMetaType>
|
||||
#include <QDateTime>
|
||||
#include <QSqlRecord>
|
||||
#include <QPair>
|
||||
#include <QNetworkReply>
|
||||
#include <QApplication>
|
||||
|
||||
|
||||
class Message;
|
||||
|
||||
|
||||
// Represents BASE class for feeds contained in FeedsModel.
|
||||
// NOTE: This class should be derived to create PARTICULAR feed types.
|
||||
class FeedsModelFeed : public FeedsModelRootItem {
|
||||
Q_DECLARE_TR_FUNCTIONS(FeedsModelFeed)
|
||||
|
||||
public:
|
||||
// Describes possible types of feeds.
|
||||
// NOTE: This is equivalent to attribute Feeds(type).
|
||||
enum Type {
|
||||
StandardRss0X = 0,
|
||||
StandardRss2X = 1,
|
||||
StandardRdf = 2,
|
||||
StandardAtom10 = 3
|
||||
Rss0X = 0,
|
||||
Rss2X = 1,
|
||||
Rdf = 2,
|
||||
Atom10 = 3
|
||||
};
|
||||
|
||||
// Specifies the auto-update strategy for the feed.
|
||||
enum AutoUpdateType {
|
||||
DontAutoUpdate = 0,
|
||||
DefaultAutoUpdate = 1,
|
||||
SpecificAutoUpdate = 2
|
||||
};
|
||||
|
||||
// Constructors and destructors.
|
||||
@ -49,12 +66,15 @@ class FeedsModelFeed : public FeedsModelRootItem {
|
||||
int countOfAllMessages() const;
|
||||
int countOfUnreadMessages() const;
|
||||
|
||||
// Each feed can be "updated".
|
||||
// NOTE: This method is used in the "update worker".
|
||||
// For example, it can fetch new messages from a remote destination
|
||||
// and store them in a local database and so on.
|
||||
virtual void update() {
|
||||
}
|
||||
// Obtains data related to this feed.
|
||||
QVariant data(int column, int role) const;
|
||||
|
||||
// Perform fetching of new messages.
|
||||
void update();
|
||||
|
||||
// Removes this standard feed from persistent
|
||||
// storage.
|
||||
bool removeItself();
|
||||
|
||||
// Other getters/setters.
|
||||
inline Type type() const {
|
||||
@ -89,6 +109,61 @@ class FeedsModelFeed : public FeedsModelRootItem {
|
||||
m_password = password;
|
||||
}
|
||||
|
||||
inline QString encoding() const {
|
||||
return m_encoding;
|
||||
}
|
||||
|
||||
inline void setEncoding(const QString &encoding) {
|
||||
m_encoding = encoding;
|
||||
}
|
||||
|
||||
inline QString url() const {
|
||||
return m_url;
|
||||
}
|
||||
|
||||
inline void setUrl(const QString &url) {
|
||||
m_url = url;
|
||||
}
|
||||
|
||||
inline int autoUpdateInitialInterval() const {
|
||||
return m_autoUpdateInitialInterval;
|
||||
}
|
||||
|
||||
inline void setAutoUpdateInitialInterval(int auto_update_interval) {
|
||||
// If new initial auto-update interval is set, then
|
||||
// we should reset time that remains to the next auto-update.
|
||||
m_autoUpdateInitialInterval = auto_update_interval;
|
||||
m_autoUpdateRemainingInterval = auto_update_interval;
|
||||
}
|
||||
|
||||
inline AutoUpdateType autoUpdateType() const {
|
||||
return m_autoUpdateType;
|
||||
}
|
||||
|
||||
inline void setAutoUpdateType(const AutoUpdateType &autoUpdateType) {
|
||||
m_autoUpdateType = autoUpdateType;
|
||||
}
|
||||
|
||||
inline int autoUpdateRemainingInterval() const {
|
||||
return m_autoUpdateRemainingInterval;
|
||||
}
|
||||
|
||||
inline void setAutoUpdateRemainingInterval(int autoUpdateRemainingInterval) {
|
||||
m_autoUpdateRemainingInterval = autoUpdateRemainingInterval;
|
||||
}
|
||||
|
||||
// Loads standard feed object from given SQL record.
|
||||
static FeedsModelFeed *loadFromRecord(const QSqlRecord &record);
|
||||
|
||||
// Tries to guess feed hidden under given URL
|
||||
// and uses given credentials.
|
||||
// Returns pointer to guessed feed (if at least partially
|
||||
// guessed) and retrieved error/status code from network layer
|
||||
// or NULL feed.
|
||||
static QPair<FeedsModelFeed*, QNetworkReply::NetworkError> guessFeed(const QString &url,
|
||||
const QString &username,
|
||||
const QString &password);
|
||||
|
||||
// Converts particular feed type to string.
|
||||
static QString typeToString(Type type);
|
||||
|
||||
@ -97,6 +172,12 @@ class FeedsModelFeed : public FeedsModelRootItem {
|
||||
void updateCounts(bool including_total_count = true);
|
||||
|
||||
protected:
|
||||
// Persistently stores given messages into the database
|
||||
// and updates existing messages if newer version is
|
||||
// available.
|
||||
void updateMessages(const QList<Message> &messages);
|
||||
|
||||
private:
|
||||
bool m_passwordProtected;
|
||||
QString m_username;
|
||||
QString m_password;
|
||||
@ -104,6 +185,13 @@ class FeedsModelFeed : public FeedsModelRootItem {
|
||||
Type m_type;
|
||||
int m_totalCount;
|
||||
int m_unreadCount;
|
||||
|
||||
AutoUpdateType m_autoUpdateType;
|
||||
int m_autoUpdateInitialInterval;
|
||||
int m_autoUpdateRemainingInterval;
|
||||
|
||||
QString m_encoding;
|
||||
QString m_url;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(FeedsModelFeed::Type)
|
||||
|
@ -1,146 +0,0 @@
|
||||
// This file is part of RSS Guard.
|
||||
//
|
||||
// Copyright (C) 2011-2014 by Martin Rotter <rotter.martinos@gmail.com>
|
||||
//
|
||||
// RSS Guard 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 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// RSS Guard 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 RSS Guard. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "core/feedsmodelstandardcategory.h"
|
||||
|
||||
#include "core/defs.h"
|
||||
#include "core/databasefactory.h"
|
||||
#include "core/textfactory.h"
|
||||
#include "core/settings.h"
|
||||
#include "gui/iconthemefactory.h"
|
||||
#include "gui/iconfactory.h"
|
||||
|
||||
#include <QVariant>
|
||||
#include <QSqlQuery>
|
||||
|
||||
|
||||
FeedsModelStandardCategory::FeedsModelStandardCategory(FeedsModelRootItem *parent_item)
|
||||
: FeedsModelCategory(parent_item) {
|
||||
m_type = Standard;
|
||||
}
|
||||
|
||||
FeedsModelStandardCategory::~FeedsModelStandardCategory() {
|
||||
qDebug("Destroying FeedsModelStandardCategory instance.");
|
||||
}
|
||||
|
||||
QVariant FeedsModelStandardCategory::data(int column, int role) const {
|
||||
switch (role) {
|
||||
case Qt::ToolTipRole:
|
||||
if (column == FDS_MODEL_TITLE_INDEX) {
|
||||
//: Tooltip for standard feed.
|
||||
return tr("%1 (standard category)\n"
|
||||
"%2%3").arg(m_title,
|
||||
m_description,
|
||||
m_childItems.size() == 0 ?
|
||||
tr("\n\nThis category does not contain any nested items.") :
|
||||
"");
|
||||
}
|
||||
else if (column == FDS_MODEL_COUNTS_INDEX) {
|
||||
//: Tooltip for "unread" column of feed list.
|
||||
return tr("%n unread message(s).", "", countOfUnreadMessages());
|
||||
}
|
||||
else {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
case Qt::EditRole:
|
||||
if (column == FDS_MODEL_TITLE_INDEX) {
|
||||
return m_title;
|
||||
}
|
||||
else if (column == FDS_MODEL_COUNTS_INDEX) {
|
||||
return countOfUnreadMessages();
|
||||
}
|
||||
else {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
case Qt::FontRole:
|
||||
return countOfUnreadMessages() > 0 ? m_boldFont : m_normalFont;
|
||||
|
||||
case Qt::DisplayRole:
|
||||
if (column == FDS_MODEL_TITLE_INDEX) {
|
||||
return m_title;
|
||||
}
|
||||
else if (column == FDS_MODEL_COUNTS_INDEX) {
|
||||
return Settings::instance()->value(APP_CFG_FEEDS,
|
||||
"count_format",
|
||||
"(%unread)").toString()
|
||||
.replace("%unread", QString::number(countOfUnreadMessages()))
|
||||
.replace("%all", QString::number(countOfAllMessages()));
|
||||
}
|
||||
else {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
case Qt::DecorationRole:
|
||||
if (column == FDS_MODEL_TITLE_INDEX) {
|
||||
return m_icon;
|
||||
}
|
||||
else {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
case Qt::TextAlignmentRole:
|
||||
if (column == FDS_MODEL_COUNTS_INDEX) {
|
||||
return Qt::AlignCenter;
|
||||
}
|
||||
else {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
bool FeedsModelStandardCategory::removeItself() {
|
||||
bool result = true;
|
||||
|
||||
// Remove all child items (feeds, categories.)
|
||||
foreach (FeedsModelRootItem *child, m_childItems) {
|
||||
result &= child->removeItself();
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Children are removed, remove this standard category too.
|
||||
QSqlDatabase database = DatabaseFactory::instance()->connection("FeedsModelStandardCategory",
|
||||
DatabaseFactory::FromSettings);
|
||||
QSqlQuery query_remove(database);
|
||||
|
||||
query_remove.setForwardOnly(true);
|
||||
|
||||
// Remove all messages from this standard feed.
|
||||
query_remove.prepare("DELETE FROM Categories WHERE id = :category;");
|
||||
query_remove.bindValue(":category", id());
|
||||
|
||||
return query_remove.exec();
|
||||
}
|
||||
|
||||
FeedsModelStandardCategory *FeedsModelStandardCategory::loadFromRecord(const QSqlRecord &record) {
|
||||
FeedsModelStandardCategory *category = new FeedsModelStandardCategory(NULL);
|
||||
|
||||
category->setId(record.value(CAT_DB_ID_INDEX).toInt());
|
||||
category->setTitle(record.value(CAT_DB_TITLE_INDEX).toString());
|
||||
category->setDescription(record.value(CAT_DB_DESCRIPTION_INDEX).toString());
|
||||
category->setCreationDate(TextFactory::parseDateTime(record.value(CAT_DB_DCREATED_INDEX).value<qint64>()).toLocalTime());
|
||||
category->setIcon(IconFactory::fromByteArray(record.value(CAT_DB_ICON_INDEX).toByteArray()));
|
||||
|
||||
return category;
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
// This file is part of RSS Guard.
|
||||
//
|
||||
// Copyright (C) 2011-2014 by Martin Rotter <rotter.martinos@gmail.com>
|
||||
//
|
||||
// RSS Guard 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 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// RSS Guard 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 RSS Guard. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef FEEDSMODELSTANDARDCATEGORY_H
|
||||
#define FEEDSMODELSTANDARDCATEGORY_H
|
||||
|
||||
#include "core/feedsmodelcategory.h"
|
||||
|
||||
#include <QSqlRecord>
|
||||
#include <QDateTime>
|
||||
#include <QApplication>
|
||||
|
||||
|
||||
// Represents STANDARD category container.
|
||||
// Standard category container can contain:
|
||||
// a) other standard category containers,
|
||||
// b) standard feeds,
|
||||
// c) other containers and feeds (synchronized ones).
|
||||
class FeedsModelStandardCategory : public FeedsModelCategory {
|
||||
Q_DECLARE_TR_FUNCTIONS(FeedsModelStandardCategory)
|
||||
|
||||
public:
|
||||
// Constructors and destructors.
|
||||
explicit FeedsModelStandardCategory(FeedsModelRootItem *parent_item = NULL);
|
||||
virtual ~FeedsModelStandardCategory();
|
||||
|
||||
// Returns the actual data representation of standard category.
|
||||
QVariant data(int column, int role) const;
|
||||
|
||||
// Removes category and all its children from persistent
|
||||
// database.
|
||||
bool removeItself();
|
||||
|
||||
// Loads particular "standard category" from given sql record.
|
||||
static FeedsModelStandardCategory *loadFromRecord(const QSqlRecord &record);
|
||||
};
|
||||
|
||||
#endif // FEEDSMODELSTANDARDCATEGORY_H
|
@ -1,431 +0,0 @@
|
||||
// This file is part of RSS Guard.
|
||||
//
|
||||
// Copyright (C) 2011-2014 by Martin Rotter <rotter.martinos@gmail.com>
|
||||
//
|
||||
// RSS Guard 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 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// RSS Guard 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 RSS Guard. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "core/feedsmodelstandardfeed.h"
|
||||
|
||||
#include "core/defs.h"
|
||||
#include "core/settings.h"
|
||||
#include "core/parsingfactory.h"
|
||||
#include "core/databasefactory.h"
|
||||
#include "core/networkfactory.h"
|
||||
#include "core/textfactory.h"
|
||||
#include "gui/iconfactory.h"
|
||||
#include "gui/iconthemefactory.h"
|
||||
|
||||
#include <QVariant>
|
||||
#include <QTextCodec>
|
||||
#include <QSqlQuery>
|
||||
|
||||
#include <QDomDocument>
|
||||
#include <QDomNode>
|
||||
#include <QDomElement>
|
||||
#include <QXmlStreamReader>
|
||||
|
||||
|
||||
FeedsModelStandardFeed::FeedsModelStandardFeed(FeedsModelRootItem *parent_item)
|
||||
: FeedsModelFeed(parent_item),
|
||||
m_autoUpdateType(DontAutoUpdate),
|
||||
m_autoUpdateInitialInterval(DEFAULT_AUTO_UPDATE_INTERVAL) {
|
||||
}
|
||||
|
||||
FeedsModelStandardFeed::~FeedsModelStandardFeed() {
|
||||
qDebug("Destroying FeedsModelStandardFeed instance.");
|
||||
}
|
||||
|
||||
FeedsModelStandardFeed *FeedsModelStandardFeed::loadFromRecord(const QSqlRecord &record) {
|
||||
FeedsModelStandardFeed *feed = new FeedsModelStandardFeed(NULL);
|
||||
|
||||
feed->setTitle(record.value(FDS_DB_TITLE_INDEX).toString());
|
||||
feed->setId(record.value(FDS_DB_ID_INDEX).toInt());
|
||||
feed->setDescription(record.value(FDS_DB_DESCRIPTION_INDEX).toString());
|
||||
feed->setCreationDate(TextFactory::parseDateTime(record.value(FDS_DB_DCREATED_INDEX).value<qint64>()).toLocalTime());
|
||||
feed->setIcon(IconFactory::fromByteArray(record.value(FDS_DB_ICON_INDEX).toByteArray()));
|
||||
feed->setEncoding(record.value(FDS_DB_ENCODING_INDEX).toString());
|
||||
feed->setUrl(record.value(FDS_DB_URL_INDEX).toString());
|
||||
feed->setPasswordProtected(record.value(FDS_DB_PROTECTED_INDEX).toBool());
|
||||
feed->setUsername(record.value(FDS_DB_USERNAME_INDEX).toString());
|
||||
feed->setPassword(record.value(FDS_DB_PASSWORD_INDEX).toString());
|
||||
feed->setAutoUpdateType(static_cast<FeedsModelStandardFeed::AutoUpdateType>(record.value(FDS_DB_UPDATE_TYPE_INDEX).toInt()));
|
||||
feed->setAutoUpdateInitialInterval(record.value(FDS_DB_UPDATE_INTERVAL_INDEX).toInt());
|
||||
feed->updateCounts();
|
||||
|
||||
return feed;
|
||||
}
|
||||
|
||||
QPair<FeedsModelStandardFeed*, QNetworkReply::NetworkError> FeedsModelStandardFeed::guessFeed(const QString &url,
|
||||
const QString &username,
|
||||
const QString &password) {
|
||||
QPair<FeedsModelStandardFeed*, QNetworkReply::NetworkError> result; result.first = NULL;
|
||||
|
||||
// Try to obtain icon.
|
||||
QIcon icon_data;
|
||||
|
||||
if ((result.second = NetworkFactory::downloadIcon(url,
|
||||
5000,
|
||||
icon_data)) ==
|
||||
QNetworkReply::NoError) {
|
||||
// Icon for feed was downloaded and is stored now in _icon_data.
|
||||
result.first = new FeedsModelStandardFeed();
|
||||
result.first->setIcon(icon_data);
|
||||
}
|
||||
|
||||
QByteArray feed_contents;
|
||||
if ((result.second = NetworkFactory::downloadFeedFile(url,
|
||||
Settings::instance()->value(APP_CFG_FEEDS, "feed_update_timeout", DOWNLOAD_TIMEOUT).toInt(),
|
||||
feed_contents,
|
||||
!username.isEmpty(),
|
||||
username,
|
||||
password)) == QNetworkReply::NoError) {
|
||||
// Feed XML was obtained, now we need to try to guess
|
||||
// its encoding before we can read further data.
|
||||
QString xml_schema_encoding;
|
||||
QString xml_contents_encoded;
|
||||
QRegExp encoding_rexp("encoding=\"[^\"]\\S+\"");
|
||||
|
||||
if (encoding_rexp.indexIn(feed_contents) != -1 &&
|
||||
!(xml_schema_encoding = encoding_rexp.cap(0)).isEmpty()) {
|
||||
// Some "encoding" attribute was found get the encoding
|
||||
// out of it.
|
||||
encoding_rexp.setPattern("[^\"]\\S+[^\"]");
|
||||
encoding_rexp.indexIn(xml_schema_encoding, 9);
|
||||
xml_schema_encoding = encoding_rexp.cap(0);
|
||||
}
|
||||
|
||||
if (result.first == NULL) {
|
||||
result.first = new FeedsModelStandardFeed();
|
||||
}
|
||||
|
||||
QTextCodec *custom_codec = QTextCodec::codecForName(xml_schema_encoding.toLocal8Bit());
|
||||
|
||||
if (custom_codec != NULL) {
|
||||
// Feed encoding was probably guessed.
|
||||
xml_contents_encoded = custom_codec->toUnicode(feed_contents);
|
||||
result.first->setEncoding(xml_schema_encoding);
|
||||
}
|
||||
else {
|
||||
// Feed encoding probably not guessed, set it as
|
||||
// default.
|
||||
xml_contents_encoded = feed_contents;
|
||||
result.first->setEncoding(DEFAULT_FEED_ENCODING);
|
||||
}
|
||||
|
||||
// Feed XML was obtained, guess it now.
|
||||
QDomDocument xml_document;
|
||||
QString error_msg;
|
||||
int error_line, error_column;
|
||||
|
||||
if (!xml_document.setContent(xml_contents_encoded,
|
||||
&error_msg,
|
||||
&error_line,
|
||||
&error_column)) {
|
||||
qDebug("XML of feed '%s' is not valid and cannot be loaded. Error: '%s' "
|
||||
"(line %d, column %d).",
|
||||
qPrintable(url),
|
||||
qPrintable(error_msg),
|
||||
error_line, error_column);
|
||||
|
||||
result.second = QNetworkReply::UnknownContentError;
|
||||
|
||||
// XML is invalid, exit.
|
||||
return result;
|
||||
}
|
||||
|
||||
QDomElement root_element = xml_document.documentElement();
|
||||
QString root_tag_name = root_element.tagName();
|
||||
|
||||
if (root_tag_name == "rdf:RDF") {
|
||||
// We found RDF feed.
|
||||
QDomElement channel_element = root_element.namedItem("channel").toElement();
|
||||
|
||||
result.first->setType(StandardRdf);
|
||||
result.first->setTitle(channel_element.namedItem("title").toElement().text());
|
||||
result.first->setDescription(channel_element.namedItem("description").toElement().text());
|
||||
}
|
||||
else if (root_tag_name == "rss") {
|
||||
// We found RSS 0.91/0.92/0.93/2.0/2.0.1 feed.
|
||||
QString rss_type = root_element.attribute("version", "2.0");
|
||||
|
||||
if (rss_type == "0.91" || rss_type == "0.92" || rss_type == "0.93") {
|
||||
result.first->setType(StandardRss0X);
|
||||
}
|
||||
else {
|
||||
result.first->setType(StandardRss2X);
|
||||
}
|
||||
|
||||
QDomElement channel_element = root_element.namedItem("channel").toElement();
|
||||
|
||||
result.first->setTitle(channel_element.namedItem("title").toElement().text());
|
||||
result.first->setDescription(channel_element.namedItem("description").toElement().text());
|
||||
}
|
||||
else if (root_tag_name == "feed") {
|
||||
// We found ATOM feed.
|
||||
result.first->setType(StandardAtom10);
|
||||
result.first->setTitle(root_element.namedItem("title").toElement().text());
|
||||
result.first->setDescription(root_element.namedItem("subtitle").toElement().text());
|
||||
}
|
||||
else {
|
||||
// File was downloaded and it really was XML file
|
||||
// but feed format was NOT recognized.
|
||||
result.second = QNetworkReply::UnknownContentError;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QVariant FeedsModelStandardFeed::data(int column, int role) const {
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
if (column == FDS_MODEL_TITLE_INDEX) {
|
||||
return m_title;
|
||||
}
|
||||
else if (column == FDS_MODEL_COUNTS_INDEX) {
|
||||
return Settings::instance()->value(APP_CFG_FEEDS,
|
||||
"count_format",
|
||||
"(%unread)").toString()
|
||||
.replace("%unread", QString::number(countOfUnreadMessages()))
|
||||
.replace("%all", QString::number(countOfAllMessages()));
|
||||
}
|
||||
else {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
case Qt::EditRole:
|
||||
if (column == FDS_MODEL_TITLE_INDEX) {
|
||||
return m_title;
|
||||
}
|
||||
else if (column == FDS_MODEL_COUNTS_INDEX) {
|
||||
return countOfUnreadMessages();
|
||||
}
|
||||
else {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
case Qt::DecorationRole:
|
||||
if (column == FDS_MODEL_TITLE_INDEX) {
|
||||
return m_icon;
|
||||
}
|
||||
else {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
case Qt::ToolTipRole:
|
||||
if (column == FDS_MODEL_TITLE_INDEX) {
|
||||
QString auto_update_string;
|
||||
|
||||
switch (m_autoUpdateType) {
|
||||
case DontAutoUpdate:
|
||||
//: Describes feed auto-update status.
|
||||
auto_update_string = tr("does not use auto-update");
|
||||
break;
|
||||
|
||||
case DefaultAutoUpdate:
|
||||
//: Describes feed auto-update status.
|
||||
auto_update_string = tr("uses global settings");
|
||||
break;
|
||||
|
||||
case SpecificAutoUpdate:
|
||||
default:
|
||||
//: Describes feed auto-update status.
|
||||
auto_update_string = tr("uses specific settings "
|
||||
"(%n minute(s) to next auto-update)",
|
||||
0,
|
||||
m_autoUpdateRemainingInterval);
|
||||
break;
|
||||
}
|
||||
|
||||
//: Tooltip for feed.
|
||||
return tr("%1 (%2)\n"
|
||||
"%3\n\n"
|
||||
"Encoding: %4\n"
|
||||
"Auto-update status: %5").arg(m_title,
|
||||
FeedsModelFeed::typeToString(m_type),
|
||||
m_description,
|
||||
m_encoding,
|
||||
auto_update_string);
|
||||
}
|
||||
else if (column == FDS_MODEL_COUNTS_INDEX) {
|
||||
//: Tooltip for "unread" column of feed list.
|
||||
return tr("%n unread message(s).", 0, countOfUnreadMessages());
|
||||
}
|
||||
else {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
case Qt::TextAlignmentRole:
|
||||
if (column == FDS_MODEL_COUNTS_INDEX) {
|
||||
return Qt::AlignCenter;
|
||||
}
|
||||
else {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
case Qt::FontRole:
|
||||
return countOfUnreadMessages() > 0 ? m_boldFont : m_normalFont;
|
||||
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
void FeedsModelStandardFeed::update() {
|
||||
QByteArray feed_contents;
|
||||
int download_timeout = Settings::instance()->value(APP_CFG_FEEDS, "feed_update_timeout", DOWNLOAD_TIMEOUT).toInt();
|
||||
QNetworkReply::NetworkError download_result = NetworkFactory::downloadFeedFile(url(),
|
||||
download_timeout,
|
||||
feed_contents,
|
||||
passwordProtected(),
|
||||
username(),
|
||||
password());
|
||||
|
||||
if (download_result != QNetworkReply::NoError) {
|
||||
qWarning("Error during fetching of new messages for feed '%s' (id %d).",
|
||||
qPrintable(url()),
|
||||
id());
|
||||
return;
|
||||
}
|
||||
|
||||
// Encode downloaded data for further parsing.
|
||||
QTextCodec *codec = QTextCodec::codecForName(encoding().toLocal8Bit());
|
||||
QString formatted_feed_contents;
|
||||
|
||||
if (codec == NULL) {
|
||||
// No suitable codec for this encoding was found.
|
||||
// Use non-converted data.
|
||||
formatted_feed_contents = feed_contents;
|
||||
}
|
||||
else {
|
||||
formatted_feed_contents = codec->toUnicode(feed_contents);
|
||||
}
|
||||
|
||||
// Feed data are downloaded and encoded.
|
||||
// Parse data and obtain messages.
|
||||
QList<Message> messages;
|
||||
|
||||
switch (type()) {
|
||||
case FeedsModelFeed::StandardRss0X:
|
||||
case FeedsModelFeed::StandardRss2X:
|
||||
messages = ParsingFactory::parseAsRSS20(formatted_feed_contents);
|
||||
break;
|
||||
|
||||
case FeedsModelFeed::StandardRdf:
|
||||
messages = ParsingFactory::parseAsRDF(formatted_feed_contents);
|
||||
break;
|
||||
|
||||
case FeedsModelFeed::StandardAtom10:
|
||||
messages = ParsingFactory::parseAsATOM10(formatted_feed_contents);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
updateMessages(messages);
|
||||
}
|
||||
|
||||
bool FeedsModelStandardFeed::removeItself() {
|
||||
QSqlDatabase database = DatabaseFactory::instance()->connection("FeedsModelStandardFeed",
|
||||
DatabaseFactory::FromSettings);
|
||||
QSqlQuery query_remove(database);
|
||||
|
||||
query_remove.setForwardOnly(true);
|
||||
|
||||
// Remove all messages from this standard feed.
|
||||
query_remove.prepare("DELETE FROM Messages WHERE feed = :feed;");
|
||||
query_remove.bindValue(":feed", id());
|
||||
|
||||
if (!query_remove.exec()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove feed itself.
|
||||
query_remove.prepare("DELETE FROM Feeds WHERE id = :feed;");
|
||||
query_remove.bindValue(":feed", id());
|
||||
|
||||
return query_remove.exec();
|
||||
}
|
||||
|
||||
void FeedsModelStandardFeed::updateMessages(const QList<Message> &messages) {
|
||||
int feed_id = id();
|
||||
QSqlDatabase database = DatabaseFactory::instance()->connection("FeedsModelStandardFeed",
|
||||
DatabaseFactory::FromSettings);
|
||||
|
||||
// Prepare queries.
|
||||
QSqlQuery query_select(database);
|
||||
QSqlQuery query_insert(database);
|
||||
|
||||
// Used to check if give feed contains with message with given
|
||||
// title, url and date_created.
|
||||
// WARNING: One feed CANNOT contain two (or more) messages with same
|
||||
// AUTHOR AND TITLE AND URL AND DATE_CREATED.
|
||||
query_select.setForwardOnly(true);
|
||||
query_select.prepare("SELECT id, feed, date_created FROM Messages "
|
||||
"WHERE feed = :feed AND title = :title AND url = :url AND author = :author;");
|
||||
|
||||
// Used to insert new messages.
|
||||
query_insert.setForwardOnly(true);
|
||||
query_insert.prepare("INSERT INTO Messages "
|
||||
"(feed, title, url, author, date_created, contents) "
|
||||
"VALUES (:feed, :title, :url, :author, :date_created, :contents);");
|
||||
|
||||
if (!database.transaction()) {
|
||||
database.rollback();
|
||||
|
||||
qDebug("Transaction start for message downloader failed.");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (const Message &message, messages) {
|
||||
query_select.bindValue(":feed", feed_id);
|
||||
query_select.bindValue(":title", message.m_title);
|
||||
query_select.bindValue(":url", message.m_url);
|
||||
query_select.bindValue(":author", message.m_author);
|
||||
query_select.exec();
|
||||
|
||||
QList<qint64> datetime_stamps;
|
||||
|
||||
while (query_select.next()) {
|
||||
datetime_stamps << query_select.value(2).value<qint64>();
|
||||
}
|
||||
|
||||
query_select.finish();
|
||||
|
||||
if (datetime_stamps.size() == 0 ||
|
||||
(message.m_createdFromFeed &&
|
||||
!datetime_stamps.contains(message.m_created.toMSecsSinceEpoch()))) {
|
||||
// Message is not fetched in this feed yet
|
||||
// or it is. If it is, then go
|
||||
// through datetime stamps of stored messages
|
||||
// and check if new (not auto-generated timestamp
|
||||
// is among them and add this message if it is not.
|
||||
query_insert.bindValue(":feed", feed_id);
|
||||
query_insert.bindValue(":title", message.m_title);
|
||||
query_insert.bindValue(":url", message.m_url);
|
||||
query_insert.bindValue(":author", message.m_author);
|
||||
query_insert.bindValue(":date_created", message.m_created.toMSecsSinceEpoch());
|
||||
query_insert.bindValue(":contents", message.m_contents);
|
||||
|
||||
query_insert.exec();
|
||||
query_insert.finish();
|
||||
}
|
||||
}
|
||||
|
||||
if (!database.commit()) {
|
||||
database.rollback();
|
||||
|
||||
qDebug("Transaction commit for message downloader failed.");
|
||||
}
|
||||
}
|
@ -1,130 +0,0 @@
|
||||
// This file is part of RSS Guard.
|
||||
//
|
||||
// Copyright (C) 2011-2014 by Martin Rotter <rotter.martinos@gmail.com>
|
||||
//
|
||||
// RSS Guard 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 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// RSS Guard 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 RSS Guard. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef FEEDSMODELSTANDARDFEED_H
|
||||
#define FEEDSMODELSTANDARDFEED_H
|
||||
|
||||
#include "core/feedsmodelfeed.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QSqlRecord>
|
||||
#include <QPair>
|
||||
#include <QNetworkReply>
|
||||
#include <QApplication>
|
||||
|
||||
|
||||
class Message;
|
||||
|
||||
// Represents STANDARD RSS/RDF/ATOM feed with no
|
||||
// online synchronization services (NO TT-RSS, NO FEEDLY).
|
||||
// So, parent item is either root item or category.
|
||||
class FeedsModelStandardFeed : public FeedsModelFeed {
|
||||
Q_DECLARE_TR_FUNCTIONS(FeedsModelStandardFeed)
|
||||
|
||||
public:
|
||||
enum AutoUpdateType {
|
||||
DontAutoUpdate = 0,
|
||||
DefaultAutoUpdate = 1,
|
||||
SpecificAutoUpdate = 2
|
||||
};
|
||||
|
||||
// Constructors and destructors.
|
||||
explicit FeedsModelStandardFeed(FeedsModelRootItem *parent_item = NULL);
|
||||
virtual ~FeedsModelStandardFeed();
|
||||
|
||||
// Obtains data related to this feed.
|
||||
QVariant data(int column, int role) const;
|
||||
|
||||
// Perform fetching of new messages.
|
||||
void update();
|
||||
|
||||
// Removes this standard feed from persistent
|
||||
// storage.
|
||||
bool removeItself();
|
||||
|
||||
// Various getters/setters.
|
||||
inline QString encoding() const {
|
||||
return m_encoding;
|
||||
}
|
||||
|
||||
inline void setEncoding(const QString &encoding) {
|
||||
m_encoding = encoding;
|
||||
}
|
||||
|
||||
inline QString url() const {
|
||||
return m_url;
|
||||
}
|
||||
|
||||
inline void setUrl(const QString &url) {
|
||||
m_url = url;
|
||||
}
|
||||
|
||||
inline int autoUpdateInitialInterval() const {
|
||||
return m_autoUpdateInitialInterval;
|
||||
}
|
||||
|
||||
inline void setAutoUpdateInitialInterval(int auto_update_interval) {
|
||||
// If new initial auto-update interval is set, then
|
||||
// we should reset time that remains to the next auto-update.
|
||||
m_autoUpdateInitialInterval = auto_update_interval;
|
||||
m_autoUpdateRemainingInterval = auto_update_interval;
|
||||
}
|
||||
|
||||
inline AutoUpdateType autoUpdateType() const {
|
||||
return m_autoUpdateType;
|
||||
}
|
||||
|
||||
inline void setAutoUpdateType(const AutoUpdateType &autoUpdateType) {
|
||||
m_autoUpdateType = autoUpdateType;
|
||||
}
|
||||
|
||||
inline int autoUpdateRemainingInterval() const {
|
||||
return m_autoUpdateRemainingInterval;
|
||||
}
|
||||
|
||||
inline void setAutoUpdateRemainingInterval(int autoUpdateRemainingInterval) {
|
||||
m_autoUpdateRemainingInterval = autoUpdateRemainingInterval;
|
||||
}
|
||||
|
||||
// Loads standard feed object from given SQL record.
|
||||
static FeedsModelStandardFeed *loadFromRecord(const QSqlRecord &record);
|
||||
|
||||
// Tries to guess feed hidden under given URL
|
||||
// and uses given credentials.
|
||||
// Returns pointer to guessed feed (if at least partially
|
||||
// guessed) and retrieved error/status code from network layer
|
||||
// or NULL feed.
|
||||
static QPair<FeedsModelStandardFeed*, QNetworkReply::NetworkError> guessFeed(const QString &url,
|
||||
const QString &username,
|
||||
const QString &password);
|
||||
|
||||
protected:
|
||||
// Persistently stores given messages into the database
|
||||
// and updates existing messages if newer version is
|
||||
// available.
|
||||
void updateMessages(const QList<Message> &messages);
|
||||
|
||||
private:
|
||||
AutoUpdateType m_autoUpdateType;
|
||||
int m_autoUpdateInitialInterval;
|
||||
int m_autoUpdateRemainingInterval;
|
||||
|
||||
QString m_encoding;
|
||||
QString m_url;
|
||||
};
|
||||
|
||||
#endif // FEEDSMODELSTANDARDFEED_H
|
@ -17,8 +17,8 @@
|
||||
|
||||
#include "core/parsingfactory.h"
|
||||
|
||||
#include "core/webfactory.h"
|
||||
#include "core/textfactory.h"
|
||||
#include "network-web/webfactory.h"
|
||||
|
||||
#include <QDomDocument>
|
||||
#include <QDomElement>
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include "core/systemfactory.h"
|
||||
|
||||
#include "core/defs.h"
|
||||
#include "core/networkfactory.h"
|
||||
#include "network-web/networkfactory.h"
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
#include "qtsingleapplication/qtsingleapplication.h"
|
||||
|
@ -21,9 +21,9 @@
|
||||
#include "core/databasefactory.h"
|
||||
#include "core/messagesproxymodel.h"
|
||||
#include "core/feeddownloader.h"
|
||||
#include "core/feedsmodelstandardfeed.h"
|
||||
#include "core/feedsmodelfeed.h"
|
||||
#include "core/systemfactory.h"
|
||||
#include "gui/webbrowser.h"
|
||||
#include "network-web/webbrowser.h"
|
||||
#include "gui/formmain.h"
|
||||
#include "gui/iconthemefactory.h"
|
||||
#include "gui/messagesview.h"
|
||||
@ -249,10 +249,10 @@ void FeedMessageViewer::createConnections() {
|
||||
SIGNAL(triggered()), m_feedsView, SLOT(updateSelectedFeeds()));
|
||||
connect(form_main->m_ui->m_actionUpdateAllFeeds,
|
||||
SIGNAL(triggered()), m_feedsView, SLOT(updateAllFeeds()));
|
||||
connect(form_main->m_ui->m_actionAddStandardCategory,
|
||||
SIGNAL(triggered()), m_feedsView, SLOT(addNewStandardCategory()));
|
||||
connect(form_main->m_ui->m_actionAddStandardFeed,
|
||||
SIGNAL(triggered()), m_feedsView, SLOT(addNewStandardFeed()));
|
||||
connect(form_main->m_ui->m_actionAddCategory,
|
||||
SIGNAL(triggered()), m_feedsView, SLOT(addNewCategory()));
|
||||
connect(form_main->m_ui->m_actionAddFeed,
|
||||
SIGNAL(triggered()), m_feedsView, SLOT(addNewFeed()));
|
||||
connect(form_main->m_ui->m_actionEditSelectedFeedCategory,
|
||||
SIGNAL(triggered()), m_feedsView, SLOT(editSelectedItem()));
|
||||
connect(form_main->m_ui->m_actionViewSelectedItemsNewspaperMode,
|
||||
|
@ -24,8 +24,7 @@
|
||||
#include "core/feedsproxymodel.h"
|
||||
#include "core/feedsmodelrootitem.h"
|
||||
#include "core/feedsmodelcategory.h"
|
||||
#include "core/feedsmodelstandardfeed.h"
|
||||
#include "core/feedsmodelstandardcategory.h"
|
||||
#include "core/feedsmodelfeed.h"
|
||||
#include "gui/formmain.h"
|
||||
#include "gui/formstandardcategorydetails.h"
|
||||
#include "gui/formstandardfeeddetails.h"
|
||||
@ -250,7 +249,7 @@ void FeedsView::clearAllFeeds() {
|
||||
setAllFeedsClearStatus(1);
|
||||
}
|
||||
|
||||
void FeedsView::addNewStandardCategory() {
|
||||
void FeedsView::addNewCategory() {
|
||||
if (!SystemFactory::instance()->applicationCloseLock()->tryLock()) {
|
||||
// Lock was not obtained because
|
||||
// it is used probably by feed updater or application
|
||||
@ -281,7 +280,7 @@ void FeedsView::addNewStandardCategory() {
|
||||
SystemFactory::instance()->applicationCloseLock()->unlock();
|
||||
}
|
||||
|
||||
void FeedsView::editStandardCategory(FeedsModelStandardCategory *category) {
|
||||
void FeedsView::editCategory(FeedsModelCategory *category) {
|
||||
QPointer<FormStandardCategoryDetails> form_pointer = new FormStandardCategoryDetails(m_sourceModel, this);
|
||||
|
||||
form_pointer.data()->exec(category);
|
||||
@ -289,7 +288,7 @@ void FeedsView::editStandardCategory(FeedsModelStandardCategory *category) {
|
||||
delete form_pointer.data();
|
||||
}
|
||||
|
||||
void FeedsView::addNewStandardFeed() {
|
||||
void FeedsView::addNewFeed() {
|
||||
if (!SystemFactory::instance()->applicationCloseLock()->tryLock()) {
|
||||
// Lock was not obtained because
|
||||
// it is used probably by feed updater or application
|
||||
@ -320,7 +319,7 @@ void FeedsView::addNewStandardFeed() {
|
||||
SystemFactory::instance()->applicationCloseLock()->unlock();
|
||||
}
|
||||
|
||||
void FeedsView::editStandardFeed(FeedsModelStandardFeed *feed) {
|
||||
void FeedsView::editFeed(FeedsModelFeed *feed) {
|
||||
QPointer<FormStandardFeedDetails> form_pointer = new FormStandardFeedDetails(m_sourceModel, this);
|
||||
|
||||
form_pointer.data()->exec(feed);
|
||||
@ -359,7 +358,7 @@ void FeedsView::editSelectedItem() {
|
||||
switch (category->type()) {
|
||||
case FeedsModelCategory::Standard: {
|
||||
// User wants to edit standard category.
|
||||
editStandardCategory(static_cast<FeedsModelStandardCategory*>(category));
|
||||
editCategory(static_cast<FeedsModelCategory*>(category));
|
||||
break;
|
||||
}
|
||||
|
||||
@ -370,12 +369,12 @@ void FeedsView::editSelectedItem() {
|
||||
else if ((feed = isCurrentIndexFeed()) != NULL) {
|
||||
// Feed is selected.
|
||||
switch (feed->type()) {
|
||||
case FeedsModelFeed::StandardAtom10:
|
||||
case FeedsModelFeed::StandardRdf:
|
||||
case FeedsModelFeed::StandardRss0X:
|
||||
case FeedsModelFeed::StandardRss2X: {
|
||||
case FeedsModelFeed::Atom10:
|
||||
case FeedsModelFeed::Rdf:
|
||||
case FeedsModelFeed::Rss0X:
|
||||
case FeedsModelFeed::Rss2X: {
|
||||
// User wants to edit standard feed.
|
||||
editStandardFeed(static_cast<FeedsModelStandardFeed*>(feed));
|
||||
editFeed(static_cast<FeedsModelFeed*>(feed));
|
||||
break;
|
||||
}
|
||||
|
||||
@ -431,6 +430,8 @@ void FeedsView::deleteSelectedItem() {
|
||||
|
||||
if (m_sourceModel->removeItem(m_proxyModel->mapToSource(current_index))) {
|
||||
// Item WAS removed, update counts.
|
||||
// TODO:_I do not need to update counts of all items here.
|
||||
// Updating counts of parent item (feed) should be enough.
|
||||
updateCountsOfAllFeeds(true);
|
||||
}
|
||||
else {
|
||||
@ -551,7 +552,8 @@ void FeedsView::initializeContextMenuEmptySpace() {
|
||||
m_contextMenuEmptySpace = new QMenu(tr("Context menu for feeds"), this);
|
||||
m_contextMenuEmptySpace->addActions(QList<QAction*>() <<
|
||||
FormMain::instance()->m_ui->m_actionUpdateAllFeeds <<
|
||||
FormMain::instance()->m_ui->m_actionAddStandardFeed);
|
||||
FormMain::instance()->m_ui->m_actionAddCategory <<
|
||||
FormMain::instance()->m_ui->m_actionAddFeed);
|
||||
}
|
||||
|
||||
void FeedsView::setupAppearance() {
|
||||
|
@ -38,6 +38,7 @@ class FeedsView : public QTreeView {
|
||||
explicit FeedsView(QWidget *parent = 0);
|
||||
virtual ~FeedsView();
|
||||
|
||||
// Fundamental accessors.
|
||||
inline FeedsProxyModel *model() {
|
||||
return m_proxyModel;
|
||||
}
|
||||
@ -66,6 +67,8 @@ class FeedsView : public QTreeView {
|
||||
FeedsModelCategory *isCurrentIndexCategory() const;
|
||||
FeedsModelFeed *isCurrentIndexFeed() const;
|
||||
|
||||
// Saves/loads expand states of all nodes (feeds/categories) of the list
|
||||
// to/from settings.
|
||||
void saveExpandedStates();
|
||||
void loadExpandedStates();
|
||||
|
||||
@ -82,7 +85,6 @@ class FeedsView : public QTreeView {
|
||||
void markSelectedFeedsReadStatus(int read);
|
||||
void markSelectedFeedsRead();
|
||||
void markSelectedFeedsUnread();
|
||||
|
||||
void markAllFeedsReadStatus(int read);
|
||||
void markAllFeedsRead();
|
||||
|
||||
@ -101,12 +103,12 @@ class FeedsView : public QTreeView {
|
||||
void deleteSelectedItem();
|
||||
|
||||
// Standard category manipulators.
|
||||
void addNewStandardCategory();
|
||||
void editStandardCategory(FeedsModelStandardCategory *category);
|
||||
void addNewCategory();
|
||||
void editCategory(FeedsModelCategory *category);
|
||||
|
||||
// Standard feed manipulators.
|
||||
void addNewStandardFeed();
|
||||
void editStandardFeed(FeedsModelStandardFeed *feed);
|
||||
void addNewFeed();
|
||||
void editFeed(FeedsModelFeed *feed);
|
||||
|
||||
// Reloads counts for selected feeds.
|
||||
void updateCountsOfSelectedFeeds(bool update_total_too = true);
|
||||
@ -124,6 +126,7 @@ class FeedsView : public QTreeView {
|
||||
m_sourceModel->countOfAllMessages());
|
||||
}
|
||||
|
||||
// Selects next/previous item (feed/category) in the list.
|
||||
void selectNextItem();
|
||||
void selectPreviousItem();
|
||||
|
||||
|
@ -21,12 +21,12 @@
|
||||
#include "core/settings.h"
|
||||
#include "core/systemfactory.h"
|
||||
#include "core/databasefactory.h"
|
||||
#include "core/webfactory.h"
|
||||
#include "network-web/webfactory.h"
|
||||
#include "network-web/webbrowser.h"
|
||||
#include "gui/formabout.h"
|
||||
#include "gui/formsettings.h"
|
||||
#include "gui/feedsview.h"
|
||||
#include "gui/messagebox.h"
|
||||
#include "gui/webbrowser.h"
|
||||
#include "gui/iconthemefactory.h"
|
||||
#include "gui/systemtrayicon.h"
|
||||
#include "gui/tabbar.h"
|
||||
@ -115,8 +115,8 @@ QList<QAction*> FormMain::allActions() {
|
||||
m_ui->m_actionEditSelectedFeedCategory <<
|
||||
m_ui->m_actionDeleteSelectedFeedCategory <<
|
||||
m_ui->m_actionViewSelectedItemsNewspaperMode <<
|
||||
m_ui->m_actionAddStandardCategory <<
|
||||
m_ui->m_actionAddStandardFeed <<
|
||||
m_ui->m_actionAddCategory <<
|
||||
m_ui->m_actionAddFeed <<
|
||||
m_ui->m_actionSelectNextFeedCategory <<
|
||||
m_ui->m_actionSelectPreviousFeedCategory <<
|
||||
m_ui->m_actionSelectNextMessage <<
|
||||
@ -291,8 +291,8 @@ void FormMain::setupIcons() {
|
||||
m_ui->m_actionClearAllFeeds->setIcon(icon_theme_factory->fromTheme("mail-remove"));
|
||||
m_ui->m_actionDeleteSelectedFeedCategory->setIcon(icon_theme_factory->fromTheme("item-remove"));
|
||||
m_ui->m_actionDeleteSelectedMessages->setIcon(icon_theme_factory->fromTheme("mail-remove"));
|
||||
m_ui->m_actionAddStandardCategory->setIcon(icon_theme_factory->fromTheme("folder-category"));
|
||||
m_ui->m_actionAddStandardFeed->setIcon(icon_theme_factory->fromTheme("folder-feed"));
|
||||
m_ui->m_actionAddCategory->setIcon(icon_theme_factory->fromTheme("folder-category"));
|
||||
m_ui->m_actionAddFeed->setIcon(icon_theme_factory->fromTheme("folder-feed"));
|
||||
m_ui->m_actionEditSelectedFeedCategory->setIcon(icon_theme_factory->fromTheme("item-edit"));
|
||||
m_ui->m_actionMarkAllFeedsRead->setIcon(icon_theme_factory->fromTheme("mail-mark-read"));
|
||||
m_ui->m_actionMarkSelectedFeedsAsRead->setIcon(icon_theme_factory->fromTheme("mail-mark-read"));
|
||||
@ -309,7 +309,6 @@ void FormMain::setupIcons() {
|
||||
m_ui->m_actionSelectNextMessage->setIcon(icon_theme_factory->fromTheme("go-down"));
|
||||
m_ui->m_actionSelectPreviousMessage->setIcon(icon_theme_factory->fromTheme("go-up"));
|
||||
|
||||
|
||||
// Setup icons for underlying components: opened web browsers...
|
||||
foreach (WebBrowser *browser, WebBrowser::runningWebBrowsers()) {
|
||||
browser->setupIcons();
|
||||
|
@ -15,7 +15,16 @@
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="margin">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
@ -39,7 +48,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>979</width>
|
||||
<height>20</height>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="m_menuFile">
|
||||
@ -111,8 +120,8 @@
|
||||
<property name="title">
|
||||
<string>Add &new feed/category</string>
|
||||
</property>
|
||||
<addaction name="m_actionAddStandardCategory"/>
|
||||
<addaction name="m_actionAddStandardFeed"/>
|
||||
<addaction name="m_actionAddCategory"/>
|
||||
<addaction name="m_actionAddFeed"/>
|
||||
</widget>
|
||||
<addaction name="m_actionUpdateAllFeeds"/>
|
||||
<addaction name="m_actionUpdateSelectedFeedsCategories"/>
|
||||
@ -300,12 +309,12 @@
|
||||
<string>Deletes all messages from selected feeds.</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="m_actionAddStandardFeed">
|
||||
<action name="m_actionAddFeed">
|
||||
<property name="text">
|
||||
<string>New standard &feed</string>
|
||||
<string>New &feed</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Add new standard feed.</string>
|
||||
<string>Add new feed.</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="m_actionOpenSelectedSourceArticlesExternally">
|
||||
@ -323,12 +332,12 @@
|
||||
<string>Open selected source articles in &internal browser</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="m_actionAddStandardCategory">
|
||||
<action name="m_actionAddCategory">
|
||||
<property name="text">
|
||||
<string>New standard &category</string>
|
||||
<string>New &category</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Add new standard category.</string>
|
||||
<string>Add new category.</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="m_actionNoActions">
|
||||
|
@ -22,11 +22,12 @@
|
||||
#include "core/databasefactory.h"
|
||||
#include "core/localization.h"
|
||||
#include "core/systemfactory.h"
|
||||
#include "core/webfactory.h"
|
||||
#include "core/feeddownloader.h"
|
||||
#include "core/dynamicshortcuts.h"
|
||||
#include "core/webbrowsernetworkaccessmanager.h"
|
||||
#include "core/silentnetworkaccessmanager.h"
|
||||
#include "network-web/webfactory.h"
|
||||
#include "network-web/webbrowsernetworkaccessmanager.h"
|
||||
#include "network-web/silentnetworkaccessmanager.h"
|
||||
#include "network-web/webbrowser.h"
|
||||
#include "core/feedsmodel.h"
|
||||
#include "gui/iconthemefactory.h"
|
||||
#include "gui/skinfactory.h"
|
||||
@ -34,7 +35,6 @@
|
||||
#include "gui/feedmessageviewer.h"
|
||||
#include "gui/feedsview.h"
|
||||
#include "gui/formmain.h"
|
||||
#include "gui/webbrowser.h"
|
||||
#include "gui/messagebox.h"
|
||||
#include "qtsingleapplication/qtsingleapplication.h"
|
||||
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include "core/defs.h"
|
||||
#include "core/feedsmodelrootitem.h"
|
||||
#include "core/feedsmodelcategory.h"
|
||||
#include "core/feedsmodelstandardcategory.h"
|
||||
#include "core/feedsmodel.h"
|
||||
#include "gui/iconthemefactory.h"
|
||||
#include "gui/feedsview.h"
|
||||
@ -70,7 +69,7 @@ void FormStandardCategoryDetails::createConnections() {
|
||||
connect(m_actionUseDefaultIcon, SIGNAL(triggered()), this, SLOT(onUseDefaultIcon()));
|
||||
}
|
||||
|
||||
void FormStandardCategoryDetails::setEditableCategory(FeedsModelStandardCategory *editable_category) {
|
||||
void FormStandardCategoryDetails::setEditableCategory(FeedsModelCategory *editable_category) {
|
||||
m_editableCategory = editable_category;
|
||||
|
||||
m_ui->m_cmbParentCategory->setCurrentIndex(m_ui->m_cmbParentCategory->findData(QVariant::fromValue((void*) editable_category->parent())));
|
||||
@ -79,7 +78,7 @@ void FormStandardCategoryDetails::setEditableCategory(FeedsModelStandardCategory
|
||||
m_ui->m_btnIcon->setIcon(editable_category->icon());
|
||||
}
|
||||
|
||||
int FormStandardCategoryDetails::exec(FeedsModelStandardCategory *input_category) {
|
||||
int FormStandardCategoryDetails::exec(FeedsModelCategory *input_category) {
|
||||
// Load categories.
|
||||
loadCategories(m_feedsModel->allCategories().values(),
|
||||
m_feedsModel->rootItem(),
|
||||
@ -105,7 +104,7 @@ int FormStandardCategoryDetails::exec(FeedsModelStandardCategory *input_category
|
||||
|
||||
void FormStandardCategoryDetails::apply() {
|
||||
FeedsModelRootItem *parent = static_cast<FeedsModelRootItem*>(m_ui->m_cmbParentCategory->itemData(m_ui->m_cmbParentCategory->currentIndex()).value<void*>());
|
||||
FeedsModelStandardCategory *new_category = new FeedsModelStandardCategory();
|
||||
FeedsModelCategory *new_category = new FeedsModelCategory();
|
||||
|
||||
new_category->setTitle(m_ui->m_txtTitle->lineEdit()->text());
|
||||
new_category->setCreationDate(QDateTime::currentDateTime());
|
||||
@ -115,7 +114,7 @@ void FormStandardCategoryDetails::apply() {
|
||||
|
||||
if (m_editableCategory == NULL) {
|
||||
// Add the category.
|
||||
if (m_feedsModel->addStandardCategory(new_category, parent)) {
|
||||
if (m_feedsModel->addCategory(new_category, parent)) {
|
||||
accept();
|
||||
}
|
||||
else {
|
||||
@ -133,7 +132,7 @@ void FormStandardCategoryDetails::apply() {
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (m_feedsModel->editStandardCategory(m_editableCategory, new_category)) {
|
||||
if (m_feedsModel->editCategory(m_editableCategory, new_category)) {
|
||||
accept();
|
||||
}
|
||||
else {
|
||||
|
@ -28,7 +28,7 @@ namespace Ui {
|
||||
}
|
||||
|
||||
class FeedsModelCategory;
|
||||
class FeedsModelStandardCategory;
|
||||
class FeedsModelCategory;
|
||||
class FeedsModel;
|
||||
class FeedsModelRootItem;
|
||||
class QMenu;
|
||||
@ -44,7 +44,7 @@ class FormStandardCategoryDetails : public QDialog {
|
||||
|
||||
public slots:
|
||||
// Executes add/edit standard category dialog.
|
||||
int exec(FeedsModelStandardCategory *input_category);
|
||||
int exec(FeedsModelCategory *input_category);
|
||||
|
||||
protected slots:
|
||||
// Applies changes.
|
||||
@ -64,7 +64,7 @@ class FormStandardCategoryDetails : public QDialog {
|
||||
void createConnections();
|
||||
|
||||
// Sets the category which will be edited.
|
||||
void setEditableCategory(FeedsModelStandardCategory *editable_category);
|
||||
void setEditableCategory(FeedsModelCategory *editable_category);
|
||||
|
||||
// Initializes the dialog.
|
||||
void initialize();
|
||||
@ -78,7 +78,7 @@ class FormStandardCategoryDetails : public QDialog {
|
||||
|
||||
private:
|
||||
Ui::FormStandardCategoryDetails *m_ui;
|
||||
FeedsModelStandardCategory *m_editableCategory;
|
||||
FeedsModelCategory *m_editableCategory;
|
||||
FeedsModel *m_feedsModel;
|
||||
|
||||
QMenu *m_iconMenu;
|
||||
|
@ -23,8 +23,7 @@
|
||||
#include "core/feedsmodelrootitem.h"
|
||||
#include "core/feedsmodelcategory.h"
|
||||
#include "core/feedsmodelfeed.h"
|
||||
#include "core/feedsmodelstandardfeed.h"
|
||||
#include "core/networkfactory.h"
|
||||
#include "network-web/networkfactory.h"
|
||||
#include "gui/iconthemefactory.h"
|
||||
#include "gui/baselineedit.h"
|
||||
#include "gui/messagebox.h"
|
||||
@ -57,7 +56,7 @@ FormStandardFeedDetails::~FormStandardFeedDetails() {
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
int FormStandardFeedDetails::exec(FeedsModelStandardFeed *input_feed) {
|
||||
int FormStandardFeedDetails::exec(FeedsModelFeed *input_feed) {
|
||||
// Load categories.
|
||||
loadCategories(m_feedsModel->allCategories().values(),
|
||||
m_feedsModel->rootItem());
|
||||
@ -151,15 +150,15 @@ void FormStandardFeedDetails::onAuthenticationSwitched() {
|
||||
}
|
||||
|
||||
void FormStandardFeedDetails::onAutoUpdateTypeChanged(int new_index) {
|
||||
FeedsModelStandardFeed::AutoUpdateType auto_update_type = static_cast<FeedsModelStandardFeed::AutoUpdateType>(m_ui->m_cmbAutoUpdateType->itemData(new_index).toInt());
|
||||
FeedsModelFeed::AutoUpdateType auto_update_type = static_cast<FeedsModelFeed::AutoUpdateType>(m_ui->m_cmbAutoUpdateType->itemData(new_index).toInt());
|
||||
|
||||
switch (auto_update_type) {
|
||||
case FeedsModelStandardFeed::DontAutoUpdate:
|
||||
case FeedsModelStandardFeed::DefaultAutoUpdate:
|
||||
case FeedsModelFeed::DontAutoUpdate:
|
||||
case FeedsModelFeed::DefaultAutoUpdate:
|
||||
m_ui->m_spinAutoUpdateInterval->setEnabled(false);
|
||||
break;
|
||||
|
||||
case FeedsModelStandardFeed::SpecificAutoUpdate:
|
||||
case FeedsModelFeed::SpecificAutoUpdate:
|
||||
default:
|
||||
m_ui->m_spinAutoUpdateInterval->setEnabled(true);
|
||||
}
|
||||
@ -203,8 +202,8 @@ void FormStandardFeedDetails::onUseDefaultIcon() {
|
||||
|
||||
void FormStandardFeedDetails::apply() {
|
||||
FeedsModelRootItem *parent = static_cast<FeedsModelRootItem*>(m_ui->m_cmbParentCategory->itemData(m_ui->m_cmbParentCategory->currentIndex()).value<void*>());
|
||||
FeedsModelStandardFeed::Type type = static_cast<FeedsModelStandardFeed::Type>(m_ui->m_cmbType->itemData(m_ui->m_cmbType->currentIndex()).value<int>());
|
||||
FeedsModelStandardFeed *new_feed = new FeedsModelStandardFeed();
|
||||
FeedsModelFeed::Type type = static_cast<FeedsModelFeed::Type>(m_ui->m_cmbType->itemData(m_ui->m_cmbType->currentIndex()).value<int>());
|
||||
FeedsModelFeed *new_feed = new FeedsModelFeed();
|
||||
|
||||
// Setup data for new_feed.
|
||||
new_feed->setTitle(m_ui->m_txtTitle->lineEdit()->text());
|
||||
@ -217,13 +216,13 @@ void FormStandardFeedDetails::apply() {
|
||||
new_feed->setPasswordProtected(m_ui->m_gbAuthentication->isChecked());
|
||||
new_feed->setUsername(m_ui->m_txtUsername->lineEdit()->text());
|
||||
new_feed->setPassword(m_ui->m_txtPassword->lineEdit()->text());
|
||||
new_feed->setAutoUpdateType(static_cast<FeedsModelStandardFeed::AutoUpdateType>(m_ui->m_cmbAutoUpdateType->itemData(m_ui->m_cmbAutoUpdateType->currentIndex()).toInt()));
|
||||
new_feed->setAutoUpdateType(static_cast<FeedsModelFeed::AutoUpdateType>(m_ui->m_cmbAutoUpdateType->itemData(m_ui->m_cmbAutoUpdateType->currentIndex()).toInt()));
|
||||
new_feed->setAutoUpdateInitialInterval(m_ui->m_spinAutoUpdateInterval->value());
|
||||
new_feed->setParent(parent);
|
||||
|
||||
if (m_editableFeed == NULL) {
|
||||
// Add the feed.
|
||||
if (m_feedsModel->addStandardFeed(new_feed, parent)) {
|
||||
if (m_feedsModel->addFeed(new_feed, parent)) {
|
||||
accept();
|
||||
}
|
||||
else {
|
||||
@ -242,7 +241,7 @@ void FormStandardFeedDetails::apply() {
|
||||
}
|
||||
else {
|
||||
// Edit the feed.
|
||||
if (m_feedsModel->editStandardFeed(m_editableFeed, new_feed)) {
|
||||
if (m_feedsModel->editFeed(m_editableFeed, new_feed)) {
|
||||
accept();
|
||||
}
|
||||
else {
|
||||
@ -262,9 +261,9 @@ void FormStandardFeedDetails::apply() {
|
||||
}
|
||||
|
||||
void FormStandardFeedDetails::guessFeed() {
|
||||
QPair<FeedsModelStandardFeed*, QNetworkReply::NetworkError> result = FeedsModelStandardFeed::guessFeed(m_ui->m_txtUrl->lineEdit()->text(),
|
||||
m_ui->m_txtUsername->lineEdit()->text(),
|
||||
m_ui->m_txtPassword->lineEdit()->text());
|
||||
QPair<FeedsModelFeed*, QNetworkReply::NetworkError> result = FeedsModelFeed::guessFeed(m_ui->m_txtUrl->lineEdit()->text(),
|
||||
m_ui->m_txtUsername->lineEdit()->text(),
|
||||
m_ui->m_txtPassword->lineEdit()->text());
|
||||
|
||||
if (result.first != NULL) {
|
||||
// Icon or whole feed was guessed.
|
||||
@ -332,7 +331,7 @@ void FormStandardFeedDetails::createConnections() {
|
||||
connect(m_actionUseDefaultIcon, SIGNAL(triggered()), this, SLOT(onUseDefaultIcon()));
|
||||
}
|
||||
|
||||
void FormStandardFeedDetails::setEditableFeed(FeedsModelStandardFeed *editable_feed) {
|
||||
void FormStandardFeedDetails::setEditableFeed(FeedsModelFeed *editable_feed) {
|
||||
m_editableFeed = editable_feed;
|
||||
|
||||
m_ui->m_cmbParentCategory->setCurrentIndex(m_ui->m_cmbParentCategory->findData(QVariant::fromValue((void*) editable_feed->parent())));
|
||||
@ -381,10 +380,10 @@ void FormStandardFeedDetails::initialize() {
|
||||
#endif
|
||||
|
||||
// Add standard feed types.
|
||||
m_ui->m_cmbType->addItem(FeedsModelFeed::typeToString(FeedsModelFeed::StandardAtom10), QVariant::fromValue((int) FeedsModelFeed::StandardAtom10));
|
||||
m_ui->m_cmbType->addItem(FeedsModelFeed::typeToString(FeedsModelFeed::StandardRdf), QVariant::fromValue((int) FeedsModelFeed::StandardRdf));
|
||||
m_ui->m_cmbType->addItem(FeedsModelFeed::typeToString(FeedsModelFeed::StandardRss0X), QVariant::fromValue((int) FeedsModelFeed::StandardRss0X));
|
||||
m_ui->m_cmbType->addItem(FeedsModelFeed::typeToString(FeedsModelFeed::StandardRss2X), QVariant::fromValue((int) FeedsModelFeed::StandardRss2X));
|
||||
m_ui->m_cmbType->addItem(FeedsModelFeed::typeToString(FeedsModelFeed::Atom10), QVariant::fromValue((int) FeedsModelFeed::Atom10));
|
||||
m_ui->m_cmbType->addItem(FeedsModelFeed::typeToString(FeedsModelFeed::Rdf), QVariant::fromValue((int) FeedsModelFeed::Rdf));
|
||||
m_ui->m_cmbType->addItem(FeedsModelFeed::typeToString(FeedsModelFeed::Rss0X), QVariant::fromValue((int) FeedsModelFeed::Rss0X));
|
||||
m_ui->m_cmbType->addItem(FeedsModelFeed::typeToString(FeedsModelFeed::Rss2X), QVariant::fromValue((int) FeedsModelFeed::Rss2X));
|
||||
|
||||
// Load available encodings.
|
||||
QList<QByteArray> encodings = QTextCodec::availableCodecs();
|
||||
@ -421,9 +420,9 @@ void FormStandardFeedDetails::initialize() {
|
||||
|
||||
// Setup auto-update options.
|
||||
m_ui->m_spinAutoUpdateInterval->setValue(DEFAULT_AUTO_UPDATE_INTERVAL);
|
||||
m_ui->m_cmbAutoUpdateType->addItem(tr("Auto-update using global interval"), QVariant::fromValue((int) FeedsModelStandardFeed::DefaultAutoUpdate));
|
||||
m_ui->m_cmbAutoUpdateType->addItem(tr("Auto-update every"), QVariant::fromValue((int) FeedsModelStandardFeed::SpecificAutoUpdate));
|
||||
m_ui->m_cmbAutoUpdateType->addItem(tr("Do not auto-update at all"), QVariant::fromValue((int) FeedsModelStandardFeed::DontAutoUpdate));
|
||||
m_ui->m_cmbAutoUpdateType->addItem(tr("Auto-update using global interval"), QVariant::fromValue((int) FeedsModelFeed::DefaultAutoUpdate));
|
||||
m_ui->m_cmbAutoUpdateType->addItem(tr("Auto-update every"), QVariant::fromValue((int) FeedsModelFeed::SpecificAutoUpdate));
|
||||
m_ui->m_cmbAutoUpdateType->addItem(tr("Do not auto-update at all"), QVariant::fromValue((int) FeedsModelFeed::DontAutoUpdate));
|
||||
|
||||
// Set tab order.
|
||||
setTabOrder(m_ui->m_cmbParentCategory, m_ui->m_cmbType);
|
||||
|
@ -28,7 +28,7 @@ namespace Ui {
|
||||
}
|
||||
|
||||
class FeedsModel;
|
||||
class FeedsModelStandardFeed;
|
||||
class FeedsModelFeed;
|
||||
class FeedsModelCategory;
|
||||
class FeedsModelRootItem;
|
||||
|
||||
@ -42,7 +42,7 @@ class FormStandardFeedDetails : public QDialog {
|
||||
|
||||
public slots:
|
||||
// Executes add/edit standard feed dialog.
|
||||
int exec(FeedsModelStandardFeed *input_feed);
|
||||
int exec(FeedsModelFeed *input_feed);
|
||||
|
||||
protected slots:
|
||||
// Applies changes.
|
||||
@ -71,7 +71,7 @@ class FormStandardFeedDetails : public QDialog {
|
||||
void createConnections();
|
||||
|
||||
// Sets the feed which will be edited.
|
||||
void setEditableFeed(FeedsModelStandardFeed *editable_feed);
|
||||
void setEditableFeed(FeedsModelFeed *editable_feed);
|
||||
|
||||
// Initializes the dialog.
|
||||
void initialize();
|
||||
@ -82,7 +82,7 @@ class FormStandardFeedDetails : public QDialog {
|
||||
|
||||
private:
|
||||
Ui::FormStandardFeedDetails *m_ui;
|
||||
FeedsModelStandardFeed *m_editableFeed;
|
||||
FeedsModelFeed *m_editableFeed;
|
||||
FeedsModel *m_feedsModel;
|
||||
|
||||
QMenu *m_iconMenu;
|
||||
|
@ -19,8 +19,8 @@
|
||||
|
||||
#include "core/defs.h"
|
||||
#include "core/systemfactory.h"
|
||||
#include "core/networkfactory.h"
|
||||
#include "core/webfactory.h"
|
||||
#include "network-web/networkfactory.h"
|
||||
#include "network-web/webfactory.h"
|
||||
#include "gui/iconthemefactory.h"
|
||||
#include "gui/messagebox.h"
|
||||
#include "gui/systemtrayicon.h"
|
||||
|
@ -20,8 +20,8 @@
|
||||
#include "core/messagesproxymodel.h"
|
||||
#include "core/messagesmodel.h"
|
||||
#include "core/settings.h"
|
||||
#include "core/networkfactory.h"
|
||||
#include "core/webfactory.h"
|
||||
#include "network-web/networkfactory.h"
|
||||
#include "network-web/webfactory.h"
|
||||
#include "gui/formmain.h"
|
||||
#include "gui/messagebox.h"
|
||||
|
||||
|
@ -20,9 +20,9 @@
|
||||
#include "core/defs.h"
|
||||
#include "core/settings.h"
|
||||
#include "core/textfactory.h"
|
||||
#include "network-web/webbrowser.h"
|
||||
#include "gui/tabbar.h"
|
||||
#include "gui/iconthemefactory.h"
|
||||
#include "gui/webbrowser.h"
|
||||
#include "gui/formmain.h"
|
||||
#include "gui/feedmessageviewer.h"
|
||||
#include "gui/plaintoolbutton.h"
|
||||
@ -109,20 +109,33 @@ void TabWidget::checkTabBarVisibility() {
|
||||
}
|
||||
|
||||
void TabWidget::tabInserted(int index) {
|
||||
QTabWidget::tabInserted(index);
|
||||
QTabWidget::tabInserted(index);
|
||||
checkTabBarVisibility();
|
||||
|
||||
int count_of_tabs = count();
|
||||
|
||||
if (index < count_of_tabs - 1 && count_of_tabs > 1) {
|
||||
// New tab was inserted and the tab is not the last one.
|
||||
fixContentsAfterMove(index, count_of_tabs - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void TabWidget::tabRemoved(int index) {
|
||||
QTabWidget::tabRemoved(index);
|
||||
checkTabBarVisibility();
|
||||
|
||||
int count_of_tabs = count();
|
||||
|
||||
if (index < count_of_tabs && count_of_tabs > 1) {
|
||||
// Some tab was removed and the tab was not the last one.
|
||||
fixContentsAfterMove(index, count_of_tabs - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void TabWidget::createConnections() {
|
||||
connect(tabBar(), SIGNAL(tabCloseRequested(int)), this, SLOT(closeTab(int)));
|
||||
connect(tabBar(), SIGNAL(emptySpaceDoubleClicked()), this, SLOT(addEmptyBrowser()));
|
||||
connect(tabBar(), SIGNAL(tabMoved(int,int)), this, SLOT(fixContentsAfterMove(int,int)));
|
||||
connect(tabBar(), SIGNAL(currentChanged(int)), this, SLOT(fixContentAfterIndexChange(int)));
|
||||
}
|
||||
|
||||
void TabWidget::initializeTabs() {
|
||||
@ -324,17 +337,12 @@ void TabWidget::changeTitle(int index, const QString &new_title) {
|
||||
setTabToolTip(index, new_title);
|
||||
}
|
||||
|
||||
void TabWidget::fixContentAfterIndexChange(int from) {
|
||||
fixContentsIndexes(from, count() - 1);
|
||||
}
|
||||
|
||||
void TabWidget::fixContentsAfterMove(int from, int to) {
|
||||
fixContentsIndexes(qMin(from, to), qMax(from, to));
|
||||
}
|
||||
from = qMin(from, to);
|
||||
to = qMax(from, to);
|
||||
|
||||
void TabWidget::fixContentsIndexes(int starting_index, int ending_index) {
|
||||
for ( ; starting_index <= ending_index; starting_index++) {
|
||||
TabContent *content = static_cast<TabContent*>(widget(starting_index));
|
||||
content->setIndex(starting_index);
|
||||
for ( ; from <= to; from++) {
|
||||
TabContent *content = static_cast<TabContent*>(widget(from));
|
||||
content->setIndex(from);
|
||||
}
|
||||
}
|
||||
|
@ -85,12 +85,8 @@ class TabWidget : public QTabWidget {
|
||||
|
||||
public slots:
|
||||
// Fixes tabs indexes.
|
||||
void fixContentAfterIndexChange(int from);
|
||||
void fixContentsAfterMove(int from, int to);
|
||||
|
||||
// Fixes indexes of tab contents.
|
||||
void fixContentsIndexes(int starting_index, int ending_index);
|
||||
|
||||
// Called when number of tab pages changes.
|
||||
void checkTabBarVisibility();
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "core/basenetworkaccessmanager.h"
|
||||
#include "network-web/basenetworkaccessmanager.h"
|
||||
|
||||
#include "core/defs.h"
|
||||
#include "core/settings.h"
|
@ -15,15 +15,16 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "core/networkfactory.h"
|
||||
#include "network-web/networkfactory.h"
|
||||
|
||||
#include "core/defs.h"
|
||||
#include "core/silentnetworkaccessmanager.h"
|
||||
#include "core/feedsmodelstandardfeed.h"
|
||||
#include "core/settings.h"
|
||||
#include "network-web/silentnetworkaccessmanager.h"
|
||||
|
||||
#include <QEventLoop>
|
||||
#include <QTimer>
|
||||
#include <QIcon>
|
||||
#include <QPixmap>
|
||||
#include <QTextDocument>
|
||||
|
||||
|
@ -22,8 +22,6 @@
|
||||
#include <QApplication>
|
||||
|
||||
|
||||
class FeedsModelStandardFeed;
|
||||
|
||||
class NetworkFactory {
|
||||
Q_DECLARE_TR_FUNCTIONS(NetworkFactory)
|
||||
|
@ -15,9 +15,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "core/silentnetworkaccessmanager.h"
|
||||
|
||||
#include "core/feedsmodelstandardfeed.h"
|
||||
#include "network-web/silentnetworkaccessmanager.h"
|
||||
|
||||
#include <QNetworkReply>
|
||||
#include <QAuthenticator>
|
@ -18,7 +18,7 @@
|
||||
#ifndef SILENTNETWORKACCESSMANAGER_H
|
||||
#define SILENTNETWORKACCESSMANAGER_H
|
||||
|
||||
#include "core/basenetworkaccessmanager.h"
|
||||
#include "network-web/basenetworkaccessmanager.h"
|
||||
|
||||
#include <QPointer>
|
||||
|
@ -15,13 +15,13 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "gui/webbrowser.h"
|
||||
#include "network-web/webbrowser.h"
|
||||
|
||||
#include "core/defs.h"
|
||||
#include "core/webbrowsernetworkaccessmanager.h"
|
||||
#include "core/webpage.h"
|
||||
#include "network-web/webbrowsernetworkaccessmanager.h"
|
||||
#include "network-web/webpage.h"
|
||||
#include "network-web/webview.h"
|
||||
#include "gui/skinfactory.h"
|
||||
#include "gui/webview.h"
|
||||
#include "gui/formmain.h"
|
||||
#include "gui/iconthemefactory.h"
|
||||
#include "gui/tabwidget.h"
|
@ -19,8 +19,8 @@
|
||||
#define WEBBROWSER_H
|
||||
|
||||
#include "core/messagesmodel.h"
|
||||
#include "network-web/webview.h"
|
||||
#include "gui/tabcontent.h"
|
||||
#include "gui/webview.h"
|
||||
#include "gui/locationlineedit.h"
|
||||
|
||||
#include <QWidget>
|
@ -15,7 +15,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "core/webbrowsernetworkaccessmanager.h"
|
||||
#include "network-web/webbrowsernetworkaccessmanager.h"
|
||||
|
||||
#include <QNetworkReply>
|
||||
#include <QApplication>
|
@ -18,7 +18,7 @@
|
||||
#ifndef WEBBROWSERNETWORKACCESSMANAGER_H
|
||||
#define WEBBROWSERNETWORKACCESSMANAGER_H
|
||||
|
||||
#include "core/basenetworkaccessmanager.h"
|
||||
#include "network-web/basenetworkaccessmanager.h"
|
||||
|
||||
#include <QPointer>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "core/webfactory.h"
|
||||
#include "network-web/webfactory.h"
|
||||
|
||||
#include "core/defs.h"
|
||||
#include "core/settings.h"
|
@ -15,10 +15,10 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "core/webpage.h"
|
||||
#include "network-web/webpage.h"
|
||||
|
||||
#include "core/webbrowsernetworkaccessmanager.h"
|
||||
#include "gui/webbrowser.h"
|
||||
#include "network-web/webbrowsernetworkaccessmanager.h"
|
||||
#include "network-web/webbrowser.h"
|
||||
|
||||
#include <QNetworkReply>
|
||||
#include <QWebFrame>
|
@ -15,11 +15,11 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "gui/webview.h"
|
||||
#include "network-web/webview.h"
|
||||
|
||||
#include "core/defs.h"
|
||||
#include "core/settings.h"
|
||||
#include "core/webpage.h"
|
||||
#include "network-web/webpage.h"
|
||||
#include "gui/skinfactory.h"
|
||||
#include "gui/iconthemefactory.h"
|
||||
|
Loading…
x
Reference in New Issue
Block a user