This commit is contained in:
Martin Rotter 2015-04-28 20:01:59 +02:00
parent e2645f7f63
commit 14a74bc028
9 changed files with 126 additions and 25 deletions

View file

@ -1,8 +1,8 @@
DROP DATABASE IF EXISTS rssguard;
DROP DATABASE IF EXISTS ##;
-- !
CREATE DATABASE IF NOT EXISTS rssguard CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE DATABASE IF NOT EXISTS ## CHARACTER SET utf8 COLLATE utf8_general_ci;
-- !
USE rssguard;
USE ##;
-- !
DROP TABLE IF EXISTS Information;
-- !

View file

@ -8,6 +8,7 @@ Fixed:
Added:
<ul>
<li>User now can specify MySQL target database by name. (issue #107)</li>
<li>Automatic detection of feeds on websites. User loads website and can add feeds via custom web browser toolbar button. (issue #47)</li>
<li>Better format for logged messages. Logging to file is possible via "rssguard 2> log.txt" command.</li>
<li>Full support for podcasts (issue #81). Supports RSS 2.0 podcasts and ATOM 1.0 podcasts. In ATOM, RSS Guard is able to fetch multiple podcasts per message. Podcasts are displayed as additional URL addresses in message preview panel.</li>

View file

@ -123,6 +123,7 @@ FormSettings::FormSettings(QWidget *parent) : QDialog(parent), m_ui(new Ui::Form
connect(m_ui->m_txtMysqlUsername->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(onMysqlUsernameChanged(QString)));
connect(m_ui->m_txtMysqlHostname->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(onMysqlHostnameChanged(QString)));
connect(m_ui->m_txtMysqlPassword->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(onMysqlPasswordChanged(QString)));
connect(m_ui->m_txtMysqlDatabase->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(onMysqlDatabaseChanged(QString)));
connect(m_ui->m_btnMysqlTestSetup, SIGNAL(clicked()), this, SLOT(mysqlTestConnection()));
connect(m_ui->m_spinMysqlPort, SIGNAL(editingFinished()), this, SLOT(onMysqlDataStorageEdited()));
connect(m_ui->m_txtMysqlHostname->lineEdit(), SIGNAL(textEdited(QString)), this, SLOT(onMysqlDataStorageEdited()));
@ -484,6 +485,7 @@ void FormSettings::loadDataStorage() {
onMysqlHostnameChanged(QString());
onMysqlUsernameChanged(QString());
onMysqlPasswordChanged(QString());
onMysqlDatabaseChanged(QString());
// Load MySQL.
m_ui->m_cmbDatabaseDriver->addItem(tr("MySQL/MariaDB (dedicated database)"), APP_DB_MYSQL_DRIVER);
@ -492,10 +494,12 @@ void FormSettings::loadDataStorage() {
m_ui->m_txtMysqlHostname->lineEdit()->setPlaceholderText(tr("Hostname of your MySQL server"));
m_ui->m_txtMysqlUsername->lineEdit()->setPlaceholderText(tr("Username to login with"));
m_ui->m_txtMysqlPassword->lineEdit()->setPlaceholderText(tr("Password for your username"));
m_ui->m_txtMysqlDatabase->lineEdit()->setPlaceholderText(tr("Working database which you have full access to."));
m_ui->m_txtMysqlHostname->lineEdit()->setText(settings->value(GROUP(Database), SETTING(Database::MySQLHostname)).toString());
m_ui->m_txtMysqlUsername->lineEdit()->setText(settings->value(GROUP(Database), SETTING(Database::MySQLUsername)).toString());
m_ui->m_txtMysqlPassword->lineEdit()->setText(settings->value(GROUP(Database), SETTING(Database::MySQLPassword)).toString());
m_ui->m_txtMysqlDatabase->lineEdit()->setText(settings->value(GROUP(Database), SETTING(Database::MySQLDatabase)).toString());
m_ui->m_spinMysqlPort->setValue(settings->value(GROUP(Database), SETTING(Database::MySQLPort)).toInt());
m_ui->m_checkMysqlShowPassword->setChecked(false);
@ -531,6 +535,7 @@ void FormSettings::saveDataStorage() {
settings->setValue(GROUP(Database), Database::MySQLHostname, m_ui->m_txtMysqlHostname->lineEdit()->text());
settings->setValue(GROUP(Database), Database::MySQLUsername, m_ui->m_txtMysqlUsername->lineEdit()->text());
settings->setValue(GROUP(Database), Database::MySQLPassword, m_ui->m_txtMysqlPassword->lineEdit()->text());
settings->setValue(GROUP(Database), Database::MySQLDatabase, m_ui->m_txtMysqlDatabase->lineEdit()->text());
settings->setValue(GROUP(Database), Database::MySQLPort, m_ui->m_spinMysqlPort->value());
}
@ -545,10 +550,12 @@ void FormSettings::saveDataStorage() {
void FormSettings::mysqlTestConnection() {
DatabaseFactory::MySQLError error_code = qApp->database()->mysqlTestConnection(m_ui->m_txtMysqlHostname->lineEdit()->text(),
m_ui->m_spinMysqlPort->value(),
m_ui->m_txtMysqlDatabase->lineEdit()->text(),
m_ui->m_txtMysqlUsername->lineEdit()->text(),
m_ui->m_txtMysqlPassword->lineEdit()->text());
QString interpretation = qApp->database()->mysqlInterpretErrorCode(error_code);
switch (error_code) {
case DatabaseFactory::MySQLOk:
m_ui->m_lblMysqlTestResult->setStatus(WidgetWithStatus::Ok, interpretation, interpretation);
@ -587,6 +594,15 @@ void FormSettings::onMysqlPasswordChanged(const QString &new_password) {
}
}
void FormSettings::onMysqlDatabaseChanged(const QString &new_database) {
if (new_database.isEmpty()) {
m_ui->m_txtMysqlDatabase->setStatus(LineEditWithStatus::Warning, tr("Working database is empty."));
}
else {
m_ui->m_txtMysqlDatabase->setStatus(LineEditWithStatus::Ok, tr("Working database is ok."));
}
}
void FormSettings::onMysqlDataStorageEdited() {
m_initialSettings.m_dataStorageDataChanged = true;
}

View file

@ -75,6 +75,7 @@ class FormSettings : public QDialog {
void onMysqlHostnameChanged(const QString &new_hostname);
void onMysqlUsernameChanged(const QString &new_username);
void onMysqlPasswordChanged(const QString &new_password);
void onMysqlDatabaseChanged(const QString &new_database);
void onMysqlDataStorageEdited();
void selectSqlBackend(int index);
void switchMysqlPasswordVisiblity(bool visible);

View file

@ -290,7 +290,7 @@ Authors of this application are NOT responsible for lost data.</string>
</item>
</layout>
</item>
<item row="1" column="0">
<item row="2" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Username</string>
@ -300,10 +300,10 @@ Authors of this application are NOT responsible for lost data.</string>
</property>
</widget>
</item>
<item row="1" column="1">
<item row="2" column="1">
<widget class="LineEditWithStatus" name="m_txtMysqlUsername" native="true"/>
</item>
<item row="2" column="0">
<item row="3" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Password</string>
@ -313,10 +313,10 @@ Authors of this application are NOT responsible for lost data.</string>
</property>
</widget>
</item>
<item row="2" column="1">
<item row="3" column="1">
<widget class="LineEditWithStatus" name="m_txtMysqlPassword" native="true"/>
</item>
<item row="4" column="1">
<item row="5" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_11">
<item>
<widget class="QPushButton" name="m_btnMysqlTestSetup">
@ -343,7 +343,7 @@ Authors of this application are NOT responsible for lost data.</string>
</item>
</layout>
</item>
<item row="5" column="0" colspan="2">
<item row="6" column="0" colspan="2">
<widget class="QLabel" name="m_lblMysqlInfo">
<property name="text">
<string>Note that speed of used MySQL server and latency of used connection medium HEAVILY influences the final performance of this application. Using slow database connections leads to bad performance when browsing feeds or messages.
@ -361,7 +361,7 @@ MySQL backend will automatically use database with name &quot;rssguard&quot;. Do
</property>
</widget>
</item>
<item row="3" column="1">
<item row="4" column="1">
<widget class="QCheckBox" name="m_checkMysqlShowPassword">
<property name="text">
<string>&amp;Show password</string>
@ -371,6 +371,16 @@ MySQL backend will automatically use database with name &quot;rssguard&quot;. Do
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="LineEditWithStatus" name="m_txtMysqlDatabase" native="true"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_11">
<property name="text">
<string>Working database</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
@ -404,8 +414,8 @@ MySQL backend will automatically use database with name &quot;rssguard&quot;. Do
<rect>
<x>0</x>
<y>0</y>
<width>740</width>
<height>448</height>
<width>100</width>
<height>30</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_4">
@ -481,9 +491,9 @@ MySQL backend will automatically use database with name &quot;rssguard&quot;. Do
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<y>0</y>
<width>208</width>
<height>238</height>
<height>238</height>
</rect>
</property>
<layout class="QFormLayout" name="formLayout">
@ -1428,6 +1438,65 @@ MySQL backend will automatically use database with name &quot;rssguard&quot;. Do
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>m_cmbDatabaseDriver</tabstop>
<tabstop>m_spinMysqlPort</tabstop>
<tabstop>m_checkMysqlShowPassword</tabstop>
<tabstop>m_btnMysqlTestSetup</tabstop>
<tabstop>m_listSettings</tabstop>
<tabstop>m_checkSqliteUseInMemoryDatabase</tabstop>
<tabstop>m_checkAutostart</tabstop>
<tabstop>m_checkRemoveTrolltechJunk</tabstop>
<tabstop>m_checkForUpdatesOnStart</tabstop>
<tabstop>m_scrollShortcuts</tabstop>
<tabstop>m_tabUi</tabstop>
<tabstop>m_scrollIconSkins</tabstop>
<tabstop>m_cmbIconTheme</tabstop>
<tabstop>m_treeSkins</tabstop>
<tabstop>m_radioTrayOff</tabstop>
<tabstop>m_checkHideWhenMinimized</tabstop>
<tabstop>m_checkHidden</tabstop>
<tabstop>m_radioTrayOn</tabstop>
<tabstop>m_checkNewTabDoubleClick</tabstop>
<tabstop>m_hideTabBarIfOneTabVisible</tabstop>
<tabstop>m_checkCloseTabsDoubleClick</tabstop>
<tabstop>m_checkCloseTabsMiddleClick</tabstop>
<tabstop>m_cmbToolbarButtonStyle</tabstop>
<tabstop>m_cmbSelectToolBar</tabstop>
<tabstop>m_treeLanguages</tabstop>
<tabstop>m_tabBrowserProxy</tabstop>
<tabstop>m_checkQueueTabs</tabstop>
<tabstop>m_checkEnableJavascript</tabstop>
<tabstop>m_checkEnablePlugins</tabstop>
<tabstop>m_checkAutoLoadImages</tabstop>
<tabstop>m_checkMouseGestures</tabstop>
<tabstop>m_grpCustomExternalBrowser</tabstop>
<tabstop>m_txtExternalBrowserExecutable</tabstop>
<tabstop>m_btnExternalBrowserExecutable</tabstop>
<tabstop>m_txtExternalBrowserArguments</tabstop>
<tabstop>m_cmbExternalBrowserPreset</tabstop>
<tabstop>m_cmbProxyType</tabstop>
<tabstop>m_txtProxyHost</tabstop>
<tabstop>m_spinProxyPort</tabstop>
<tabstop>m_txtProxyUsername</tabstop>
<tabstop>m_txtProxyPassword</tabstop>
<tabstop>m_checkShowPassword</tabstop>
<tabstop>m_tabFeedsMessages</tabstop>
<tabstop>m_checkUpdateAllFeedsOnStartup</tabstop>
<tabstop>m_checkAutoUpdate</tabstop>
<tabstop>m_spinAutoUpdateInterval</tabstop>
<tabstop>m_spinFeedUpdateTimeout</tabstop>
<tabstop>m_cmbCountsFeedList</tabstop>
<tabstop>m_checkRemoveReadMessagesOnExit</tabstop>
<tabstop>m_checkKeppMessagesInTheMiddle</tabstop>
<tabstop>m_checkMessagesDateTimeFormat</tabstop>
<tabstop>m_cmbMessagesDateTimeFormat</tabstop>
<tabstop>m_checkRemoveDuplicateMessages</tabstop>
<tabstop>m_rbDownloadsAskEachFile</tabstop>
<tabstop>m_rbDownloadsSaveAllIntoDirectory</tabstop>
<tabstop>m_txtDownloadsTargetDirectory</tabstop>
<tabstop>m_btnDownloadsTargetDirectory</tabstop>
</tabstops>
<resources/>
<connections>
<connection>

View file

@ -38,7 +38,7 @@ DatabaseFactory::DatabaseFactory(QObject *parent)
DatabaseFactory::~DatabaseFactory() {
}
DatabaseFactory::MySQLError DatabaseFactory::mysqlTestConnection(const QString &hostname, int port,
DatabaseFactory::MySQLError DatabaseFactory::mysqlTestConnection(const QString &hostname, int port, const QString &w_database,
const QString &username, const QString &password) {
QSqlDatabase database = QSqlDatabase::addDatabase(APP_DB_MYSQL_DRIVER, APP_DB_MYSQL_TEST);
@ -46,6 +46,7 @@ DatabaseFactory::MySQLError DatabaseFactory::mysqlTestConnection(const QString &
database.setPort(port);
database.setUserName(username);
database.setPassword(password);
database.setDatabaseName(w_database);
if (database.open()) {
// Connection succeeded, clean up the mess and return OK status.
@ -65,6 +66,9 @@ QString DatabaseFactory::mysqlInterpretErrorCode(MySQLError error_code) {
case MySQLOk:
return tr("MySQL server works as expected.");
case MySQLUnknownDatabase:
return tr("Selected database does not exist (yet).");
case MySQLCantConnect:
case MySQLConnectionError:
case MySQLUnknownHost:
@ -498,7 +502,7 @@ QSqlDatabase DatabaseFactory::mysqlConnection(const QString &connection_name) {
database.setPort(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLPort)).toInt());
database.setUserName(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLUsername)).toString());
database.setPassword(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLPassword)).toString());
database.setDatabaseName(APP_LOW_NAME);
database.setDatabaseName(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLDatabase)).toString());
}
if (!database.isOpen() && !database.open()) {
@ -518,6 +522,7 @@ QSqlDatabase DatabaseFactory::mysqlConnection(const QString &connection_name) {
QSqlDatabase DatabaseFactory::mysqlInitializeDatabase(const QString &connection_name) {
// Folders are created. Create new QSQLDatabase object.
QSqlDatabase database = QSqlDatabase::addDatabase(APP_DB_MYSQL_DRIVER, connection_name);
QString database_name = qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLDatabase)).toString();
database.setHostName(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLHostname)).toString());
database.setPort(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLPort)).toInt());
@ -532,7 +537,7 @@ QSqlDatabase DatabaseFactory::mysqlInitializeDatabase(const QString &connection_
QSqlQuery query_db(database);
query_db.setForwardOnly(true);
if (!query_db.exec("USE rssguard") || !query_db.exec("SELECT inf_value FROM Information WHERE inf_key = 'schema_version'")) {
if (!query_db.exec(QString("USE %1").arg(database_name)) || !query_db.exec("SELECT inf_value FROM Information WHERE inf_key = 'schema_version'")) {
// If no "rssguard" database exists or schema version is wrong, then initialize it.
qWarning("Error occurred. MySQL database is not initialized. Initializing now.");
@ -548,8 +553,9 @@ QSqlDatabase DatabaseFactory::mysqlInitializeDatabase(const QString &connection_
QStringList statements = QString(file_init.readAll()).split(APP_DB_COMMENT_SPLIT, QString::SkipEmptyParts);
database.transaction();
foreach(const QString &statement, statements) {
query_db.exec(statement);
foreach(QString statement, statements) {
// Assign real database name and run the query.
query_db.exec(statement.replace("##", database_name));
if (query_db.lastError().isValid()) {
qFatal("MySQL database initialization failed. Initialization script '%s' is not correct. Error : '%s'.",

View file

@ -42,11 +42,12 @@ class DatabaseFactory : public QObject {
// Describes possible MySQL-specific errors.
enum MySQLError {
MySQLOk = 0,
MySQLAccessDenied = 1045,
MySQLConnectionError = 2002,
MySQLCantConnect = 2003,
MySQLUnknownHost = 2005
MySQLOk = 0,
MySQLAccessDenied = 1045,
MySQLUnknownDatabase = 1049,
MySQLConnectionError = 2002,
MySQLCantConnect = 2003,
MySQLUnknownHost = 2005
};
//
@ -95,7 +96,8 @@ class DatabaseFactory : public QObject {
// Tests if database connection with given data
// can be established and returns 0 if it can.
// Otherwise returns MySQL-specific error code.
MySQLError mysqlTestConnection(const QString &hostname, int port, const QString &username, const QString &password);
MySQLError mysqlTestConnection(const QString &hostname, int port, const QString &w_database,
const QString &username, const QString &password);
// Interprets MySQL error code.
QString mysqlInterpretErrorCode(MySQLError error_code);

View file

@ -199,6 +199,9 @@ DVALUE(char*) Database::MySQLUsernameDef = "";
DKEY Database::MySQLPassword = "mysql_password";
DVALUE(char*) Database::MySQLPasswordDef = "";
DKEY Database::MySQLDatabase = "mysql_database";
DVALUE(char*) Database::MySQLDatabaseDef = APP_LOW_NAME;
DKEY Database::MySQLPort = "mysql_port";
DVALUE(int) Database::MySQLPortDef = APP_DB_MYSQL_PORT;

View file

@ -221,6 +221,9 @@ namespace Database {
KEY MySQLPort;
VALUE(int) MySQLPortDef;
KEY MySQLDatabase;
VALUE(char*) MySQLDatabaseDef;
KEY ActiveDriver;
VALUE(char*) ActiveDriverDef;
}