Added some initial "edit account" dialog etc.

This commit is contained in:
Martin Rotter 2016-02-16 13:32:23 +01:00
parent 2c86dde8a4
commit d6ba170efd
19 changed files with 896 additions and 68 deletions

View File

@ -361,6 +361,8 @@ file( GLOB APP_SOURCES_GL
"src/services/tt-rss/gui/*.cpp"
"src/services/tt-rss/network/*.cpp"
"src/services/owncloud/*.cpp"
"src/services/owncloud/network/*.cpp"
"src/services/owncloud/gui/*.cpp"
"src/network-web/*.cpp"
"src/network-web/adblock/*.cpp"
"src/*.cpp")
@ -391,6 +393,8 @@ file( GLOB APP_HEADERS
"src/services/tt-rss/gui/*.h"
"src/services/tt-rss/network/*.h"
"src/services/owncloud/*.h"
"src/services/owncloud/network/*.h"
"src/services/owncloud/gui/*.h"
"src/network-web/*.h"
"src/network-web/adblock/*.h")
@ -400,6 +404,7 @@ file( GLOB APP_FORMS
"src/gui/*.ui"
"src/services/standard/gui/*.ui"
"src/services/tt-rss/gui/*.ui"
"src/services/owncloud/gui/*.ui"
"src/network-web/*.ui"
"src/network-web/adblock/*.ui")

View File

