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/shortcutcatcher.cpp
|
||||||
src/gui/shortcutbutton.cpp
|
src/gui/shortcutbutton.cpp
|
||||||
src/gui/dynamicshortcutswidget.cpp
|
src/gui/dynamicshortcutswidget.cpp
|
||||||
src/gui/webbrowser.cpp
|
|
||||||
src/gui/webview.cpp
|
|
||||||
src/gui/baselineedit.cpp
|
src/gui/baselineedit.cpp
|
||||||
src/gui/locationlineedit.cpp
|
src/gui/locationlineedit.cpp
|
||||||
src/gui/tabwidget.cpp
|
src/gui/tabwidget.cpp
|
||||||
@ -307,10 +305,6 @@ set(APP_SOURCES
|
|||||||
src/core/systemfactory.cpp
|
src/core/systemfactory.cpp
|
||||||
src/core/localization.cpp
|
src/core/localization.cpp
|
||||||
src/core/dynamicshortcuts.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/textfactory.cpp
|
||||||
src/core/databasefactory.cpp
|
src/core/databasefactory.cpp
|
||||||
src/core/messagesmodel.cpp
|
src/core/messagesmodel.cpp
|
||||||
@ -320,14 +314,20 @@ set(APP_SOURCES
|
|||||||
src/core/feedsmodelcategory.cpp
|
src/core/feedsmodelcategory.cpp
|
||||||
src/core/feedsmodelrootitem.cpp
|
src/core/feedsmodelrootitem.cpp
|
||||||
src/core/feedsmodelfeed.cpp
|
src/core/feedsmodelfeed.cpp
|
||||||
src/core/feedsmodelstandardcategory.cpp
|
|
||||||
src/core/feedsmodelstandardfeed.cpp
|
|
||||||
src/core/parsingfactory.cpp
|
src/core/parsingfactory.cpp
|
||||||
src/core/feeddownloader.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
|
src/main.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -349,8 +349,6 @@ set(APP_HEADERS
|
|||||||
src/gui/shortcutcatcher.h
|
src/gui/shortcutcatcher.h
|
||||||
src/gui/shortcutbutton.h
|
src/gui/shortcutbutton.h
|
||||||
src/gui/dynamicshortcutswidget.h
|
src/gui/dynamicshortcutswidget.h
|
||||||
src/gui/webbrowser.h
|
|
||||||
src/gui/webview.h
|
|
||||||
src/gui/baselineedit.h
|
src/gui/baselineedit.h
|
||||||
src/gui/locationlineedit.h
|
src/gui/locationlineedit.h
|
||||||
src/gui/tabwidget.h
|
src/gui/tabwidget.h
|
||||||
@ -373,10 +371,7 @@ set(APP_HEADERS
|
|||||||
# CORE headers.
|
# CORE headers.
|
||||||
src/core/settings.h
|
src/core/settings.h
|
||||||
src/core/localization.h
|
src/core/localization.h
|
||||||
src/core/basenetworkaccessmanager.h
|
src/network-web/webpage.h
|
||||||
src/core/webbrowsernetworkaccessmanager.h
|
|
||||||
src/core/silentnetworkaccessmanager.h
|
|
||||||
src/core/webpage.h
|
|
||||||
src/core/systemfactory.h
|
src/core/systemfactory.h
|
||||||
src/core/databasefactory.h
|
src/core/databasefactory.h
|
||||||
src/core/messagesmodel.h
|
src/core/messagesmodel.h
|
||||||
@ -384,7 +379,14 @@ set(APP_HEADERS
|
|||||||
src/core/feedsmodel.h
|
src/core/feedsmodel.h
|
||||||
src/core/feedsproxymodel.h
|
src/core/feedsproxymodel.h
|
||||||
src/core/feeddownloader.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.
|
# Add form files.
|
||||||
@ -454,6 +456,7 @@ endif(${USE_QT_5})
|
|||||||
include_directories (
|
include_directories (
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/gui
|
${CMAKE_CURRENT_SOURCE_DIR}/src/gui
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src/network-web
|
||||||
${CMAKE_CURRENT_BINARY_DIR}
|
${CMAKE_CURRENT_BINARY_DIR}
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/src
|
${CMAKE_CURRENT_BINARY_DIR}/src
|
||||||
)
|
)
|
||||||
|
@ -5,6 +5,7 @@ Fixed:
|
|||||||
<ul>
|
<ul>
|
||||||
<li>Informative buttons now do not accept focus.</li>
|
<li>Informative buttons now do not accept focus.</li>
|
||||||
<li>Button for resetting keyboard shortcut now works.</li>
|
<li>Button for resetting keyboard shortcut now works.</li>
|
||||||
|
<li>Fixed web browser tab title/icon handling (bug #39).</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
Added:
|
Added:
|
||||||
@ -19,6 +20,7 @@ Added:
|
|||||||
|
|
||||||
Changed:
|
Changed:
|
||||||
<ul>
|
<ul>
|
||||||
|
<li>Massive code cleanups.</li>
|
||||||
<li>Removed "progress bar" from address text edit of web browser.</li>
|
<li>Removed "progress bar" from address text edit of web browser.</li>
|
||||||
<li>Removed "blau" skin due to its slowness.</li>
|
<li>Removed "blau" skin due to its slowness.</li>
|
||||||
<li>Tab order and default widget changed for category/feed add/edit dialogs.</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/defs.h"
|
||||||
#include "core/databasefactory.h"
|
#include "core/databasefactory.h"
|
||||||
#include "core/feedsmodelstandardcategory.h"
|
#include "core/feedsmodelcategory.h"
|
||||||
#include "core/feedsmodelstandardfeed.h"
|
#include "core/feedsmodelfeed.h"
|
||||||
#include "core/textfactory.h"
|
#include "core/textfactory.h"
|
||||||
#include "gui/iconthemefactory.h"
|
#include "gui/iconthemefactory.h"
|
||||||
#include "gui/iconfactory.h"
|
#include "gui/iconfactory.h"
|
||||||
@ -177,7 +177,7 @@ bool FeedsModel::removeItem(const QModelIndex &index) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FeedsModel::addStandardCategory(FeedsModelStandardCategory *category,
|
bool FeedsModel::addCategory(FeedsModelCategory *category,
|
||||||
FeedsModelRootItem *parent) {
|
FeedsModelRootItem *parent) {
|
||||||
// Get index of parent item (parent standard category).
|
// Get index of parent item (parent standard category).
|
||||||
QModelIndex parent_index = indexForItem(parent);
|
QModelIndex parent_index = indexForItem(parent);
|
||||||
@ -225,8 +225,8 @@ bool FeedsModel::addStandardCategory(FeedsModelStandardCategory *category,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FeedsModel::editStandardCategory(FeedsModelStandardCategory *original_category,
|
bool FeedsModel::editCategory(FeedsModelCategory *original_category,
|
||||||
FeedsModelStandardCategory *new_category) {
|
FeedsModelCategory *new_category) {
|
||||||
QSqlDatabase database = DatabaseFactory::instance()->connection(objectName(),
|
QSqlDatabase database = DatabaseFactory::instance()->connection(objectName(),
|
||||||
DatabaseFactory::FromSettings);
|
DatabaseFactory::FromSettings);
|
||||||
QSqlQuery query_update_category(database);
|
QSqlQuery query_update_category(database);
|
||||||
@ -281,7 +281,7 @@ bool FeedsModel::editStandardCategory(FeedsModelStandardCategory *original_categ
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FeedsModel::addStandardFeed(FeedsModelStandardFeed *feed,
|
bool FeedsModel::addFeed(FeedsModelFeed *feed,
|
||||||
FeedsModelRootItem *parent) {
|
FeedsModelRootItem *parent) {
|
||||||
// Get index of parent item (parent standard category).
|
// Get index of parent item (parent standard category).
|
||||||
QModelIndex parent_index = indexForItem(parent);
|
QModelIndex parent_index = indexForItem(parent);
|
||||||
@ -336,8 +336,8 @@ bool FeedsModel::addStandardFeed(FeedsModelStandardFeed *feed,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FeedsModel::editStandardFeed(FeedsModelStandardFeed *original_feed,
|
bool FeedsModel::editFeed(FeedsModelFeed *original_feed,
|
||||||
FeedsModelStandardFeed *new_feed) {
|
FeedsModelFeed *new_feed) {
|
||||||
QSqlDatabase database = DatabaseFactory::instance()->connection(objectName(),
|
QSqlDatabase database = DatabaseFactory::instance()->connection(objectName(),
|
||||||
DatabaseFactory::FromSettings);
|
DatabaseFactory::FromSettings);
|
||||||
QSqlQuery query_update_feed(database);
|
QSqlQuery query_update_feed(database);
|
||||||
@ -413,34 +413,32 @@ QList<FeedsModelFeed*> FeedsModel::feedsForScheduledUpdate(bool auto_update_now)
|
|||||||
QList<FeedsModelFeed*> feeds_for_update;
|
QList<FeedsModelFeed*> feeds_for_update;
|
||||||
|
|
||||||
foreach (FeedsModelFeed *feed, allFeeds()) {
|
foreach (FeedsModelFeed *feed, allFeeds()) {
|
||||||
FeedsModelStandardFeed *std_feed = static_cast<FeedsModelStandardFeed*>(feed);
|
switch (feed->autoUpdateType()) {
|
||||||
|
case FeedsModelFeed::DontAutoUpdate:
|
||||||
switch (std_feed->autoUpdateType()) {
|
|
||||||
case FeedsModelStandardFeed::DontAutoUpdate:
|
|
||||||
// Do not auto-update this feed ever.
|
// Do not auto-update this feed ever.
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case FeedsModelStandardFeed::DefaultAutoUpdate:
|
case FeedsModelFeed::DefaultAutoUpdate:
|
||||||
if (auto_update_now) {
|
if (auto_update_now) {
|
||||||
feeds_for_update.append(feed);
|
feeds_for_update.append(feed);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FeedsModelStandardFeed::SpecificAutoUpdate:
|
case FeedsModelFeed::SpecificAutoUpdate:
|
||||||
default:
|
default:
|
||||||
int remaining_interval = std_feed->autoUpdateRemainingInterval();
|
int remaining_interval = feed->autoUpdateRemainingInterval();
|
||||||
|
|
||||||
if (--remaining_interval <= 0) {
|
if (--remaining_interval <= 0) {
|
||||||
// Interval of this feed passed, include this feed in the output list
|
// Interval of this feed passed, include this feed in the output list
|
||||||
// and reset the interval.
|
// and reset the interval.
|
||||||
feeds_for_update.append(feed);
|
feeds_for_update.append(feed);
|
||||||
std_feed->setAutoUpdateRemainingInterval(std_feed->autoUpdateInitialInterval());
|
feed->setAutoUpdateRemainingInterval(feed->autoUpdateInitialInterval());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Interval did not pass, set new decremented interval and do NOT
|
// Interval did not pass, set new decremented interval and do NOT
|
||||||
// include this feed in the output list.
|
// include this feed in the output list.
|
||||||
std_feed->setAutoUpdateRemainingInterval(remaining_interval);
|
feed->setAutoUpdateRemainingInterval(remaining_interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -613,13 +611,12 @@ void FeedsModel::loadFromDatabase() {
|
|||||||
case FeedsModelCategory::Standard: {
|
case FeedsModelCategory::Standard: {
|
||||||
CategoryAssignmentItem pair;
|
CategoryAssignmentItem pair;
|
||||||
pair.first = query_categories.value(CAT_DB_PARENT_ID_INDEX).toInt();
|
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;
|
categories << pair;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case FeedsModelCategory::Feedly:
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -639,13 +636,13 @@ void FeedsModel::loadFromDatabase() {
|
|||||||
FeedsModelFeed::Type type = static_cast<FeedsModelFeed::Type>(query_feeds.value(FDS_DB_TYPE_INDEX).toInt());
|
FeedsModelFeed::Type type = static_cast<FeedsModelFeed::Type>(query_feeds.value(FDS_DB_TYPE_INDEX).toInt());
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case FeedsModelFeed::StandardAtom10:
|
case FeedsModelFeed::Atom10:
|
||||||
case FeedsModelFeed::StandardRdf:
|
case FeedsModelFeed::Rdf:
|
||||||
case FeedsModelFeed::StandardRss0X:
|
case FeedsModelFeed::Rss0X:
|
||||||
case FeedsModelFeed::StandardRss2X: {
|
case FeedsModelFeed::Rss2X: {
|
||||||
FeedAssignmentItem pair;
|
FeedAssignmentItem pair;
|
||||||
pair.first = query_feeds.value(FDS_DB_CATEGORY_INDEX).toInt();
|
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);
|
pair.second->setType(type);
|
||||||
|
|
||||||
feeds << pair;
|
feeds << pair;
|
||||||
|
@ -28,8 +28,6 @@
|
|||||||
|
|
||||||
class FeedsModelCategory;
|
class FeedsModelCategory;
|
||||||
class FeedsModelFeed;
|
class FeedsModelFeed;
|
||||||
class FeedsModelStandardCategory;
|
|
||||||
class FeedsModelStandardFeed;
|
|
||||||
|
|
||||||
typedef QList<QPair<int, FeedsModelCategory*> > CategoryAssignment;
|
typedef QList<QPair<int, FeedsModelCategory*> > CategoryAssignment;
|
||||||
typedef QPair<int, FeedsModelCategory*> CategoryAssignmentItem;
|
typedef QPair<int, FeedsModelCategory*> CategoryAssignmentItem;
|
||||||
@ -72,20 +70,20 @@ class FeedsModel : public QAbstractItemModel {
|
|||||||
bool removeItem(const QModelIndex &index);
|
bool removeItem(const QModelIndex &index);
|
||||||
|
|
||||||
// Standard category manipulators.
|
// Standard category manipulators.
|
||||||
bool addStandardCategory(FeedsModelStandardCategory *category,
|
bool addCategory(FeedsModelCategory *category,
|
||||||
FeedsModelRootItem *parent);
|
FeedsModelRootItem *parent);
|
||||||
bool editStandardCategory(FeedsModelStandardCategory *original_category,
|
bool editCategory(FeedsModelCategory *original_category,
|
||||||
FeedsModelStandardCategory *new_category);
|
FeedsModelCategory *new_category);
|
||||||
|
|
||||||
// Standard feed manipulators.
|
// Standard feed manipulators.
|
||||||
bool addStandardFeed(FeedsModelStandardFeed *feed,
|
bool addFeed(FeedsModelFeed *feed,
|
||||||
FeedsModelRootItem *parent);
|
FeedsModelRootItem *parent);
|
||||||
|
|
||||||
// New feed is just temporary feed, it is not added to the model.
|
// New feed is just temporary feed, it is not added to the model.
|
||||||
// It is used to fetch its data to the original feed
|
// It is used to fetch its data to the original feed
|
||||||
// and the original feed is moved if needed.
|
// and the original feed is moved if needed.
|
||||||
bool editStandardFeed(FeedsModelStandardFeed *original_feed,
|
bool editFeed(FeedsModelFeed *original_feed,
|
||||||
FeedsModelStandardFeed *new_feed);
|
FeedsModelFeed *new_feed);
|
||||||
|
|
||||||
// Returns the list of updates which should be updated
|
// Returns the list of updates which should be updated
|
||||||
// according to auto-update schedule.
|
// according to auto-update schedule.
|
||||||
|
@ -17,12 +17,20 @@
|
|||||||
|
|
||||||
#include "core/feedsmodelcategory.h"
|
#include "core/feedsmodelcategory.h"
|
||||||
|
|
||||||
#include "core/feedsmodelstandardcategory.h"
|
#include "core/defs.h"
|
||||||
#include "core/feedsmodelstandardfeed.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)
|
FeedsModelCategory::FeedsModelCategory(FeedsModelRootItem *parent_item)
|
||||||
: FeedsModelRootItem(parent_item) {
|
: FeedsModelRootItem(parent_item) {
|
||||||
|
m_type = Standard;
|
||||||
m_kind = FeedsModelRootItem::Category;
|
m_kind = FeedsModelRootItem::Category;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,4 +48,113 @@ FeedsModelCategory::FeedsModelCategory(const FeedsModelCategory &other)
|
|||||||
}
|
}
|
||||||
|
|
||||||
FeedsModelCategory::~FeedsModelCategory() {
|
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 "core/feedsmodelrootitem.h"
|
||||||
|
|
||||||
|
#include <QSqlRecord>
|
||||||
|
#include <QApplication>
|
||||||
|
|
||||||
|
|
||||||
class FeedsModelFeed;
|
class FeedsModelFeed;
|
||||||
|
|
||||||
@ -27,12 +30,13 @@ class FeedsModelFeed;
|
|||||||
// NOTE: This class should be derived to create PARTICULAR category types.
|
// NOTE: This class should be derived to create PARTICULAR category types.
|
||||||
// NOTE: This class should not be instantiated directly.
|
// NOTE: This class should not be instantiated directly.
|
||||||
class FeedsModelCategory : public FeedsModelRootItem {
|
class FeedsModelCategory : public FeedsModelRootItem {
|
||||||
|
Q_DECLARE_TR_FUNCTIONS(FeedsModelCategory)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Describes possible types of categories.
|
// Describes possible types of categories.
|
||||||
// NOTE: This is equivavelnt to Categories(type).
|
// NOTE: This is equivavelnt to Categories(type).
|
||||||
enum Type {
|
enum Type {
|
||||||
Standard = 0,
|
Standard = 0
|
||||||
Feedly = 1
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Constructors and destructors
|
// Constructors and destructors
|
||||||
@ -40,6 +44,13 @@ class FeedsModelCategory : public FeedsModelRootItem {
|
|||||||
explicit FeedsModelCategory(const FeedsModelCategory &other);
|
explicit FeedsModelCategory(const FeedsModelCategory &other);
|
||||||
virtual ~FeedsModelCategory();
|
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.
|
// All types of categories offer these getters/setters.
|
||||||
inline Type type() const {
|
inline Type type() const {
|
||||||
return m_type;
|
return m_type;
|
||||||
@ -49,6 +60,9 @@ class FeedsModelCategory : public FeedsModelRootItem {
|
|||||||
m_type = type;
|
m_type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Loads particular "standard category" from given sql record.
|
||||||
|
static FeedsModelCategory *loadFromRecord(const QSqlRecord &record);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Type m_type;
|
Type m_type;
|
||||||
};
|
};
|
||||||
|
@ -17,23 +17,38 @@
|
|||||||
|
|
||||||
#include "core/feedsmodelfeed.h"
|
#include "core/feedsmodelfeed.h"
|
||||||
|
|
||||||
|
#include "core/defs.h"
|
||||||
|
#include "core/settings.h"
|
||||||
|
#include "core/parsingfactory.h"
|
||||||
#include "core/databasefactory.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 <QSqlDatabase>
|
||||||
#include <QSqlQuery>
|
#include <QSqlQuery>
|
||||||
#include <QSqlError>
|
#include <QSqlError>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
#include <QTextCodec>
|
||||||
|
#include <QDomDocument>
|
||||||
|
#include <QDomNode>
|
||||||
|
#include <QDomElement>
|
||||||
|
#include <QXmlStreamReader>
|
||||||
|
|
||||||
|
|
||||||
FeedsModelFeed::FeedsModelFeed(FeedsModelRootItem *parent_item)
|
FeedsModelFeed::FeedsModelFeed(FeedsModelRootItem *parent_item)
|
||||||
: FeedsModelRootItem(parent_item),
|
: FeedsModelRootItem(parent_item),
|
||||||
m_type(StandardRss0X),
|
m_type(Rss0X),
|
||||||
m_totalCount(0),
|
m_totalCount(0),
|
||||||
m_unreadCount(0) {
|
m_unreadCount(0),
|
||||||
|
m_autoUpdateType(DontAutoUpdate),
|
||||||
|
m_autoUpdateInitialInterval(DEFAULT_AUTO_UPDATE_INTERVAL) {
|
||||||
m_kind = FeedsModelRootItem::Feed;
|
m_kind = FeedsModelRootItem::Feed;
|
||||||
}
|
}
|
||||||
|
|
||||||
FeedsModelFeed::~FeedsModelFeed() {
|
FeedsModelFeed::~FeedsModelFeed() {
|
||||||
|
qDebug("Destroying FeedsModelFeed instance.");
|
||||||
}
|
}
|
||||||
|
|
||||||
int FeedsModelFeed::childCount() const {
|
int FeedsModelFeed::childCount() const {
|
||||||
@ -51,16 +66,16 @@ int FeedsModelFeed::countOfUnreadMessages() const {
|
|||||||
|
|
||||||
QString FeedsModelFeed::typeToString(FeedsModelFeed::Type type) {
|
QString FeedsModelFeed::typeToString(FeedsModelFeed::Type type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case StandardAtom10:
|
case Atom10:
|
||||||
return "ATOM 1.0";
|
return "ATOM 1.0";
|
||||||
|
|
||||||
case StandardRdf:
|
case Rdf:
|
||||||
return "RDF";
|
return "RDF (RSS 1.0)";
|
||||||
|
|
||||||
case StandardRss0X:
|
case Rss0X:
|
||||||
return "RSS 0.91/0.92/0.93";
|
return "RSS 0.91/0.92/0.93";
|
||||||
|
|
||||||
case StandardRss2X:
|
case Rss2X:
|
||||||
default:
|
default:
|
||||||
return "RSS 2.0/2.0.1";
|
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 "core/feedsmodelrootitem.h"
|
||||||
|
|
||||||
#include <QMetaType>
|
#include <QMetaType>
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QSqlRecord>
|
||||||
|
#include <QPair>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
#include <QApplication>
|
||||||
|
|
||||||
|
|
||||||
|
class Message;
|
||||||
|
|
||||||
|
|
||||||
// Represents BASE class for feeds contained in FeedsModel.
|
// Represents BASE class for feeds contained in FeedsModel.
|
||||||
// NOTE: This class should be derived to create PARTICULAR feed types.
|
// NOTE: This class should be derived to create PARTICULAR feed types.
|
||||||
class FeedsModelFeed : public FeedsModelRootItem {
|
class FeedsModelFeed : public FeedsModelRootItem {
|
||||||
|
Q_DECLARE_TR_FUNCTIONS(FeedsModelFeed)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Describes possible types of feeds.
|
// Describes possible types of feeds.
|
||||||
// NOTE: This is equivalent to attribute Feeds(type).
|
// NOTE: This is equivalent to attribute Feeds(type).
|
||||||
enum Type {
|
enum Type {
|
||||||
StandardRss0X = 0,
|
Rss0X = 0,
|
||||||
StandardRss2X = 1,
|
Rss2X = 1,
|
||||||
StandardRdf = 2,
|
Rdf = 2,
|
||||||
StandardAtom10 = 3
|
Atom10 = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
// Specifies the auto-update strategy for the feed.
|
||||||
|
enum AutoUpdateType {
|
||||||
|
DontAutoUpdate = 0,
|
||||||
|
DefaultAutoUpdate = 1,
|
||||||
|
SpecificAutoUpdate = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
// Constructors and destructors.
|
// Constructors and destructors.
|
||||||
@ -49,12 +66,15 @@ class FeedsModelFeed : public FeedsModelRootItem {
|
|||||||
int countOfAllMessages() const;
|
int countOfAllMessages() const;
|
||||||
int countOfUnreadMessages() const;
|
int countOfUnreadMessages() const;
|
||||||
|
|
||||||
// Each feed can be "updated".
|
// Obtains data related to this feed.
|
||||||
// NOTE: This method is used in the "update worker".
|
QVariant data(int column, int role) const;
|
||||||
// For example, it can fetch new messages from a remote destination
|
|
||||||
// and store them in a local database and so on.
|
// Perform fetching of new messages.
|
||||||
virtual void update() {
|
void update();
|
||||||
}
|
|
||||||
|
// Removes this standard feed from persistent
|
||||||
|
// storage.
|
||||||
|
bool removeItself();
|
||||||
|
|
||||||
// Other getters/setters.
|
// Other getters/setters.
|
||||||
inline Type type() const {
|
inline Type type() const {
|
||||||
@ -89,6 +109,61 @@ class FeedsModelFeed : public FeedsModelRootItem {
|
|||||||
m_password = password;
|
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.
|
// Converts particular feed type to string.
|
||||||
static QString typeToString(Type type);
|
static QString typeToString(Type type);
|
||||||
|
|
||||||
@ -97,6 +172,12 @@ class FeedsModelFeed : public FeedsModelRootItem {
|
|||||||
void updateCounts(bool including_total_count = true);
|
void updateCounts(bool including_total_count = true);
|
||||||
|
|
||||||
protected:
|
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;
|
bool m_passwordProtected;
|
||||||
QString m_username;
|
QString m_username;
|
||||||
QString m_password;
|
QString m_password;
|
||||||
@ -104,6 +185,13 @@ class FeedsModelFeed : public FeedsModelRootItem {
|
|||||||
Type m_type;
|
Type m_type;
|
||||||
int m_totalCount;
|
int m_totalCount;
|
||||||
int m_unreadCount;
|
int m_unreadCount;
|
||||||
|
|
||||||
|
AutoUpdateType m_autoUpdateType;
|
||||||
|
int m_autoUpdateInitialInterval;
|
||||||
|
int m_autoUpdateRemainingInterval;
|
||||||
|
|
||||||
|
QString m_encoding;
|
||||||
|
QString m_url;
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(FeedsModelFeed::Type)
|
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/parsingfactory.h"
|
||||||
|
|
||||||
#include "core/webfactory.h"
|
|
||||||
#include "core/textfactory.h"
|
#include "core/textfactory.h"
|
||||||
|
#include "network-web/webfactory.h"
|
||||||
|
|
||||||
#include <QDomDocument>
|
#include <QDomDocument>
|
||||||
#include <QDomElement>
|
#include <QDomElement>
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
#include "core/systemfactory.h"
|
#include "core/systemfactory.h"
|
||||||
|
|
||||||
#include "core/defs.h"
|
#include "core/defs.h"
|
||||||
#include "core/networkfactory.h"
|
#include "network-web/networkfactory.h"
|
||||||
|
|
||||||
#if defined(Q_OS_WIN)
|
#if defined(Q_OS_WIN)
|
||||||
#include "qtsingleapplication/qtsingleapplication.h"
|
#include "qtsingleapplication/qtsingleapplication.h"
|
||||||
|
@ -21,9 +21,9 @@
|
|||||||
#include "core/databasefactory.h"
|
#include "core/databasefactory.h"
|
||||||
#include "core/messagesproxymodel.h"
|
#include "core/messagesproxymodel.h"
|
||||||
#include "core/feeddownloader.h"
|
#include "core/feeddownloader.h"
|
||||||
#include "core/feedsmodelstandardfeed.h"
|
#include "core/feedsmodelfeed.h"
|
||||||
#include "core/systemfactory.h"
|
#include "core/systemfactory.h"
|
||||||
#include "gui/webbrowser.h"
|
#include "network-web/webbrowser.h"
|
||||||
#include "gui/formmain.h"
|
#include "gui/formmain.h"
|
||||||
#include "gui/iconthemefactory.h"
|
#include "gui/iconthemefactory.h"
|
||||||
#include "gui/messagesview.h"
|
#include "gui/messagesview.h"
|
||||||
@ -249,10 +249,10 @@ void FeedMessageViewer::createConnections() {
|
|||||||
SIGNAL(triggered()), m_feedsView, SLOT(updateSelectedFeeds()));
|
SIGNAL(triggered()), m_feedsView, SLOT(updateSelectedFeeds()));
|
||||||
connect(form_main->m_ui->m_actionUpdateAllFeeds,
|
connect(form_main->m_ui->m_actionUpdateAllFeeds,
|
||||||
SIGNAL(triggered()), m_feedsView, SLOT(updateAllFeeds()));
|
SIGNAL(triggered()), m_feedsView, SLOT(updateAllFeeds()));
|
||||||
connect(form_main->m_ui->m_actionAddStandardCategory,
|
connect(form_main->m_ui->m_actionAddCategory,
|
||||||
SIGNAL(triggered()), m_feedsView, SLOT(addNewStandardCategory()));
|
SIGNAL(triggered()), m_feedsView, SLOT(addNewCategory()));
|
||||||
connect(form_main->m_ui->m_actionAddStandardFeed,
|
connect(form_main->m_ui->m_actionAddFeed,
|
||||||
SIGNAL(triggered()), m_feedsView, SLOT(addNewStandardFeed()));
|
SIGNAL(triggered()), m_feedsView, SLOT(addNewFeed()));
|
||||||
connect(form_main->m_ui->m_actionEditSelectedFeedCategory,
|
connect(form_main->m_ui->m_actionEditSelectedFeedCategory,
|
||||||
SIGNAL(triggered()), m_feedsView, SLOT(editSelectedItem()));
|
SIGNAL(triggered()), m_feedsView, SLOT(editSelectedItem()));
|
||||||
connect(form_main->m_ui->m_actionViewSelectedItemsNewspaperMode,
|
connect(form_main->m_ui->m_actionViewSelectedItemsNewspaperMode,
|
||||||
|
@ -24,8 +24,7 @@
|
|||||||
#include "core/feedsproxymodel.h"
|
#include "core/feedsproxymodel.h"
|
||||||
#include "core/feedsmodelrootitem.h"
|
#include "core/feedsmodelrootitem.h"
|
||||||
#include "core/feedsmodelcategory.h"
|
#include "core/feedsmodelcategory.h"
|
||||||
#include "core/feedsmodelstandardfeed.h"
|
#include "core/feedsmodelfeed.h"
|
||||||
#include "core/feedsmodelstandardcategory.h"
|
|
||||||
#include "gui/formmain.h"
|
#include "gui/formmain.h"
|
||||||
#include "gui/formstandardcategorydetails.h"
|
#include "gui/formstandardcategorydetails.h"
|
||||||
#include "gui/formstandardfeeddetails.h"
|
#include "gui/formstandardfeeddetails.h"
|
||||||
@ -250,7 +249,7 @@ void FeedsView::clearAllFeeds() {
|
|||||||
setAllFeedsClearStatus(1);
|
setAllFeedsClearStatus(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FeedsView::addNewStandardCategory() {
|
void FeedsView::addNewCategory() {
|
||||||
if (!SystemFactory::instance()->applicationCloseLock()->tryLock()) {
|
if (!SystemFactory::instance()->applicationCloseLock()->tryLock()) {
|
||||||
// Lock was not obtained because
|
// Lock was not obtained because
|
||||||
// it is used probably by feed updater or application
|
// it is used probably by feed updater or application
|
||||||
@ -281,7 +280,7 @@ void FeedsView::addNewStandardCategory() {
|
|||||||
SystemFactory::instance()->applicationCloseLock()->unlock();
|
SystemFactory::instance()->applicationCloseLock()->unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FeedsView::editStandardCategory(FeedsModelStandardCategory *category) {
|
void FeedsView::editCategory(FeedsModelCategory *category) {
|
||||||
QPointer<FormStandardCategoryDetails> form_pointer = new FormStandardCategoryDetails(m_sourceModel, this);
|
QPointer<FormStandardCategoryDetails> form_pointer = new FormStandardCategoryDetails(m_sourceModel, this);
|
||||||
|
|
||||||
form_pointer.data()->exec(category);
|
form_pointer.data()->exec(category);
|
||||||
@ -289,7 +288,7 @@ void FeedsView::editStandardCategory(FeedsModelStandardCategory *category) {
|
|||||||
delete form_pointer.data();
|
delete form_pointer.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FeedsView::addNewStandardFeed() {
|
void FeedsView::addNewFeed() {
|
||||||
if (!SystemFactory::instance()->applicationCloseLock()->tryLock()) {
|
if (!SystemFactory::instance()->applicationCloseLock()->tryLock()) {
|
||||||
// Lock was not obtained because
|
// Lock was not obtained because
|
||||||
// it is used probably by feed updater or application
|
// it is used probably by feed updater or application
|
||||||
@ -320,7 +319,7 @@ void FeedsView::addNewStandardFeed() {
|
|||||||
SystemFactory::instance()->applicationCloseLock()->unlock();
|
SystemFactory::instance()->applicationCloseLock()->unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FeedsView::editStandardFeed(FeedsModelStandardFeed *feed) {
|
void FeedsView::editFeed(FeedsModelFeed *feed) {
|
||||||
QPointer<FormStandardFeedDetails> form_pointer = new FormStandardFeedDetails(m_sourceModel, this);
|
QPointer<FormStandardFeedDetails> form_pointer = new FormStandardFeedDetails(m_sourceModel, this);
|
||||||
|
|
||||||
form_pointer.data()->exec(feed);
|
form_pointer.data()->exec(feed);
|
||||||
@ -359,7 +358,7 @@ void FeedsView::editSelectedItem() {
|
|||||||
switch (category->type()) {
|
switch (category->type()) {
|
||||||
case FeedsModelCategory::Standard: {
|
case FeedsModelCategory::Standard: {
|
||||||
// User wants to edit standard category.
|
// User wants to edit standard category.
|
||||||
editStandardCategory(static_cast<FeedsModelStandardCategory*>(category));
|
editCategory(static_cast<FeedsModelCategory*>(category));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,12 +369,12 @@ void FeedsView::editSelectedItem() {
|
|||||||
else if ((feed = isCurrentIndexFeed()) != NULL) {
|
else if ((feed = isCurrentIndexFeed()) != NULL) {
|
||||||
// Feed is selected.
|
// Feed is selected.
|
||||||
switch (feed->type()) {
|
switch (feed->type()) {
|
||||||
case FeedsModelFeed::StandardAtom10:
|
case FeedsModelFeed::Atom10:
|
||||||
case FeedsModelFeed::StandardRdf:
|
case FeedsModelFeed::Rdf:
|
||||||
case FeedsModelFeed::StandardRss0X:
|
case FeedsModelFeed::Rss0X:
|
||||||
case FeedsModelFeed::StandardRss2X: {
|
case FeedsModelFeed::Rss2X: {
|
||||||
// User wants to edit standard feed.
|
// User wants to edit standard feed.
|
||||||
editStandardFeed(static_cast<FeedsModelStandardFeed*>(feed));
|
editFeed(static_cast<FeedsModelFeed*>(feed));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -431,6 +430,8 @@ void FeedsView::deleteSelectedItem() {
|
|||||||
|
|
||||||
if (m_sourceModel->removeItem(m_proxyModel->mapToSource(current_index))) {
|
if (m_sourceModel->removeItem(m_proxyModel->mapToSource(current_index))) {
|
||||||
// Item WAS removed, update counts.
|
// 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);
|
updateCountsOfAllFeeds(true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -551,7 +552,8 @@ void FeedsView::initializeContextMenuEmptySpace() {
|
|||||||
m_contextMenuEmptySpace = new QMenu(tr("Context menu for feeds"), this);
|
m_contextMenuEmptySpace = new QMenu(tr("Context menu for feeds"), this);
|
||||||
m_contextMenuEmptySpace->addActions(QList<QAction*>() <<
|
m_contextMenuEmptySpace->addActions(QList<QAction*>() <<
|
||||||
FormMain::instance()->m_ui->m_actionUpdateAllFeeds <<
|
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() {
|
void FeedsView::setupAppearance() {
|
||||||
|
@ -38,6 +38,7 @@ class FeedsView : public QTreeView {
|
|||||||
explicit FeedsView(QWidget *parent = 0);
|
explicit FeedsView(QWidget *parent = 0);
|
||||||
virtual ~FeedsView();
|
virtual ~FeedsView();
|
||||||
|
|
||||||
|
// Fundamental accessors.
|
||||||
inline FeedsProxyModel *model() {
|
inline FeedsProxyModel *model() {
|
||||||
return m_proxyModel;
|
return m_proxyModel;
|
||||||
}
|
}
|
||||||
@ -66,6 +67,8 @@ class FeedsView : public QTreeView {
|
|||||||
FeedsModelCategory *isCurrentIndexCategory() const;
|
FeedsModelCategory *isCurrentIndexCategory() const;
|
||||||
FeedsModelFeed *isCurrentIndexFeed() const;
|
FeedsModelFeed *isCurrentIndexFeed() const;
|
||||||
|
|
||||||
|
// Saves/loads expand states of all nodes (feeds/categories) of the list
|
||||||
|
// to/from settings.
|
||||||
void saveExpandedStates();
|
void saveExpandedStates();
|
||||||
void loadExpandedStates();
|
void loadExpandedStates();
|
||||||
|
|
||||||
@ -82,7 +85,6 @@ class FeedsView : public QTreeView {
|
|||||||
void markSelectedFeedsReadStatus(int read);
|
void markSelectedFeedsReadStatus(int read);
|
||||||
void markSelectedFeedsRead();
|
void markSelectedFeedsRead();
|
||||||
void markSelectedFeedsUnread();
|
void markSelectedFeedsUnread();
|
||||||
|
|
||||||
void markAllFeedsReadStatus(int read);
|
void markAllFeedsReadStatus(int read);
|
||||||
void markAllFeedsRead();
|
void markAllFeedsRead();
|
||||||
|
|
||||||
@ -101,12 +103,12 @@ class FeedsView : public QTreeView {
|
|||||||
void deleteSelectedItem();
|
void deleteSelectedItem();
|
||||||
|
|
||||||
// Standard category manipulators.
|
// Standard category manipulators.
|
||||||
void addNewStandardCategory();
|
void addNewCategory();
|
||||||
void editStandardCategory(FeedsModelStandardCategory *category);
|
void editCategory(FeedsModelCategory *category);
|
||||||
|
|
||||||
// Standard feed manipulators.
|
// Standard feed manipulators.
|
||||||
void addNewStandardFeed();
|
void addNewFeed();
|
||||||
void editStandardFeed(FeedsModelStandardFeed *feed);
|
void editFeed(FeedsModelFeed *feed);
|
||||||
|
|
||||||
// Reloads counts for selected feeds.
|
// Reloads counts for selected feeds.
|
||||||
void updateCountsOfSelectedFeeds(bool update_total_too = true);
|
void updateCountsOfSelectedFeeds(bool update_total_too = true);
|
||||||
@ -124,6 +126,7 @@ class FeedsView : public QTreeView {
|
|||||||
m_sourceModel->countOfAllMessages());
|
m_sourceModel->countOfAllMessages());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Selects next/previous item (feed/category) in the list.
|
||||||
void selectNextItem();
|
void selectNextItem();
|
||||||
void selectPreviousItem();
|
void selectPreviousItem();
|
||||||
|
|
||||||
|
@ -21,12 +21,12 @@
|
|||||||
#include "core/settings.h"
|
#include "core/settings.h"
|
||||||
#include "core/systemfactory.h"
|
#include "core/systemfactory.h"
|
||||||
#include "core/databasefactory.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/formabout.h"
|
||||||
#include "gui/formsettings.h"
|
#include "gui/formsettings.h"
|
||||||
#include "gui/feedsview.h"
|
#include "gui/feedsview.h"
|
||||||
#include "gui/messagebox.h"
|
#include "gui/messagebox.h"
|
||||||
#include "gui/webbrowser.h"
|
|
||||||
#include "gui/iconthemefactory.h"
|
#include "gui/iconthemefactory.h"
|
||||||
#include "gui/systemtrayicon.h"
|
#include "gui/systemtrayicon.h"
|
||||||
#include "gui/tabbar.h"
|
#include "gui/tabbar.h"
|
||||||
@ -115,8 +115,8 @@ QList<QAction*> FormMain::allActions() {
|
|||||||
m_ui->m_actionEditSelectedFeedCategory <<
|
m_ui->m_actionEditSelectedFeedCategory <<
|
||||||
m_ui->m_actionDeleteSelectedFeedCategory <<
|
m_ui->m_actionDeleteSelectedFeedCategory <<
|
||||||
m_ui->m_actionViewSelectedItemsNewspaperMode <<
|
m_ui->m_actionViewSelectedItemsNewspaperMode <<
|
||||||
m_ui->m_actionAddStandardCategory <<
|
m_ui->m_actionAddCategory <<
|
||||||
m_ui->m_actionAddStandardFeed <<
|
m_ui->m_actionAddFeed <<
|
||||||
m_ui->m_actionSelectNextFeedCategory <<
|
m_ui->m_actionSelectNextFeedCategory <<
|
||||||
m_ui->m_actionSelectPreviousFeedCategory <<
|
m_ui->m_actionSelectPreviousFeedCategory <<
|
||||||
m_ui->m_actionSelectNextMessage <<
|
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_actionClearAllFeeds->setIcon(icon_theme_factory->fromTheme("mail-remove"));
|
||||||
m_ui->m_actionDeleteSelectedFeedCategory->setIcon(icon_theme_factory->fromTheme("item-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_actionDeleteSelectedMessages->setIcon(icon_theme_factory->fromTheme("mail-remove"));
|
||||||
m_ui->m_actionAddStandardCategory->setIcon(icon_theme_factory->fromTheme("folder-category"));
|
m_ui->m_actionAddCategory->setIcon(icon_theme_factory->fromTheme("folder-category"));
|
||||||
m_ui->m_actionAddStandardFeed->setIcon(icon_theme_factory->fromTheme("folder-feed"));
|
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_actionEditSelectedFeedCategory->setIcon(icon_theme_factory->fromTheme("item-edit"));
|
||||||
m_ui->m_actionMarkAllFeedsRead->setIcon(icon_theme_factory->fromTheme("mail-mark-read"));
|
m_ui->m_actionMarkAllFeedsRead->setIcon(icon_theme_factory->fromTheme("mail-mark-read"));
|
||||||
m_ui->m_actionMarkSelectedFeedsAsRead->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_actionSelectNextMessage->setIcon(icon_theme_factory->fromTheme("go-down"));
|
||||||
m_ui->m_actionSelectPreviousMessage->setIcon(icon_theme_factory->fromTheme("go-up"));
|
m_ui->m_actionSelectPreviousMessage->setIcon(icon_theme_factory->fromTheme("go-up"));
|
||||||
|
|
||||||
|
|
||||||
// Setup icons for underlying components: opened web browsers...
|
// Setup icons for underlying components: opened web browsers...
|
||||||
foreach (WebBrowser *browser, WebBrowser::runningWebBrowsers()) {
|
foreach (WebBrowser *browser, WebBrowser::runningWebBrowsers()) {
|
||||||
browser->setupIcons();
|
browser->setupIcons();
|
||||||
|
@ -15,7 +15,16 @@
|
|||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="centralwidget">
|
<widget class="QWidget" name="centralwidget">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<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>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
@ -39,7 +48,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>979</width>
|
<width>979</width>
|
||||||
<height>20</height>
|
<height>21</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QMenu" name="m_menuFile">
|
<widget class="QMenu" name="m_menuFile">
|
||||||
@ -111,8 +120,8 @@
|
|||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Add &new feed/category</string>
|
<string>Add &new feed/category</string>
|
||||||
</property>
|
</property>
|
||||||
<addaction name="m_actionAddStandardCategory"/>
|
<addaction name="m_actionAddCategory"/>
|
||||||
<addaction name="m_actionAddStandardFeed"/>
|
<addaction name="m_actionAddFeed"/>
|
||||||
</widget>
|
</widget>
|
||||||
<addaction name="m_actionUpdateAllFeeds"/>
|
<addaction name="m_actionUpdateAllFeeds"/>
|
||||||
<addaction name="m_actionUpdateSelectedFeedsCategories"/>
|
<addaction name="m_actionUpdateSelectedFeedsCategories"/>
|
||||||
@ -300,12 +309,12 @@
|
|||||||
<string>Deletes all messages from selected feeds.</string>
|
<string>Deletes all messages from selected feeds.</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="m_actionAddStandardFeed">
|
<action name="m_actionAddFeed">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>New standard &feed</string>
|
<string>New &feed</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Add new standard feed.</string>
|
<string>Add new feed.</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="m_actionOpenSelectedSourceArticlesExternally">
|
<action name="m_actionOpenSelectedSourceArticlesExternally">
|
||||||
@ -323,12 +332,12 @@
|
|||||||
<string>Open selected source articles in &internal browser</string>
|
<string>Open selected source articles in &internal browser</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="m_actionAddStandardCategory">
|
<action name="m_actionAddCategory">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>New standard &category</string>
|
<string>New &category</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Add new standard category.</string>
|
<string>Add new category.</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="m_actionNoActions">
|
<action name="m_actionNoActions">
|
||||||
|
@ -22,11 +22,12 @@
|
|||||||
#include "core/databasefactory.h"
|
#include "core/databasefactory.h"
|
||||||
#include "core/localization.h"
|
#include "core/localization.h"
|
||||||
#include "core/systemfactory.h"
|
#include "core/systemfactory.h"
|
||||||
#include "core/webfactory.h"
|
|
||||||
#include "core/feeddownloader.h"
|
#include "core/feeddownloader.h"
|
||||||
#include "core/dynamicshortcuts.h"
|
#include "core/dynamicshortcuts.h"
|
||||||
#include "core/webbrowsernetworkaccessmanager.h"
|
#include "network-web/webfactory.h"
|
||||||
#include "core/silentnetworkaccessmanager.h"
|
#include "network-web/webbrowsernetworkaccessmanager.h"
|
||||||
|
#include "network-web/silentnetworkaccessmanager.h"
|
||||||
|
#include "network-web/webbrowser.h"
|
||||||
#include "core/feedsmodel.h"
|
#include "core/feedsmodel.h"
|
||||||
#include "gui/iconthemefactory.h"
|
#include "gui/iconthemefactory.h"
|
||||||
#include "gui/skinfactory.h"
|
#include "gui/skinfactory.h"
|
||||||
@ -34,7 +35,6 @@
|
|||||||
#include "gui/feedmessageviewer.h"
|
#include "gui/feedmessageviewer.h"
|
||||||
#include "gui/feedsview.h"
|
#include "gui/feedsview.h"
|
||||||
#include "gui/formmain.h"
|
#include "gui/formmain.h"
|
||||||
#include "gui/webbrowser.h"
|
|
||||||
#include "gui/messagebox.h"
|
#include "gui/messagebox.h"
|
||||||
#include "qtsingleapplication/qtsingleapplication.h"
|
#include "qtsingleapplication/qtsingleapplication.h"
|
||||||
|
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
#include "core/defs.h"
|
#include "core/defs.h"
|
||||||
#include "core/feedsmodelrootitem.h"
|
#include "core/feedsmodelrootitem.h"
|
||||||
#include "core/feedsmodelcategory.h"
|
#include "core/feedsmodelcategory.h"
|
||||||
#include "core/feedsmodelstandardcategory.h"
|
|
||||||
#include "core/feedsmodel.h"
|
#include "core/feedsmodel.h"
|
||||||
#include "gui/iconthemefactory.h"
|
#include "gui/iconthemefactory.h"
|
||||||
#include "gui/feedsview.h"
|
#include "gui/feedsview.h"
|
||||||
@ -70,7 +69,7 @@ void FormStandardCategoryDetails::createConnections() {
|
|||||||
connect(m_actionUseDefaultIcon, SIGNAL(triggered()), this, SLOT(onUseDefaultIcon()));
|
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_editableCategory = editable_category;
|
||||||
|
|
||||||
m_ui->m_cmbParentCategory->setCurrentIndex(m_ui->m_cmbParentCategory->findData(QVariant::fromValue((void*) editable_category->parent())));
|
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());
|
m_ui->m_btnIcon->setIcon(editable_category->icon());
|
||||||
}
|
}
|
||||||
|
|
||||||
int FormStandardCategoryDetails::exec(FeedsModelStandardCategory *input_category) {
|
int FormStandardCategoryDetails::exec(FeedsModelCategory *input_category) {
|
||||||
// Load categories.
|
// Load categories.
|
||||||
loadCategories(m_feedsModel->allCategories().values(),
|
loadCategories(m_feedsModel->allCategories().values(),
|
||||||
m_feedsModel->rootItem(),
|
m_feedsModel->rootItem(),
|
||||||
@ -105,7 +104,7 @@ int FormStandardCategoryDetails::exec(FeedsModelStandardCategory *input_category
|
|||||||
|
|
||||||
void FormStandardCategoryDetails::apply() {
|
void FormStandardCategoryDetails::apply() {
|
||||||
FeedsModelRootItem *parent = static_cast<FeedsModelRootItem*>(m_ui->m_cmbParentCategory->itemData(m_ui->m_cmbParentCategory->currentIndex()).value<void*>());
|
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->setTitle(m_ui->m_txtTitle->lineEdit()->text());
|
||||||
new_category->setCreationDate(QDateTime::currentDateTime());
|
new_category->setCreationDate(QDateTime::currentDateTime());
|
||||||
@ -115,7 +114,7 @@ void FormStandardCategoryDetails::apply() {
|
|||||||
|
|
||||||
if (m_editableCategory == NULL) {
|
if (m_editableCategory == NULL) {
|
||||||
// Add the category.
|
// Add the category.
|
||||||
if (m_feedsModel->addStandardCategory(new_category, parent)) {
|
if (m_feedsModel->addCategory(new_category, parent)) {
|
||||||
accept();
|
accept();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -133,7 +132,7 @@ void FormStandardCategoryDetails::apply() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (m_feedsModel->editStandardCategory(m_editableCategory, new_category)) {
|
if (m_feedsModel->editCategory(m_editableCategory, new_category)) {
|
||||||
accept();
|
accept();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -28,7 +28,7 @@ namespace Ui {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class FeedsModelCategory;
|
class FeedsModelCategory;
|
||||||
class FeedsModelStandardCategory;
|
class FeedsModelCategory;
|
||||||
class FeedsModel;
|
class FeedsModel;
|
||||||
class FeedsModelRootItem;
|
class FeedsModelRootItem;
|
||||||
class QMenu;
|
class QMenu;
|
||||||
@ -44,7 +44,7 @@ class FormStandardCategoryDetails : public QDialog {
|
|||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
// Executes add/edit standard category dialog.
|
// Executes add/edit standard category dialog.
|
||||||
int exec(FeedsModelStandardCategory *input_category);
|
int exec(FeedsModelCategory *input_category);
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
// Applies changes.
|
// Applies changes.
|
||||||
@ -64,7 +64,7 @@ class FormStandardCategoryDetails : public QDialog {
|
|||||||
void createConnections();
|
void createConnections();
|
||||||
|
|
||||||
// Sets the category which will be edited.
|
// Sets the category which will be edited.
|
||||||
void setEditableCategory(FeedsModelStandardCategory *editable_category);
|
void setEditableCategory(FeedsModelCategory *editable_category);
|
||||||
|
|
||||||
// Initializes the dialog.
|
// Initializes the dialog.
|
||||||
void initialize();
|
void initialize();
|
||||||
@ -78,7 +78,7 @@ class FormStandardCategoryDetails : public QDialog {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::FormStandardCategoryDetails *m_ui;
|
Ui::FormStandardCategoryDetails *m_ui;
|
||||||
FeedsModelStandardCategory *m_editableCategory;
|
FeedsModelCategory *m_editableCategory;
|
||||||
FeedsModel *m_feedsModel;
|
FeedsModel *m_feedsModel;
|
||||||
|
|
||||||
QMenu *m_iconMenu;
|
QMenu *m_iconMenu;
|
||||||
|
@ -23,8 +23,7 @@
|
|||||||
#include "core/feedsmodelrootitem.h"
|
#include "core/feedsmodelrootitem.h"
|
||||||
#include "core/feedsmodelcategory.h"
|
#include "core/feedsmodelcategory.h"
|
||||||
#include "core/feedsmodelfeed.h"
|
#include "core/feedsmodelfeed.h"
|
||||||
#include "core/feedsmodelstandardfeed.h"
|
#include "network-web/networkfactory.h"
|
||||||
#include "core/networkfactory.h"
|
|
||||||
#include "gui/iconthemefactory.h"
|
#include "gui/iconthemefactory.h"
|
||||||
#include "gui/baselineedit.h"
|
#include "gui/baselineedit.h"
|
||||||
#include "gui/messagebox.h"
|
#include "gui/messagebox.h"
|
||||||
@ -57,7 +56,7 @@ FormStandardFeedDetails::~FormStandardFeedDetails() {
|
|||||||
delete m_ui;
|
delete m_ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
int FormStandardFeedDetails::exec(FeedsModelStandardFeed *input_feed) {
|
int FormStandardFeedDetails::exec(FeedsModelFeed *input_feed) {
|
||||||
// Load categories.
|
// Load categories.
|
||||||
loadCategories(m_feedsModel->allCategories().values(),
|
loadCategories(m_feedsModel->allCategories().values(),
|
||||||
m_feedsModel->rootItem());
|
m_feedsModel->rootItem());
|
||||||
@ -151,15 +150,15 @@ void FormStandardFeedDetails::onAuthenticationSwitched() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FormStandardFeedDetails::onAutoUpdateTypeChanged(int new_index) {
|
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) {
|
switch (auto_update_type) {
|
||||||
case FeedsModelStandardFeed::DontAutoUpdate:
|
case FeedsModelFeed::DontAutoUpdate:
|
||||||
case FeedsModelStandardFeed::DefaultAutoUpdate:
|
case FeedsModelFeed::DefaultAutoUpdate:
|
||||||
m_ui->m_spinAutoUpdateInterval->setEnabled(false);
|
m_ui->m_spinAutoUpdateInterval->setEnabled(false);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FeedsModelStandardFeed::SpecificAutoUpdate:
|
case FeedsModelFeed::SpecificAutoUpdate:
|
||||||
default:
|
default:
|
||||||
m_ui->m_spinAutoUpdateInterval->setEnabled(true);
|
m_ui->m_spinAutoUpdateInterval->setEnabled(true);
|
||||||
}
|
}
|
||||||
@ -203,8 +202,8 @@ void FormStandardFeedDetails::onUseDefaultIcon() {
|
|||||||
|
|
||||||
void FormStandardFeedDetails::apply() {
|
void FormStandardFeedDetails::apply() {
|
||||||
FeedsModelRootItem *parent = static_cast<FeedsModelRootItem*>(m_ui->m_cmbParentCategory->itemData(m_ui->m_cmbParentCategory->currentIndex()).value<void*>());
|
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>());
|
FeedsModelFeed::Type type = static_cast<FeedsModelFeed::Type>(m_ui->m_cmbType->itemData(m_ui->m_cmbType->currentIndex()).value<int>());
|
||||||
FeedsModelStandardFeed *new_feed = new FeedsModelStandardFeed();
|
FeedsModelFeed *new_feed = new FeedsModelFeed();
|
||||||
|
|
||||||
// Setup data for new_feed.
|
// Setup data for new_feed.
|
||||||
new_feed->setTitle(m_ui->m_txtTitle->lineEdit()->text());
|
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->setPasswordProtected(m_ui->m_gbAuthentication->isChecked());
|
||||||
new_feed->setUsername(m_ui->m_txtUsername->lineEdit()->text());
|
new_feed->setUsername(m_ui->m_txtUsername->lineEdit()->text());
|
||||||
new_feed->setPassword(m_ui->m_txtPassword->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->setAutoUpdateInitialInterval(m_ui->m_spinAutoUpdateInterval->value());
|
||||||
new_feed->setParent(parent);
|
new_feed->setParent(parent);
|
||||||
|
|
||||||
if (m_editableFeed == NULL) {
|
if (m_editableFeed == NULL) {
|
||||||
// Add the feed.
|
// Add the feed.
|
||||||
if (m_feedsModel->addStandardFeed(new_feed, parent)) {
|
if (m_feedsModel->addFeed(new_feed, parent)) {
|
||||||
accept();
|
accept();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -242,7 +241,7 @@ void FormStandardFeedDetails::apply() {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Edit the feed.
|
// Edit the feed.
|
||||||
if (m_feedsModel->editStandardFeed(m_editableFeed, new_feed)) {
|
if (m_feedsModel->editFeed(m_editableFeed, new_feed)) {
|
||||||
accept();
|
accept();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -262,9 +261,9 @@ void FormStandardFeedDetails::apply() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FormStandardFeedDetails::guessFeed() {
|
void FormStandardFeedDetails::guessFeed() {
|
||||||
QPair<FeedsModelStandardFeed*, QNetworkReply::NetworkError> result = FeedsModelStandardFeed::guessFeed(m_ui->m_txtUrl->lineEdit()->text(),
|
QPair<FeedsModelFeed*, QNetworkReply::NetworkError> result = FeedsModelFeed::guessFeed(m_ui->m_txtUrl->lineEdit()->text(),
|
||||||
m_ui->m_txtUsername->lineEdit()->text(),
|
m_ui->m_txtUsername->lineEdit()->text(),
|
||||||
m_ui->m_txtPassword->lineEdit()->text());
|
m_ui->m_txtPassword->lineEdit()->text());
|
||||||
|
|
||||||
if (result.first != NULL) {
|
if (result.first != NULL) {
|
||||||
// Icon or whole feed was guessed.
|
// Icon or whole feed was guessed.
|
||||||
@ -332,7 +331,7 @@ void FormStandardFeedDetails::createConnections() {
|
|||||||
connect(m_actionUseDefaultIcon, SIGNAL(triggered()), this, SLOT(onUseDefaultIcon()));
|
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_editableFeed = editable_feed;
|
||||||
|
|
||||||
m_ui->m_cmbParentCategory->setCurrentIndex(m_ui->m_cmbParentCategory->findData(QVariant::fromValue((void*) editable_feed->parent())));
|
m_ui->m_cmbParentCategory->setCurrentIndex(m_ui->m_cmbParentCategory->findData(QVariant::fromValue((void*) editable_feed->parent())));
|
||||||
@ -381,10 +380,10 @@ void FormStandardFeedDetails::initialize() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Add standard feed types.
|
// 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::Atom10), QVariant::fromValue((int) FeedsModelFeed::Atom10));
|
||||||
m_ui->m_cmbType->addItem(FeedsModelFeed::typeToString(FeedsModelFeed::StandardRdf), QVariant::fromValue((int) FeedsModelFeed::StandardRdf));
|
m_ui->m_cmbType->addItem(FeedsModelFeed::typeToString(FeedsModelFeed::Rdf), QVariant::fromValue((int) FeedsModelFeed::Rdf));
|
||||||
m_ui->m_cmbType->addItem(FeedsModelFeed::typeToString(FeedsModelFeed::StandardRss0X), QVariant::fromValue((int) FeedsModelFeed::StandardRss0X));
|
m_ui->m_cmbType->addItem(FeedsModelFeed::typeToString(FeedsModelFeed::Rss0X), QVariant::fromValue((int) FeedsModelFeed::Rss0X));
|
||||||
m_ui->m_cmbType->addItem(FeedsModelFeed::typeToString(FeedsModelFeed::StandardRss2X), QVariant::fromValue((int) FeedsModelFeed::StandardRss2X));
|
m_ui->m_cmbType->addItem(FeedsModelFeed::typeToString(FeedsModelFeed::Rss2X), QVariant::fromValue((int) FeedsModelFeed::Rss2X));
|
||||||
|
|
||||||
// Load available encodings.
|
// Load available encodings.
|
||||||
QList<QByteArray> encodings = QTextCodec::availableCodecs();
|
QList<QByteArray> encodings = QTextCodec::availableCodecs();
|
||||||
@ -421,9 +420,9 @@ void FormStandardFeedDetails::initialize() {
|
|||||||
|
|
||||||
// Setup auto-update options.
|
// Setup auto-update options.
|
||||||
m_ui->m_spinAutoUpdateInterval->setValue(DEFAULT_AUTO_UPDATE_INTERVAL);
|
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 using global interval"), QVariant::fromValue((int) FeedsModelFeed::DefaultAutoUpdate));
|
||||||
m_ui->m_cmbAutoUpdateType->addItem(tr("Auto-update every"), QVariant::fromValue((int) FeedsModelStandardFeed::SpecificAutoUpdate));
|
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) FeedsModelStandardFeed::DontAutoUpdate));
|
m_ui->m_cmbAutoUpdateType->addItem(tr("Do not auto-update at all"), QVariant::fromValue((int) FeedsModelFeed::DontAutoUpdate));
|
||||||
|
|
||||||
// Set tab order.
|
// Set tab order.
|
||||||
setTabOrder(m_ui->m_cmbParentCategory, m_ui->m_cmbType);
|
setTabOrder(m_ui->m_cmbParentCategory, m_ui->m_cmbType);
|
||||||
|
@ -28,7 +28,7 @@ namespace Ui {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class FeedsModel;
|
class FeedsModel;
|
||||||
class FeedsModelStandardFeed;
|
class FeedsModelFeed;
|
||||||
class FeedsModelCategory;
|
class FeedsModelCategory;
|
||||||
class FeedsModelRootItem;
|
class FeedsModelRootItem;
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ class FormStandardFeedDetails : public QDialog {
|
|||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
// Executes add/edit standard feed dialog.
|
// Executes add/edit standard feed dialog.
|
||||||
int exec(FeedsModelStandardFeed *input_feed);
|
int exec(FeedsModelFeed *input_feed);
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
// Applies changes.
|
// Applies changes.
|
||||||
@ -71,7 +71,7 @@ class FormStandardFeedDetails : public QDialog {
|
|||||||
void createConnections();
|
void createConnections();
|
||||||
|
|
||||||
// Sets the feed which will be edited.
|
// Sets the feed which will be edited.
|
||||||
void setEditableFeed(FeedsModelStandardFeed *editable_feed);
|
void setEditableFeed(FeedsModelFeed *editable_feed);
|
||||||
|
|
||||||
// Initializes the dialog.
|
// Initializes the dialog.
|
||||||
void initialize();
|
void initialize();
|
||||||
@ -82,7 +82,7 @@ class FormStandardFeedDetails : public QDialog {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::FormStandardFeedDetails *m_ui;
|
Ui::FormStandardFeedDetails *m_ui;
|
||||||
FeedsModelStandardFeed *m_editableFeed;
|
FeedsModelFeed *m_editableFeed;
|
||||||
FeedsModel *m_feedsModel;
|
FeedsModel *m_feedsModel;
|
||||||
|
|
||||||
QMenu *m_iconMenu;
|
QMenu *m_iconMenu;
|
||||||
|
@ -19,8 +19,8 @@
|
|||||||
|
|
||||||
#include "core/defs.h"
|
#include "core/defs.h"
|
||||||
#include "core/systemfactory.h"
|
#include "core/systemfactory.h"
|
||||||
#include "core/networkfactory.h"
|
#include "network-web/networkfactory.h"
|
||||||
#include "core/webfactory.h"
|
#include "network-web/webfactory.h"
|
||||||
#include "gui/iconthemefactory.h"
|
#include "gui/iconthemefactory.h"
|
||||||
#include "gui/messagebox.h"
|
#include "gui/messagebox.h"
|
||||||
#include "gui/systemtrayicon.h"
|
#include "gui/systemtrayicon.h"
|
||||||
|
@ -20,8 +20,8 @@
|
|||||||
#include "core/messagesproxymodel.h"
|
#include "core/messagesproxymodel.h"
|
||||||
#include "core/messagesmodel.h"
|
#include "core/messagesmodel.h"
|
||||||
#include "core/settings.h"
|
#include "core/settings.h"
|
||||||
#include "core/networkfactory.h"
|
#include "network-web/networkfactory.h"
|
||||||
#include "core/webfactory.h"
|
#include "network-web/webfactory.h"
|
||||||
#include "gui/formmain.h"
|
#include "gui/formmain.h"
|
||||||
#include "gui/messagebox.h"
|
#include "gui/messagebox.h"
|
||||||
|
|
||||||
|
@ -20,9 +20,9 @@
|
|||||||
#include "core/defs.h"
|
#include "core/defs.h"
|
||||||
#include "core/settings.h"
|
#include "core/settings.h"
|
||||||
#include "core/textfactory.h"
|
#include "core/textfactory.h"
|
||||||
|
#include "network-web/webbrowser.h"
|
||||||
#include "gui/tabbar.h"
|
#include "gui/tabbar.h"
|
||||||
#include "gui/iconthemefactory.h"
|
#include "gui/iconthemefactory.h"
|
||||||
#include "gui/webbrowser.h"
|
|
||||||
#include "gui/formmain.h"
|
#include "gui/formmain.h"
|
||||||
#include "gui/feedmessageviewer.h"
|
#include "gui/feedmessageviewer.h"
|
||||||
#include "gui/plaintoolbutton.h"
|
#include "gui/plaintoolbutton.h"
|
||||||
@ -111,18 +111,31 @@ void TabWidget::checkTabBarVisibility() {
|
|||||||
void TabWidget::tabInserted(int index) {
|
void TabWidget::tabInserted(int index) {
|
||||||
QTabWidget::tabInserted(index);
|
QTabWidget::tabInserted(index);
|
||||||
checkTabBarVisibility();
|
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) {
|
void TabWidget::tabRemoved(int index) {
|
||||||
QTabWidget::tabRemoved(index);
|
QTabWidget::tabRemoved(index);
|
||||||
checkTabBarVisibility();
|
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() {
|
void TabWidget::createConnections() {
|
||||||
connect(tabBar(), SIGNAL(tabCloseRequested(int)), this, SLOT(closeTab(int)));
|
connect(tabBar(), SIGNAL(tabCloseRequested(int)), this, SLOT(closeTab(int)));
|
||||||
connect(tabBar(), SIGNAL(emptySpaceDoubleClicked()), this, SLOT(addEmptyBrowser()));
|
connect(tabBar(), SIGNAL(emptySpaceDoubleClicked()), this, SLOT(addEmptyBrowser()));
|
||||||
connect(tabBar(), SIGNAL(tabMoved(int,int)), this, SLOT(fixContentsAfterMove(int,int)));
|
connect(tabBar(), SIGNAL(tabMoved(int,int)), this, SLOT(fixContentsAfterMove(int,int)));
|
||||||
connect(tabBar(), SIGNAL(currentChanged(int)), this, SLOT(fixContentAfterIndexChange(int)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabWidget::initializeTabs() {
|
void TabWidget::initializeTabs() {
|
||||||
@ -324,17 +337,12 @@ void TabWidget::changeTitle(int index, const QString &new_title) {
|
|||||||
setTabToolTip(index, new_title);
|
setTabToolTip(index, new_title);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabWidget::fixContentAfterIndexChange(int from) {
|
|
||||||
fixContentsIndexes(from, count() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TabWidget::fixContentsAfterMove(int from, int to) {
|
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 ( ; from <= to; from++) {
|
||||||
for ( ; starting_index <= ending_index; starting_index++) {
|
TabContent *content = static_cast<TabContent*>(widget(from));
|
||||||
TabContent *content = static_cast<TabContent*>(widget(starting_index));
|
content->setIndex(from);
|
||||||
content->setIndex(starting_index);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,12 +85,8 @@ class TabWidget : public QTabWidget {
|
|||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
// Fixes tabs indexes.
|
// Fixes tabs indexes.
|
||||||
void fixContentAfterIndexChange(int from);
|
|
||||||
void fixContentsAfterMove(int from, int to);
|
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.
|
// Called when number of tab pages changes.
|
||||||
void checkTabBarVisibility();
|
void checkTabBarVisibility();
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
|
// 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/defs.h"
|
||||||
#include "core/settings.h"
|
#include "core/settings.h"
|
@ -15,15 +15,16 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
|
// 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/defs.h"
|
||||||
#include "core/silentnetworkaccessmanager.h"
|
|
||||||
#include "core/feedsmodelstandardfeed.h"
|
|
||||||
#include "core/settings.h"
|
#include "core/settings.h"
|
||||||
|
#include "network-web/silentnetworkaccessmanager.h"
|
||||||
|
|
||||||
#include <QEventLoop>
|
#include <QEventLoop>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
#include <QIcon>
|
||||||
|
#include <QPixmap>
|
||||||
#include <QTextDocument>
|
#include <QTextDocument>
|
||||||
|
|
||||||
|
|
@ -22,8 +22,6 @@
|
|||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
|
||||||
|
|
||||||
class FeedsModelStandardFeed;
|
|
||||||
|
|
||||||
class NetworkFactory {
|
class NetworkFactory {
|
||||||
Q_DECLARE_TR_FUNCTIONS(NetworkFactory)
|
Q_DECLARE_TR_FUNCTIONS(NetworkFactory)
|
||||||
|
|
@ -15,9 +15,7 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
|
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#include "core/silentnetworkaccessmanager.h"
|
#include "network-web/silentnetworkaccessmanager.h"
|
||||||
|
|
||||||
#include "core/feedsmodelstandardfeed.h"
|
|
||||||
|
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
#include <QAuthenticator>
|
#include <QAuthenticator>
|
@ -18,7 +18,7 @@
|
|||||||
#ifndef SILENTNETWORKACCESSMANAGER_H
|
#ifndef SILENTNETWORKACCESSMANAGER_H
|
||||||
#define SILENTNETWORKACCESSMANAGER_H
|
#define SILENTNETWORKACCESSMANAGER_H
|
||||||
|
|
||||||
#include "core/basenetworkaccessmanager.h"
|
#include "network-web/basenetworkaccessmanager.h"
|
||||||
|
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
|
|
@ -15,13 +15,13 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
|
// 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/defs.h"
|
||||||
#include "core/webbrowsernetworkaccessmanager.h"
|
#include "network-web/webbrowsernetworkaccessmanager.h"
|
||||||
#include "core/webpage.h"
|
#include "network-web/webpage.h"
|
||||||
|
#include "network-web/webview.h"
|
||||||
#include "gui/skinfactory.h"
|
#include "gui/skinfactory.h"
|
||||||
#include "gui/webview.h"
|
|
||||||
#include "gui/formmain.h"
|
#include "gui/formmain.h"
|
||||||
#include "gui/iconthemefactory.h"
|
#include "gui/iconthemefactory.h"
|
||||||
#include "gui/tabwidget.h"
|
#include "gui/tabwidget.h"
|
@ -19,8 +19,8 @@
|
|||||||
#define WEBBROWSER_H
|
#define WEBBROWSER_H
|
||||||
|
|
||||||
#include "core/messagesmodel.h"
|
#include "core/messagesmodel.h"
|
||||||
|
#include "network-web/webview.h"
|
||||||
#include "gui/tabcontent.h"
|
#include "gui/tabcontent.h"
|
||||||
#include "gui/webview.h"
|
|
||||||
#include "gui/locationlineedit.h"
|
#include "gui/locationlineedit.h"
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
@ -15,7 +15,7 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
|
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#include "core/webbrowsernetworkaccessmanager.h"
|
#include "network-web/webbrowsernetworkaccessmanager.h"
|
||||||
|
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
@ -18,7 +18,7 @@
|
|||||||
#ifndef WEBBROWSERNETWORKACCESSMANAGER_H
|
#ifndef WEBBROWSERNETWORKACCESSMANAGER_H
|
||||||
#define WEBBROWSERNETWORKACCESSMANAGER_H
|
#define WEBBROWSERNETWORKACCESSMANAGER_H
|
||||||
|
|
||||||
#include "core/basenetworkaccessmanager.h"
|
#include "network-web/basenetworkaccessmanager.h"
|
||||||
|
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
#include "core/webfactory.h"
|
#include "network-web/webfactory.h"
|
||||||
|
|
||||||
#include "core/defs.h"
|
#include "core/defs.h"
|
||||||
#include "core/settings.h"
|
#include "core/settings.h"
|
@ -15,10 +15,10 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
|
// 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 "network-web/webbrowsernetworkaccessmanager.h"
|
||||||
#include "gui/webbrowser.h"
|
#include "network-web/webbrowser.h"
|
||||||
|
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
#include <QWebFrame>
|
#include <QWebFrame>
|
@ -15,11 +15,11 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
|
// 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/defs.h"
|
||||||
#include "core/settings.h"
|
#include "core/settings.h"
|
||||||
#include "core/webpage.h"
|
#include "network-web/webpage.h"
|
||||||
#include "gui/skinfactory.h"
|
#include "gui/skinfactory.h"
|
||||||
#include "gui/iconthemefactory.h"
|
#include "gui/iconthemefactory.h"
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user