diff --git a/CMakeLists.txt b/CMakeLists.txt index 26146a312..017388ddb 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,8 +71,8 @@ project(rssguard) set(APP_NAME "RSS Guard") set(APP_LOW_NAME "rssguard") -set(APP_VERSION "2.2.0") -set(FILE_VERSION "2,2,0,0") +set(APP_VERSION "2.3.0") +set(FILE_VERSION "2,3,0,0") set(APP_AUTHOR "Martin Rotter") set(APP_URL "http://bitbucket.org/skunkos/rssguard") set(APP_URL_ISSUES "http://bitbucket.org/skunkos/rssguard/issues") diff --git a/README.md b/README.md index 2f4dbff65..211fbe25f 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,9 @@ Downloads --------- ### Windows * [all downloads](https://bitbucket.org/skunkos/rssguard/downloads). +* alternative downloads + +[![Alternative RSS Guard downloads.](http://www.instalki.pl/img/buttons/en/download_dark.png)](http://www.instalki.pl/programy/download/Windows/czytniki_RSS/RSS_Guard.html) ### Linux * [stable releases](http://software.opensuse.org/download.html?project=home%3Askunkos&package=rssguard), * [development releases](http://software.opensuse.org/download.html?project=home%3Askunkos&package=rssguard-git) (compiled from the master branch of RSS Guard Git repository), @@ -40,6 +43,7 @@ Downloads ![RSS Guard is 100% clean.](http://www.softpedia.com/_img/softpedia_100_free.png) - - - + Features -------- RSS Guard is simple (yet powerful) feed reader. It is able to fetch the most known feed formats, including RSS/RDF and ATOM. RSS Guard is developed on top of the [Qt library](http://qt-project.org/) and it supports these operating systems: @@ -58,6 +62,7 @@ RSS Guard is written in C++. It is pretty fast even with tons of messages loaded * support for all feed formats, * simplicity, * import/export of feeds to/from OPML 2.0, +* downloader with own tab and support for up to 6 parallel downloads, * message filter with regular expressions, * feed metadata fetching including icons, * enhanced feed auto-updating with separate time intervals, diff --git a/src/definitions/definitions.h.in b/src/definitions/definitions.h.in index 24ec0b957..e41da1e86 100755 --- a/src/definitions/definitions.h.in +++ b/src/definitions/definitions.h.in @@ -108,6 +108,9 @@ #define APP_CFG_PATH "data/config" #define APP_CFG_FILE "config.ini" +#define APP_LOG_PATH "data/log" +#define APP_LOG_FILE "log.txt" + #if defined(Q_OS_OSX) #define APP_PREFIX "@CMAKE_INSTALL_PREFIX@/@APP_LOW_NAME@.app/Contents/Resources" #else diff --git a/src/gui/formabout.cpp b/src/gui/formabout.cpp index 3501f265f..826eff536 100755 --- a/src/gui/formabout.cpp +++ b/src/gui/formabout.cpp @@ -104,7 +104,7 @@ FormAbout::FormAbout(QWidget *parent) : QDialog(parent), m_ui(new Ui::FormAbout) APP_NAME)); // Load additional paths information. - if (qApp->settings()->type() == Settings::Portable) { + if (qApp->settings()->type() == SettingsType::Portable) { m_ui->m_txtPathsSettingsType->setText(tr("FULLY portable")); m_ui->m_txtPathsDatabaseRoot->setText(QDir::toNativeSeparators(qApp->applicationDirPath() + QDir::separator() + QString(APP_DB_SQLITE_PATH))); } diff --git a/src/gui/systemtrayicon.h b/src/gui/systemtrayicon.h old mode 100644 new mode 100755 index 93b5d69de..b9be20002 --- a/src/gui/systemtrayicon.h +++ b/src/gui/systemtrayicon.h @@ -22,7 +22,6 @@ #include "definitions/definitions.h" -#include #include #include diff --git a/src/miscellaneous/databasefactory.cpp b/src/miscellaneous/databasefactory.cpp index 78299d01e..075d140ee 100755 --- a/src/miscellaneous/databasefactory.cpp +++ b/src/miscellaneous/databasefactory.cpp @@ -115,7 +115,7 @@ void DatabaseFactory::finishRestoration() { } void DatabaseFactory::sqliteAssemblyDatabaseFilePath() { - if (qApp->settings()->type() == Settings::Portable) { + if (qApp->settings()->type() == SettingsType::Portable) { m_sqliteDatabaseFilePath = qApp->applicationDirPath() + QDir::separator() + QString(APP_DB_SQLITE_PATH); } else { diff --git a/src/miscellaneous/debugging.cpp b/src/miscellaneous/debugging.cpp index 42f3b3e74..a3f85ecef 100755 --- a/src/miscellaneous/debugging.cpp +++ b/src/miscellaneous/debugging.cpp @@ -24,49 +24,50 @@ #include #include -#ifndef QT_NO_DEBUG_OUTPUT -#if QT_VERSION >= 0x050000 -#define DEBUG_OUTPUT_WORKER(type_string, file, line, message) \ - fprintf(stderr, "[%s] %s (%s:%d): %s\n", \ - APP_LOW_NAME, \ - type_string, \ - file, \ - line, \ - qPrintable(message)); -#else -#define DEBUG_OUTPUT_WORKER(type_string, message) \ - fprintf(stderr, "[%s] %s: %s\n", \ - APP_LOW_NAME, \ - type_string, \ - message); -#endif -#endif +Debugging::Debugging() { +} -#if QT_VERSION >= 0x050000 -void Debugging::debugHandler(QtMsgType type, - const QMessageLogContext &placement, - const QString &message) { -#ifndef QT_NO_DEBUG_OUTPUT - const char *file = qPrintable(QString(placement.file).section(QDir::separator(), - -1)); +void Debugging::performLog(const char *message, QtMsgType type, const char *file, const char *function, int line) { + const char *type_string = typeToString(type); + // Write to console. + if (file == 0 || function == 0 || line < 0) { + fprintf(stderr, "[%s] %s: %s\n", APP_LOW_NAME, type_string, message); + } + else { + fprintf(stderr, "[%s] %s\n Type: %s\n File: %s (line %d)\n Function: %s\n\n", + APP_LOW_NAME, message, type_string, file, line, function); + } + + // TODO: Write to file here. + + if (type == QtFatalMsg) { + qApp->exit(EXIT_FAILURE); + } +} + +const char *Debugging::typeToString(QtMsgType type) { switch (type) { case QtDebugMsg: - DEBUG_OUTPUT_WORKER("INFO", file, placement.line, message); - break; + return "DEBUG"; + case QtWarningMsg: - DEBUG_OUTPUT_WORKER("WARNING", file, placement.line, message); - break; + return "WARNING"; + case QtCriticalMsg: - DEBUG_OUTPUT_WORKER("CRITICAL", file, placement.line, message); - break; + return "CRITICAL"; + case QtFatalMsg: - DEBUG_OUTPUT_WORKER("FATAL", file, placement.line, message); - qApp->exit(EXIT_FAILURE); default: - break; + return "FATAL (terminating application)"; } +} + +#if QT_VERSION >= 0x050000 +void Debugging::debugHandler(QtMsgType type, const QMessageLogContext &placement, const QString &message) { +#ifndef QT_NO_DEBUG_OUTPUT + performLog(qPrintable(message), type, placement.file, placement.function, placement.line); #else Q_UNUSED(type) Q_UNUSED(placement) @@ -75,29 +76,11 @@ void Debugging::debugHandler(QtMsgType type, } #else void Debugging::debugHandler(QtMsgType type, const char *message) { - #ifndef QT_NO_DEBUG_OUTPUT - switch (type) { - case QtDebugMsg: - DEBUG_OUTPUT_WORKER("INFO", message); - break; - case QtWarningMsg: - DEBUG_OUTPUT_WORKER("WARNING", message); - break; - case QtCriticalMsg: - DEBUG_OUTPUT_WORKER("CRITICAL", message); - break; - case QtFatalMsg: - DEBUG_OUTPUT_WORKER("FATAL", message); - qApp->exit(EXIT_FAILURE); - default: - break; - } +#ifndef QT_NO_DEBUG_OUTPUT + performLog(message, type); #else Q_UNUSED(type) Q_UNUSED(message) #endif } #endif - -Debugging::Debugging() { -} diff --git a/src/miscellaneous/debugging.h b/src/miscellaneous/debugging.h old mode 100644 new mode 100755 index 07805ce63..76ee9e1a4 --- a/src/miscellaneous/debugging.h +++ b/src/miscellaneous/debugging.h @@ -26,14 +26,14 @@ class Debugging { // Specifies format of output console messages. // NOTE: QT_NO_DEBUG_OUTPUT - disables debug outputs completely!!! #if QT_VERSION >= 0x050000 - static void debugHandler(QtMsgType type, - const QMessageLogContext &placement, - const QString &message); + static void debugHandler(QtMsgType type, const QMessageLogContext &placement, const QString &message); #else - static void debugHandler(QtMsgType type, - const char *message); + static void debugHandler(QtMsgType type, const char *message); #endif + static void performLog(const char *message, QtMsgType type, const char *file = 0, const char *function = 0, int line = -1); + static const char *typeToString(QtMsgType type); + private: // Constructor. explicit Debugging(); diff --git a/src/miscellaneous/iconfactory.h b/src/miscellaneous/iconfactory.h index 4d8a6b326..945410010 100755 --- a/src/miscellaneous/iconfactory.h +++ b/src/miscellaneous/iconfactory.h @@ -79,9 +79,6 @@ class IconFactory : public QObject { // Sets icon theme with given name as the active one and loads it. void setCurrentIconTheme(const QString &theme_name); - // Singleton getter. - static IconFactory *instance(); - private: QHash m_cachedIcons; QString m_currentIconTheme; diff --git a/src/miscellaneous/settings.cpp b/src/miscellaneous/settings.cpp index 81bd12acd..021755297 100755 --- a/src/miscellaneous/settings.cpp +++ b/src/miscellaneous/settings.cpp @@ -238,8 +238,7 @@ DVALUE(bool) Browser::QueueTabsDef = true; // Categories. DKEY Categories::ID = "categories_expand_states"; -Settings::Settings(const QString &file_name, Format format, - const Type &status, QObject *parent) +Settings::Settings(const QString &file_name, Format format, const SettingsType &status, QObject *parent) : QSettings(file_name, format, parent), m_initializationStatus(status) { } @@ -248,6 +247,10 @@ Settings::~Settings() { qDebug("Deleting Settings instance."); } +QString Settings::pathName() const { + return QFileInfo(fileName()).absolutePath(); +} + QSettings::Status Settings::checkSettings() { qDebug("Syncing settings."); @@ -281,14 +284,40 @@ void Settings::finishRestoration(const QString &desired_settings_file_path) { Settings *Settings::setupSettings(QObject *parent) { Settings *new_settings; - // If settings file exists in executable file working directory + // If settings file exists (and is writable) in executable file working directory // (in subdirectory APP_CFG_PATH), then use it (portable settings). // Otherwise use settings file stored in home path. - QString relative_path = QDir::separator() + QString(APP_CFG_PATH) + QDir::separator() + QString(APP_CFG_FILE); + SettingsProperties properties = determineProperties(); + + finishRestoration(properties.m_absoluteSettingsFileName); + + // Portable settings are available, use them. + new_settings = new Settings(properties.m_absoluteSettingsFileName, QSettings::IniFormat, properties.m_type, parent); + + // Construct icon cache in the same path. + QString web_path = properties.m_baseDirectory + QDir::separator() + QString(APP_DB_WEB_PATH); + QDir(web_path).mkpath(web_path); + QWebSettings::setIconDatabasePath(web_path); + + // Check if portable settings are available. + if (properties.m_type == SettingsType::Portable) { + qDebug("Initializing settings in '%s' (portable way).", qPrintable(QDir::toNativeSeparators(properties.m_absoluteSettingsFileName))); + } + else { + qDebug("Initializing settings in '%s' (non-portable way).", qPrintable(QDir::toNativeSeparators(properties.m_absoluteSettingsFileName))); + } + + return new_settings; +} + +SettingsProperties Settings::determineProperties() { + SettingsProperties properties; + + properties.m_settingsSuffix = QDir::separator() + QString(APP_CFG_PATH) + QDir::separator() + QString(APP_CFG_FILE); + QString app_path = qApp->applicationDirPath(); - QString app_path_file = app_path + relative_path; QString home_path = qApp->homeFolderPath() + QDir::separator() + QString(APP_LOW_H_NAME); - QString home_path_file = home_path + relative_path; + QString home_path_file = home_path + properties.m_settingsSuffix; bool portable_settings_available = QFileInfo(app_path).isWritable(); bool non_portable_settings_exist = QFile::exists(home_path_file); @@ -297,34 +326,16 @@ Settings *Settings::setupSettings(QObject *parent) { // settings was not initialized before. bool will_we_use_portable_settings = portable_settings_available && !non_portable_settings_exist; - // Check if portable settings are available. if (will_we_use_portable_settings) { - finishRestoration(app_path_file); - - // Portable settings are available, use them. - new_settings = new Settings(app_path_file, QSettings::IniFormat, Settings::Portable, parent); - - // Construct icon cache in the same path. - QString web_path = app_path + QDir::separator() + QString(APP_DB_WEB_PATH); - QDir(web_path).mkpath(web_path); - QWebSettings::setIconDatabasePath(web_path); - - qDebug("Initializing settings in '%s' (portable way).", qPrintable(QDir::toNativeSeparators(app_path_file))); + properties.m_type = SettingsType::Portable; + properties.m_baseDirectory = app_path; } else { - finishRestoration(home_path_file); - - // Portable settings are NOT available, store them in - // user's home directory. - new_settings = new Settings(home_path_file, QSettings::IniFormat, Settings::NonPortable, parent); - - // Construct icon cache in the same path. - QString web_path = home_path + QDir::separator() + QString(APP_DB_WEB_PATH); - QDir(web_path).mkpath(web_path); - QWebSettings::setIconDatabasePath(web_path); - - qDebug("Initializing settings in '%s' (non-portable way).", qPrintable(QDir::toNativeSeparators(home_path_file))); + properties.m_type = SettingsType::NonPortable; + properties.m_baseDirectory = home_path; } - return new_settings; + properties.m_absoluteSettingsFileName = properties.m_baseDirectory + properties.m_settingsSuffix; + + return properties; } diff --git a/src/miscellaneous/settings.h b/src/miscellaneous/settings.h index 2885f6259..ab0cef82f 100755 --- a/src/miscellaneous/settings.h +++ b/src/miscellaneous/settings.h @@ -22,7 +22,8 @@ #include "definitions/definitions.h" -#include +#include "miscellaneous/settingsproperties.h" + #include #define KEY extern const char* @@ -267,17 +268,11 @@ class Settings : public QSettings { Q_OBJECT public: - // Describes possible types of loaded settings. - enum Type { - Portable, - NonPortable - }; - // Destructor. virtual ~Settings(); // Type of used settings. - inline Type type() const { + inline SettingsType type() const { return m_initializationStatus; } @@ -302,6 +297,9 @@ class Settings : public QSettings { QSettings::remove(QString("%1/%2").arg(section, key)); } + // Returns the path which contains the settings. + QString pathName() const; + // Synchronizes settings. QSettings::Status checkSettings(); @@ -311,11 +309,13 @@ class Settings : public QSettings { // Creates settings file in correct location. static Settings *setupSettings(QObject *parent); + static SettingsProperties determineProperties(); + private: // Constructor. - explicit Settings(const QString &file_name, Format format, const Type &type, QObject *parent = 0); + explicit Settings(const QString &file_name, Format format, const SettingsType &type, QObject *parent = 0); - Type m_initializationStatus; + SettingsType m_initializationStatus; }; #endif // SETTINGS_H diff --git a/src/miscellaneous/settingsproperties.h b/src/miscellaneous/settingsproperties.h new file mode 100755 index 000000000..258c91a7f --- /dev/null +++ b/src/miscellaneous/settingsproperties.h @@ -0,0 +1,21 @@ +#ifndef SETTINGSPROPERTIES_H +#define SETTINGSPROPERTIES_H + +#include + + +// Describes possible types of loaded settings. +enum SettingsType { + Portable, + NonPortable +}; + +// Describes characteristics of settings. +struct SettingsProperties { + SettingsType m_type; + QString m_baseDirectory; + QString m_settingsSuffix; + QString m_absoluteSettingsFileName; +}; + +#endif // SETTINGSPROPERTIES_H diff --git a/src/miscellaneous/systemfactory.h b/src/miscellaneous/systemfactory.h old mode 100644 new mode 100755 index efbc88d29..6a530eb23 --- a/src/miscellaneous/systemfactory.h +++ b/src/miscellaneous/systemfactory.h @@ -20,7 +20,6 @@ #include -#include #include #include #include