@ -54,6 +54,8 @@
#include <QFileDialog>
#include <QTextStream>
#include "services/owncloud/network/owncloudnetworkfactory.h"
FormMain::FormMain(QWidget *parent, Qt::WindowFlags f)
: QMainWindow(parent, f), m_ui(new Ui::FormMain) {
@ -83,6 +85,21 @@ FormMain::FormMain(QWidget *parent, Qt::WindowFlags f)
// Initialize the web factory.
WebFactory::instance()->loadState();
OwnCloudNetworkFactory fac;
fac.setAuthIsUsed(true);
fac.setUrl("https://cloud.yarpen.cz");
fac.setAuthPassword("rssguard135");
fac.setAuthUsername("rssguard");
OwnCloudStatusResponse user = fac.status();
QString ver = user.version();
int aaaa = 0;
}
FormMain::~FormMain() {

View File

@ -86,7 +86,7 @@ void FormUpdate::checkForUpdates() {
const bool is_self_update_for_this_system = isUpdateForThisSystem() && isSelfUpdateSupported();
if (SystemFactory::isUpdateNewer(update.first.m_availableVersion)) {
if (SystemFactory::isUpdateNewer(update.first.m_availableVersion, APP_VERSION)) {
m_ui->m_lblStatus->setStatus(WidgetWithStatus::Ok,
tr("New release available."),
tr("This is new version which can be\ndownloaded and installed."));

View File

@ -206,25 +206,25 @@ QPair<UpdateInfo, QNetworkReply::NetworkError> SystemFactory::checkForUpdates()
return result;
}
bool SystemFactory::isUpdateNewer(const QString &update_version) {
QStringList current_version_tkn = QString(APP_VERSION).split(QL1C('.'));
QStringList new_version_tkn = update_version.split(QL1C('.'));
bool SystemFactory::isUpdateNewer(const QString &new_version, const QString &base_version) {
QStringList base_version_tkn = base_version.split(QL1C('.'));
QStringList new_version_tkn = new_version.split(QL1C('.'));
while (!current_version_tkn.isEmpty() && !new_version_tkn.isEmpty()) {
const int current_number = current_version_tkn.takeFirst().toInt();
while (!base_version_tkn.isEmpty() && !new_version_tkn.isEmpty()) {
const int base_number = base_version_tkn.takeFirst().toInt();
const int new_number = new_version_tkn.takeFirst().toInt();
if (new_number > current_number) {
if (new_number > base_number) {
// New version is indeed higher thatn current version.
return true;
}
else if (new_number < current_number) {
else if (new_number < base_number) {
return false;
}
}
// Versions are either the same or they have unequal sizes.
if (current_version_tkn.isEmpty() && new_version_tkn.isEmpty()) {
if (base_version_tkn.isEmpty() && new_version_tkn.isEmpty()) {
// Versions are the same.
return false;
}
@ -273,7 +273,8 @@ UpdateInfo SystemFactory::parseUpdatesFile(const QByteArray &updates_file, const
void SystemFactory::checkForUpdatesOnStartup() {
const UpdateCheck updates = checkForUpdates();
if (updates.second == QNetworkReply::NoError && isUpdateNewer(updates.first.m_availableVersion)) {
if (updates.second == QNetworkReply::NoError && isUpdateNewer(updates.first.m_availableVersion,
APP_VERSION)) {
qApp->showGuiMessage(tr("New version available"),
tr("Click the bubble for more information."),
QSystemTrayIcon::Information,

View File

@ -87,7 +87,7 @@ class SystemFactory : public QObject {
QPair<UpdateInfo, QNetworkReply::NetworkError> checkForUpdates() const;
// Checks if update is newer than current application version.
static bool isUpdateNewer(const QString &update_version);
static bool isUpdateNewer(const QString &new_version, const QString &base_version);
public slots:
void checkForUpdatesOnStartup();

View File

@ -194,13 +194,20 @@ NetworkResult NetworkFactory::downloadFeedFile(const QString &url, int timeout,
NetworkResult NetworkFactory::downloadFile(const QString &url, int timeout,
QByteArray &output, bool protected_contents,
const QString &username, const QString &password) {
// Here, we want to achieve "synchronous" approach because we want synchronout download API for
const QString &username, const QString &password, bool set_basic_header) {
// Here, we want to achieve "synchronous" approach because we want synchronous download API for
// some use-cases too.
Downloader downloader;
QEventLoop loop;
NetworkResult result;
if (set_basic_header) {
QString basic_value = username + ":" + password;
QString header_value = QString("Basic ") + QString(basic_value.toUtf8().toBase64());
downloader.appendRawHeader("Authorization", header_value.toLocal8Bit());
}
// We need to quit event loop when the download finishes.
QObject::connect(&downloader, SIGNAL(completed(QNetworkReply::NetworkError)), &loop, SLOT(quit()));

View File

@ -56,7 +56,7 @@ class NetworkFactory {
// and given timeout.
static NetworkResult downloadFile(const QString &url, int timeout, QByteArray &output,
bool protected_contents = false, const QString &username = QString(),
const QString &password = QString());
const QString &password = QString(), bool set_basic_header = false);
};
#endif // NETWORKFACTORY_H

View File

@ -97,6 +97,40 @@ QList<QAction*> ServiceRoot::serviceMenu() {
return QList<QAction*>();
}
void ServiceRoot::removeOldFeedTree(bool including_messages) {
QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings);
QSqlQuery query(database);
query.setForwardOnly(true);
query.prepare(QSL("DELETE FROM Feeds WHERE account_id = :account_id;"));
query.bindValue(QSL(":account_id"), accountId());
query.exec();
query.prepare(QSL("DELETE FROM Categories WHERE account_id = :account_id;"));
query.bindValue(QSL(":account_id"), accountId());
query.exec();
if (including_messages) {
query.prepare(QSL("DELETE FROM Messages WHERE account_id = :account_id;"));
query.bindValue(QSL(":account_id"), accountId());
query.exec();
}
}
void ServiceRoot::removeLeftOverMessages() {
QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings);
QSqlQuery query(database);
int account_id = accountId();
query.setForwardOnly(true);
query.prepare(QSL("DELETE FROM Messages WHERE account_id = :account_id AND feed NOT IN (SELECT custom_id FROM Feeds WHERE account_id = :account_id);"));
query.bindValue(QSL(":account_id"), account_id);
if (!query.exec()) {
qWarning("Removing of left over messages failed: '%s'.", qPrintable(query.lastError().text()));
}
}
QList<Message> ServiceRoot::undeletedMessages() const {
QList<Message> messages;
const int account_id = accountId();

View File

@ -44,10 +44,6 @@ class ServiceRoot : public RootItem {
explicit ServiceRoot(RootItem *parent = NULL);
virtual ~ServiceRoot();
/////////////////////////////////////////
// /* Members to override.
/////////////////////////////////////////
bool deleteViaGui();
bool markAsReadUnread(ReadStatus status);
@ -149,10 +145,6 @@ class ServiceRoot : public RootItem {
// Selected item is naturally recycle bin.
virtual bool onAfterMessagesRestoredFromBin(RootItem *selected_item, const QList<Message> &messages);
/////////////////////////////////////////
// Members to override. */
/////////////////////////////////////////
// Obvious methods to wrap signals.
void itemChanged(const QList<RootItem*> &items);
void requestReloadMessageList(bool mark_selected_messages_read);
@ -166,6 +158,17 @@ class ServiceRoot : public RootItem {
virtual void addNewCategory() = 0;
protected:
// Removes all messages/categories/feeds which are
// associated with this account.
void removeOldFeedTree(bool including_messages);
// Removes messages which do not belong to any
// existing feed.
//
// NOTE: This situation may happen if user deletes some feed
// from another machine and then performs sync-in on this machine.
void removeLeftOverMessages();
QStringList textualFeedIds(const QList<Feed*> &feeds) const;
// Takes lists of feeds/categories and assembles them into the tree structure.

View File

@ -1,7 +1,26 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2016 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 OWNCLOUD_DEFINITIONS_H
#define OWNCLOUD_DEFINITIONS_H
#define API_VERSION "1.2"
#define CONTENT_TYPE "application/json; charset=utf-8"
#define API_VERSION "1.2"
#define MINIMAL_OC_VERSION "6.0.5"
#endif // OWNCLOUD_DEFINITIONS_H

View File

@ -0,0 +1,230 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2016 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 "services/owncloud/gui/formeditowncloudaccount.h"
#include "services/owncloud/definitions.h"
#include "services/owncloud/owncloudserviceroot.h"
#include "services/owncloud/network/owncloudnetworkfactory.h"
#include "miscellaneous/iconfactory.h"
#include "network-web/networkfactory.h"
FormEditOwnCloudAccount::FormEditOwnCloudAccount(QWidget *parent)
: QDialog(parent), m_ui(new Ui::FormEditOwnCloudAccount), m_editableRoot(NULL) {
m_ui->setupUi(this);
m_btnOk = m_ui->m_buttonBox->button(QDialogButtonBox::Ok);
setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint);
setWindowIcon(qApp->icons()->fromTheme(QSL("application-ttrss")));
m_ui->m_lblServerSideUpdateInformation->setText(tr("Leaving this option on causes that updates "
"of feeds will be probably much slower and may time-out often."));
m_ui->m_lblDescription->setText(tr("Note that at least API level %1 is required.").arg(MINIMAL_OC_VERSION));
m_ui->m_txtPassword->lineEdit()->setPlaceholderText(tr("Password for your TT-RSS account"));
m_ui->m_txtUsername->lineEdit()->setPlaceholderText(tr("Username for your TT-RSS account"));
m_ui->m_txtUrl->lineEdit()->setPlaceholderText(tr("FULL URL of your TT-RSS instance WITH trailing \"/api/\" string"));
m_ui->m_lblTestResult->setStatus(WidgetWithStatus::Information,
tr("No test done yet."),
tr("Here, results of connection test are shown."));
setTabOrder(m_ui->m_txtUrl->lineEdit(), m_ui->m_checkServerSideUpdate);
setTabOrder(m_ui->m_checkServerSideUpdate, m_ui->m_txtUsername->lineEdit());
setTabOrder(m_ui->m_txtUsername->lineEdit(), m_ui->m_txtPassword->lineEdit());
setTabOrder(m_ui->m_txtPassword->lineEdit(), m_ui->m_checkShowPassword);
setTabOrder(m_ui->m_checkShowPassword, m_ui->m_btnTestSetup);
setTabOrder(m_ui->m_btnTestSetup, m_ui->m_buttonBox);
connect(m_ui->m_checkShowPassword, SIGNAL(toggled(bool)), this, SLOT(displayPassword(bool)));
connect(m_ui->m_buttonBox, SIGNAL(accepted()), this, SLOT(onClickedOk()));
connect(m_ui->m_buttonBox, SIGNAL(rejected()), this, SLOT(onClickedCancel()));
connect(m_ui->m_txtPassword->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(onPasswordChanged()));
connect(m_ui->m_txtUsername->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(onUsernameChanged()));
connect(m_ui->m_txtUrl->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(onUrlChanged()));
connect(m_ui->m_txtPassword->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(checkOkButton()));
connect(m_ui->m_txtUsername->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(checkOkButton()));
connect(m_ui->m_txtUrl->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(checkOkButton()));
connect(m_ui->m_btnTestSetup, SIGNAL(clicked()), this, SLOT(performTest()));
onPasswordChanged();
onUsernameChanged();
onUrlChanged();
checkOkButton();
displayPassword(false);
}
FormEditOwnCloudAccount::~FormEditOwnCloudAccount() {
}
OwnCloudServiceRoot *FormEditOwnCloudAccount::execForCreate() {
setWindowTitle(tr("Add new Tiny Tiny RSS account"));
exec();
return m_editableRoot;
}
void FormEditOwnCloudAccount::execForEdit(OwnCloudServiceRoot *existing_root) {
setWindowTitle(tr("Edit existing Tiny Tiny RSS account"));
m_editableRoot = existing_root;
// TODO: todo
/* m_ui->m_txtUsername->lineEdit()->setText(existing_root->network()->username());
m_ui->m_txtPassword->lineEdit()->setText(existing_root->network()->password());
m_ui->m_txtUrl->lineEdit()->setText(existing_root->network()->url());
m_ui->m_checkServerSideUpdate->setChecked(existing_root->network()->forceServerSideUpdate());
*/
exec();
}
void FormEditOwnCloudAccount::displayPassword(bool display) {
m_ui->m_txtPassword->lineEdit()->setEchoMode(display ? QLineEdit::Normal : QLineEdit::Password);
}
void FormEditOwnCloudAccount::performTest() {
// TODO: todo
/*TtRssNetworkFactory factory;
factory.setUsername(m_ui->m_txtUsername->lineEdit()->text());
factory.setPassword(m_ui->m_txtPassword->lineEdit()->text());
factory.setUrl(m_ui->m_txtUrl->lineEdit()->text());
factory.setAuthIsUsed(m_ui->m_gbHttpAuthentication->isChecked());
factory.setAuthUsername(m_ui->m_txtHttpUsername->lineEdit()->text());
factory.setAuthPassword(m_ui->m_txtHttpPassword->lineEdit()->text());
factory.setForceServerSideUpdate(m_ui->m_checkServerSideUpdate->isChecked());
TtRssLoginResponse result = factory.login();
if (result.isLoaded()) {
if (result.hasError()) {
QString error = result.error();
if (error == API_DISABLED) {
m_ui->m_lblTestResult->setStatus(WidgetWithStatus::Error,
tr("API access on selected server is not enabled."),
tr("API access on selected server is not enabled."));
}
else if (error == LOGIN_ERROR) {
m_ui->m_lblTestResult->setStatus(WidgetWithStatus::Error,
tr("Entered credentials are incorrect."),
tr("Entered credentials are incorrect."));
}
else {
m_ui->m_lblTestResult->setStatus(WidgetWithStatus::Error,
tr("Other error occurred, contact developers."),
tr("Other error occurred, contact developers."));
}
}
else if (result.apiLevel() < MINIMAL_API_LEVEL) {
m_ui->m_lblTestResult->setStatus(WidgetWithStatus::Error,
tr("Selected Tiny Tiny RSS server is running unsupported version of API (%1). At least API level %2 is required.").arg(QString::number(result.apiLevel()),
QString::number(MINIMAL_API_LEVEL)),
tr("Selected Tiny Tiny RSS server is running unsupported version of API."));
}
else {
m_ui->m_lblTestResult->setStatus(WidgetWithStatus::Ok,
tr("Tiny Tiny RSS server is okay, running with API level %1, while at least API level %2 is required.").arg(QString::number(result.apiLevel()),
QString::number(MINIMAL_API_LEVEL)),
tr("Tiny Tiny RSS server is okay."));
}
}
else if (factory.lastError() != QNetworkReply::NoError ) {
m_ui->m_lblTestResult->setStatus(WidgetWithStatus::Error,
tr("Network error: '%1'.").arg(NetworkFactory::networkErrorText(factory.lastError())),
tr("Network error, have you entered correct Tiny Tiny RSS API endpoint and password?"));
}
else {
m_ui->m_lblTestResult->setStatus(WidgetWithStatus::Error,
tr("Unspecified error, did you enter correct URL?"),
tr("Unspecified error, did you enter correct URL?"));
}*/
}
void FormEditOwnCloudAccount::onClickedOk() {
bool editing_account = true;
if (m_editableRoot == NULL) {
// We want to confirm newly created account.
// So save new account into DB, setup its properties.
m_editableRoot = new OwnCloudServiceRoot();
editing_account = false;
}
// TODO: TODO
/*
m_editableRoot->network()->setUrl(m_ui->m_txtUrl->lineEdit()->text());
m_editableRoot->network()->setUsername(m_ui->m_txtUsername->lineEdit()->text());
m_editableRoot->network()->setPassword(m_ui->m_txtPassword->lineEdit()->text());
m_editableRoot->network()->setAuthIsUsed(m_ui->m_gbHttpAuthentication->isChecked());
m_editableRoot->network()->setAuthUsername(m_ui->m_txtHttpUsername->lineEdit()->text());
m_editableRoot->network()->setAuthPassword(m_ui->m_txtHttpPassword->lineEdit()->text());
m_editableRoot->network()->setForceServerSideUpdate(m_ui->m_checkServerSideUpdate->isChecked());
m_editableRoot->saveAccountDataToDatabase();
accept();
if (editing_account) {
m_editableRoot->network()->logout();
m_editableRoot->completelyRemoveAllData();
m_editableRoot->syncIn();
}*/
}
void FormEditOwnCloudAccount::onClickedCancel() {
reject();
}
void FormEditOwnCloudAccount::onUsernameChanged() {
const QString username = m_ui->m_txtUsername->lineEdit()->text();
if (username.isEmpty()) {
m_ui->m_txtUsername->setStatus(WidgetWithStatus::Error, tr("Username cannot be empty."));
}
else {
m_ui->m_txtUsername->setStatus(WidgetWithStatus::Ok, tr("Username is okay."));
}
}
void FormEditOwnCloudAccount::onPasswordChanged() {
const QString password = m_ui->m_txtPassword->lineEdit()->text();
if (password.isEmpty()) {
m_ui->m_txtPassword->setStatus(WidgetWithStatus::Error, tr("Password cannot be empty."));
}
else {
m_ui->m_txtPassword->setStatus(WidgetWithStatus::Ok, tr("Password is okay."));
}
}
void FormEditOwnCloudAccount::onUrlChanged() {
const QString url = m_ui->m_txtUrl->lineEdit()->text();
if (url.isEmpty()) {
m_ui->m_txtUrl->setStatus(WidgetWithStatus::Error, tr("URL cannot be empty."));
}
else if (!url.endsWith(QL1S("/api/"))) {
m_ui->m_txtUrl->setStatus(WidgetWithStatus::Warning, tr("URL should end with \"/api/\"."));
}
else {
m_ui->m_txtUrl->setStatus(WidgetWithStatus::Ok, tr("URL is okay."));
}
}
void FormEditOwnCloudAccount::checkOkButton() {
m_btnOk->setEnabled(!m_ui->m_txtUsername->lineEdit()->text().isEmpty() &&
!m_ui->m_txtPassword->lineEdit()->text().isEmpty() &&
!m_ui->m_txtUrl->lineEdit()->text().isEmpty());
}

View File

@ -0,0 +1,60 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2016 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 FORMEDITOWNCLOUDACCOUNT_H
#define FORMEDITOWNCLOUDACCOUNT_H
#include <QDialog>
#include "ui_formeditowncloudaccount.h"
namespace Ui {
class FormEditAccount;
}
class OwnCloudServiceRoot;
class FormEditOwnCloudAccount : public QDialog {
Q_OBJECT
public:
explicit FormEditOwnCloudAccount(QWidget *parent = 0);
virtual ~FormEditOwnCloudAccount();
OwnCloudServiceRoot *execForCreate();
void execForEdit(OwnCloudServiceRoot *existing_root);
private slots:
void displayPassword(bool display);
void performTest();
void onClickedOk();
void onClickedCancel();
void onUsernameChanged();
void onPasswordChanged();
void onUrlChanged();
void checkOkButton();
private:
QScopedPointer<Ui::FormEditOwnCloudAccount> m_ui;
OwnCloudServiceRoot *m_editableRoot;
QPushButton *m_btnOk;
};
#endif // FORMEDITOWNCLOUDACCOUNT_H

View File

@ -0,0 +1,164 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FormEditOwnCloudAccount</class>
<widget class="QDialog" name="FormEditOwnCloudAccount">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>541</width>
<height>273</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="m_lblTitle">
<property name="text">
<string>URL</string>
</property>
<property name="buddy">
<cstring>m_txtUrl</cstring>
</property>
</widget>
</item>
<item>
<widget class="LineEditWithStatus" name="m_txtUrl" native="true"/>
</item>
</layout>
</item>
<item row="1" column="0" colspan="2">
<widget class="QLabel" name="m_lblDescription">
<property name="text">
<string/>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QCheckBox" name="m_checkServerSideUpdate">
<property name="text">
<string>Force execution of server-side update when updating feeds from RSS Guard</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QLabel" name="m_lblServerSideUpdateInformation">
<property name="text">
<string/>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="QGroupBox" name="m_gbAuthentication">
<property name="toolTip">
<string>Some feeds require authentication, including GMail feeds. BASIC, NTLM-2 and DIGEST-MD5 authentication schemes are supported.</string>
</property>
<property name="title">
<string>Authentication</string>
</property>
<property name="flat">
<bool>false</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Username</string>
</property>
<property name="buddy">
<cstring>m_txtUsername</cstring>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Password</string>
</property>
<property name="buddy">
<cstring>m_txtPassword</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="LineEditWithStatus" name="m_txtPassword" native="true"/>
</item>
<item row="0" column="1">
<widget class="LineEditWithStatus" name="m_txtUsername" native="true"/>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="m_checkShowPassword">
<property name="text">
<string>Show password</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="5" column="0">
<widget class="QPushButton" name="m_btnTestSetup">
<property name="text">
<string>&amp;Test setup</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="LabelWithStatus" name="m_lblTestResult" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="m_buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LineEditWithStatus</class>
<extends>QWidget</extends>
<header>lineeditwithstatus.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>LabelWithStatus</class>
<extends>QWidget</extends>
<header>labelwithstatus.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,211 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2016 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 "services/owncloud/network/owncloudnetworkfactory.h"
#include "services/owncloud/definitions.h"
#include "network-web/networkfactory.h"
#include "miscellaneous/application.h"
#include "miscellaneous/settings.h"
#include <QPixmap>
OwnCloudNetworkFactory::OwnCloudNetworkFactory()
: m_url(QString()), m_forceServerSideUpdate(false), m_authIsUsed(false),
m_authUsername(QString()), m_authPassword(QString()), m_urlUser(QString()), m_urlStatus(QString()) {
}
OwnCloudNetworkFactory::~OwnCloudNetworkFactory() {
}
QString OwnCloudNetworkFactory::url() const {
return m_url;
}
void OwnCloudNetworkFactory::setUrl(const QString &url) {
if (url.endsWith('/')) {
m_url = url;
}
else {
m_url = url + '/';
}
// Store endpoints.
m_urlUser = m_url + "index.php/apps/news/api/v1-2/user";
m_urlStatus = m_url + "index.php/apps/news/api/v1-2/status";
}
bool OwnCloudNetworkFactory::forceServerSideUpdate() const {
return m_forceServerSideUpdate;
}
void OwnCloudNetworkFactory::setForceServerSideUpdate(bool force_update) {
m_forceServerSideUpdate = force_update;
}
bool OwnCloudNetworkFactory::authIsUsed() const {
return m_authIsUsed;
}
void OwnCloudNetworkFactory::setAuthIsUsed(bool authIsUsed) {
m_authIsUsed = authIsUsed;
}
QString OwnCloudNetworkFactory::authUsername() const {
return m_authUsername;
}
void OwnCloudNetworkFactory::setAuthUsername(const QString &auth_username) {
m_authUsername = auth_username;
}
QString OwnCloudNetworkFactory::authPassword() const {
return m_authPassword;
}
void OwnCloudNetworkFactory::setAuthPassword(const QString &auth_password) {
m_authPassword = auth_password;
}
QNetworkReply::NetworkError OwnCloudNetworkFactory::lastError() const {
return m_lastError;
}
OwnCloudUserResponse OwnCloudNetworkFactory::userInfo() {
QByteArray result_raw;
NetworkResult network_reply = NetworkFactory::downloadFile(m_urlUser,
qApp->settings()->value(GROUP(Feeds),
SETTING(Feeds::UpdateTimeout)).toInt(),
result_raw,
m_authIsUsed, m_authUsername, m_authPassword,
true);
OwnCloudUserResponse user_response(QString::fromUtf8(result_raw));
if (network_reply.first != QNetworkReply::NoError) {
qWarning("ownCloud: Obtaining user info failed with error %d.", network_reply.first);
}
m_lastError = network_reply.first;
return user_response;
}
OwnCloudStatusResponse OwnCloudNetworkFactory::status() {
QByteArray result_raw;
NetworkResult network_reply = NetworkFactory::downloadFile(m_urlStatus,
qApp->settings()->value(GROUP(Feeds),
SETTING(Feeds::UpdateTimeout)).toInt(),
result_raw,
m_authIsUsed, m_authUsername, m_authPassword,
true);
OwnCloudStatusResponse status_response(QString::fromUtf8(result_raw));
if (network_reply.first != QNetworkReply::NoError) {
qWarning("ownCloud: Obtaining status info failed with error %d.", network_reply.first);
}
m_lastError = network_reply.first;
return status_response;
}
OwnCloudResponse::OwnCloudResponse(const QString &raw_content) {
m_rawContent = QtJson::parse(raw_content).toMap();
}
OwnCloudResponse::~OwnCloudResponse() {
}
bool OwnCloudResponse::isLoaded() const {
return !m_rawContent.empty();
}
QString OwnCloudResponse::toString() const {
return QtJson::serializeStr(m_rawContent);
}
OwnCloudUserResponse::OwnCloudUserResponse(const QString &raw_content) : OwnCloudResponse(raw_content) {
}
OwnCloudUserResponse::~OwnCloudUserResponse() {
}
QString OwnCloudUserResponse::displayName() const {
if (isLoaded()) {
return m_rawContent["displayName"].toString();
}
else {
return QString();
}
}
QString OwnCloudUserResponse::userId() const {
if (isLoaded()) {
return m_rawContent["userId"].toString();
}
else {
return QString();
}
}
QDateTime OwnCloudUserResponse::lastLoginTime() const {
if (isLoaded()) {
return QDateTime::fromMSecsSinceEpoch(m_rawContent["lastLoginTimestamp"].value<qint64>());
}
else {
return QDateTime();
}
}
QIcon OwnCloudUserResponse::avatar() const {
if (isLoaded()) {
QString image_data = m_rawContent["avatar"].toMap()["data"].toString();
QByteArray decoded_data = QByteArray::fromBase64(image_data.toLocal8Bit());
QPixmap image;
if (image.loadFromData(decoded_data)) {
return QIcon(image);
}
}
return QIcon();
}
OwnCloudStatusResponse::OwnCloudStatusResponse(const QString &raw_content) : OwnCloudResponse(raw_content) {
}
OwnCloudStatusResponse::~OwnCloudStatusResponse() {
}
QString OwnCloudStatusResponse::version() const {
if (isLoaded()) {
return m_rawContent["version"].toString();
}
else {
return QString();
}
}
bool OwnCloudStatusResponse::misconfiguredCron() const {
if (isLoaded()) {
return m_rawContent["warnings"].toMap()["improperlyConfiguredCron"].toBool();
}
else {
return false;
}
}

View File

@ -0,0 +1,104 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2016 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 OWNCLOUDNETWORKFACTORY_H
#define OWNCLOUDNETWORKFACTORY_H
#include <QDateTime>
#include <QString>
#include <QIcon>
#include <QNetworkReply>
#include "qt-json/json.h"
class OwnCloudResponse {
public:
explicit OwnCloudResponse(const QString &raw_content = QString());
virtual ~OwnCloudResponse();
bool isLoaded() const;
QString toString() const;
protected:
QtJson::JsonObject m_rawContent;
};
class OwnCloudUserResponse : public OwnCloudResponse {
public:
explicit OwnCloudUserResponse(const QString &raw_content = QString());
virtual ~OwnCloudUserResponse();
QString userId() const;
QString displayName() const;
QDateTime lastLoginTime() const;
QIcon avatar() const;
};
class OwnCloudStatusResponse : public OwnCloudResponse {
public:
explicit OwnCloudStatusResponse(const QString &raw_content = QString());
virtual ~OwnCloudStatusResponse();
QString version() const;
bool misconfiguredCron() const;
};
class OwnCloudNetworkFactory {
public:
explicit OwnCloudNetworkFactory();
virtual ~OwnCloudNetworkFactory();
QString url() const;
void setUrl(const QString &url);
bool forceServerSideUpdate() const;
void setForceServerSideUpdate(bool force_update);
bool authIsUsed() const;
void setAuthIsUsed(bool authIsUsed);
QString authUsername() const;
void setAuthUsername(const QString &auth_username);
QString authPassword() const;
void setAuthPassword(const QString &auth_password);
QNetworkReply::NetworkError lastError() const;
// Operations.
// Get user info.
OwnCloudUserResponse userInfo();
// Get version info.
OwnCloudStatusResponse status();
private:
QString m_url;
bool m_forceServerSideUpdate;
bool m_authIsUsed;
QString m_authUsername;
QString m_authPassword;
QNetworkReply::NetworkError m_lastError;
// Endpoints.
QString m_urlUser;
QString m_urlStatus;
};
#endif // OWNCLOUDNETWORKFACTORY_H

View File

@ -1,3 +1,20 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2016 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 TTRSS_DEFINITIONS_H
#define TTRSS_DEFINITIONS_H

View File

@ -161,7 +161,7 @@
<item row="2" column="0" colspan="2">
<widget class="QCheckBox" name="m_checkServerSideUpdate">
<property name="text">
<string>Force execution of server-side update when updating feeds from RSS Guard</string>
<string>Force execution of server-side update when updating feeds from RSS Guard</string>
</property>
</widget>
</item>

View File

@ -579,40 +579,6 @@ QStringList TtRssServiceRoot::customIDsOfMessages(const QList<Message> &messages
return list;
}
void TtRssServiceRoot::removeOldFeedTree(bool including_messages) {
QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings);
QSqlQuery query(database);
query.setForwardOnly(true);
query.prepare(QSL("DELETE FROM Feeds WHERE account_id = :account_id;"));
query.bindValue(QSL(":account_id"), accountId());
query.exec();
query.prepare(QSL("DELETE FROM Categories WHERE account_id = :account_id;"));
query.bindValue(QSL(":account_id"), accountId());
query.exec();
if (including_messages) {
query.prepare(QSL("DELETE FROM Messages WHERE account_id = :account_id;"));
query.bindValue(QSL(":account_id"), accountId());
query.exec();
}
}
void TtRssServiceRoot::removeLeftOverMessages() {
QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings);
QSqlQuery query(database);
int account_id = accountId();
query.setForwardOnly(true);
query.prepare(QSL("DELETE FROM Messages WHERE account_id = :account_id AND feed NOT IN (SELECT custom_id FROM Feeds WHERE account_id = :account_id);"));
query.bindValue(QSL(":account_id"), account_id);
if (!query.exec()) {
qWarning("Removing of left over messages failed: '%s'.", qPrintable(query.lastError().text()));
}
}
void TtRssServiceRoot::cleanAllItems() {
foreach (RootItem *top_level_item, childItems()) {
if (top_level_item->kind() != RootItemKind::Bin) {

View File

@ -74,16 +74,6 @@ class TtRssServiceRoot : public ServiceRoot {
QStringList customIDsOfMessages(const QList<QPair<Message,Importance> > &changes);
QStringList customIDsOfMessages(const QList<Message> &messages);
// Removes all messages/categories/feeds which are
// associated with this account.
void removeOldFeedTree(bool including_messages);
// Removes messages which do not belong to any
// existing feed.
//
// NOTE: This situation may happen if user deletes some feed
// from another machine and then performs sync-in on this machine.
void removeLeftOverMessages();
void cleanAllItems();
// Takes new tree and adds its feeds/categories/whatever.