Work on enclosures, only editing of skins remains.
This commit is contained in:
parent
21f970d456
commit
8c1414c3df
12 changed files with 109 additions and 81 deletions
|
@ -444,19 +444,6 @@ bool FeedsModelFeed::removeItself() {
|
|||
return query_remove.exec();
|
||||
}
|
||||
|
||||
/*
|
||||
* postup zpracování zpráv:
|
||||
* 1. Kontrola, zda existují již v DB zprávy se stejným NAZVEM, AUTOREM, URL ze stejneho kanalu.
|
||||
* a. KONEC: Pokud neexistují, pak se aktuální nová zpráva přidá do DB.
|
||||
* b. Pokud existují, jde se na krok 2.
|
||||
* 2. Pokud má uživatel nastaveno mazání duplicitních zpráv, pak udělej a. Jinak jdi na krok 3.
|
||||
* a. Vymaž všechny zprávy, které byly nalezeny ve kroku 1.
|
||||
* b. Přidej tuto novou zprávu, nastav ji status přečtena na true.
|
||||
* 3. Uživatel nemá nastaveno mazani dupl zpráv. Novou zprávu přidáme do DB tehdy když zpráva
|
||||
* má datum získané z kanálu a zároveň identická zpráva s takovým datumem ještě v DB není.
|
||||
* */
|
||||
|
||||
|
||||
void FeedsModelFeed::updateMessages(const QList<Message> &messages) {
|
||||
int feed_id = id();
|
||||
QSqlDatabase database = qApp->database()->connection("FeedsModelFeed", DatabaseFactory::FromSettings);
|
||||
|
@ -476,12 +463,12 @@ void FeedsModelFeed::updateMessages(const QList<Message> &messages) {
|
|||
// 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);");
|
||||
"(feed, title, url, author, date_created, contents, enclosures) "
|
||||
"VALUES (:feed, :title, :url, :author, :date_created, :contents, :enclosures);");
|
||||
|
||||
if (remove_duplicates) {
|
||||
query_update.setForwardOnly(true);
|
||||
query_update.prepare("UPDATE Messages SET contents = :contents WHERE id = :id;");
|
||||
query_update.prepare("UPDATE Messages SET contents = :contents enclosures = :enclosures WHERE id = :id;");
|
||||
}
|
||||
|
||||
if (!database.transaction()) {
|
||||
|
@ -528,6 +515,7 @@ void FeedsModelFeed::updateMessages(const QList<Message> &messages) {
|
|||
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.bindValue(":enclosures", Enclosures::encodeEnclosuresToString(message.m_enclosures));
|
||||
|
||||
if (query_insert.exec() && query_insert.numRowsAffected() == 1) {
|
||||
setStatus(NewMessages);
|
||||
|
@ -543,6 +531,7 @@ void FeedsModelFeed::updateMessages(const QList<Message> &messages) {
|
|||
// messages and there is exactly ONE existing duplicate.
|
||||
query_update.bindValue(":id", ids.at(0));
|
||||
query_update.bindValue(":contents", message.m_contents);
|
||||
query_update.bindValue(":enclosures", Enclosures::encodeEnclosuresToString(message.m_enclosures));
|
||||
query_update.exec();
|
||||
query_update.finish();
|
||||
|
||||
|
@ -557,6 +546,7 @@ void FeedsModelFeed::updateMessages(const QList<Message> &messages) {
|
|||
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.bindValue(":enclosures", Enclosures::encodeEnclosuresToString(message.m_enclosures));
|
||||
|
||||
if (query_insert.exec() && query_insert.numRowsAffected() == 1) {
|
||||
setStatus(NewMessages);
|
||||
|
|
|
@ -132,6 +132,7 @@ Message MessagesModel::messageAt(int row_index) const {
|
|||
// Fill Message object with details.
|
||||
message.m_author = rec.value(MSG_DB_AUTHOR_INDEX).toString();
|
||||
message.m_contents = rec.value(MSG_DB_CONTENTS_INDEX).toString();
|
||||
message.m_enclosures = Enclosures::decodeEnclosuresFromString(rec.value(MSG_DB_ENCLOSURES_INDEX).toString());
|
||||
message.m_title = rec.value(MSG_DB_TITLE_INDEX).toString();
|
||||
message.m_url = rec.value(MSG_DB_URL_INDEX).toString();
|
||||
message.m_created = TextFactory::parseDateTime(rec.value(MSG_DB_DCREATED_INDEX).value<qint64>()).toLocalTime();
|
||||
|
|
|
@ -27,27 +27,27 @@
|
|||
|
||||
|
||||
// Represents single enclosure.
|
||||
class Enclosure {
|
||||
class Enclosures {
|
||||
public:
|
||||
explicit Enclosure() {
|
||||
m_url = m_title = "";
|
||||
}
|
||||
|
||||
static QList<Enclosure> decodeEnclosuresFromString(const QString &enclosures_data) {
|
||||
QList<Enclosure> enclosures;
|
||||
static QStringList decodeEnclosuresFromString(const QString &enclosures_data) {
|
||||
QStringList enclosures;
|
||||
|
||||
foreach (const QString &single_enclosure, enclosures_data.split(ENCLOSURES_OUTER_SEPARATOR, QString::SkipEmptyParts)) {
|
||||
Enclosure final_enclosure;
|
||||
final_enclosure.m_url = QByteArray::fromBase64(single_enclosure.toUtf8());
|
||||
|
||||
enclosures.append(final_enclosure);
|
||||
enclosures.append(QByteArray::fromBase64(single_enclosure.toLocal8Bit()));
|
||||
}
|
||||
|
||||
return enclosures;
|
||||
}
|
||||
|
||||
QString m_url;
|
||||
QString m_title;
|
||||
static QString encodeEnclosuresToString(const QStringList &enclosures) {
|
||||
QStringList enclosures_str;
|
||||
|
||||
foreach (const QString &enclosure, enclosures) {
|
||||
enclosures_str.append(enclosure.toLocal8Bit().toBase64());
|
||||
}
|
||||
|
||||
return enclosures_str.join(QString(ENCLOSURES_OUTER_SEPARATOR));
|
||||
}
|
||||
};
|
||||
|
||||
// Represents single message.
|
||||
|
@ -55,7 +55,7 @@ class Message {
|
|||
public:
|
||||
explicit Message() {
|
||||
m_title = m_url = m_author = m_contents = "";
|
||||
m_enclosures = QList<Enclosure>();
|
||||
m_enclosures = QStringList();
|
||||
}
|
||||
|
||||
QString m_title;
|
||||
|
@ -64,7 +64,7 @@ class Message {
|
|||
QString m_contents;
|
||||
QDateTime m_created;
|
||||
|
||||
QList<Enclosure> m_enclosures;
|
||||
QStringList m_enclosures;
|
||||
|
||||
// Is true if "created" date was obtained directly
|
||||
// from the feed, otherwise is false
|
||||
|
|
|
@ -70,12 +70,21 @@ QList<Message> ParsingFactory::parseAsATOM10(const QString &data) {
|
|||
// Deal with link.
|
||||
QDomNodeList elem_links = message_item.toElement().elementsByTagName("link");
|
||||
|
||||
for (int i = 0; i < elem_links.size(); i++) {
|
||||
new_message.m_url = elem_links.at(i).attributes().namedItem("href").toAttr().value();
|
||||
for (int i = 0; i < elem_links.size(); i++) {
|
||||
QDomElement link = elem_links.at(i).toElement();
|
||||
|
||||
if (!new_message.m_url.isNull() && !new_message.m_url.isEmpty()) {
|
||||
break;
|
||||
if (link.attribute("rel") == "enclosure") {
|
||||
new_message.m_enclosures.append(link.attribute("href"));
|
||||
|
||||
qDebug("Adding enclosure '%s' for the message.", qPrintable(new_message.m_enclosures.last()));
|
||||
}
|
||||
else {
|
||||
new_message.m_url = link.attribute("href");
|
||||
}
|
||||
}
|
||||
|
||||
if (new_message.m_url.isEmpty() && !new_message.m_enclosures.isEmpty()) {
|
||||
new_message.m_url = new_message.m_enclosures.first();
|
||||
}
|
||||
|
||||
// Deal with authors.
|
||||
|
@ -193,6 +202,7 @@ QList<Message> ParsingFactory::parseAsRSS20(const QString &data) {
|
|||
// Deal with titles & descriptions.
|
||||
QString elem_title = message_item.namedItem("title").toElement().text().simplified();
|
||||
QString elem_description = message_item.namedItem("description").toElement().text();
|
||||
QString elem_enclosure = message_item.namedItem("enclosure").toElement().attribute("url");
|
||||
|
||||
if (elem_description.isEmpty()) {
|
||||
elem_description = message_item.namedItem("encoded").toElement().text();
|
||||
|
@ -216,6 +226,12 @@ QList<Message> ParsingFactory::parseAsRSS20(const QString &data) {
|
|||
new_message.m_contents = elem_description;
|
||||
}
|
||||
|
||||
if (!elem_enclosure.isEmpty()) {
|
||||
new_message.m_enclosures.append(elem_enclosure);
|
||||
|
||||
qDebug("Adding enclosure '%s' for the message.", qPrintable(elem_enclosure));
|
||||
}
|
||||
|
||||
// Deal with link and author.
|
||||
new_message.m_url = message_item.namedItem("link").toElement().text();
|
||||
new_message.m_author = message_item.namedItem("author").toElement().text();
|
||||
|
|
|
@ -41,7 +41,7 @@ FormBackupDatabaseSettings::FormBackupDatabaseSettings(QWidget *parent) : QDialo
|
|||
connect(m_ui->m_txtBackupName->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(checkOkButton()));
|
||||
connect(m_ui->m_btnSelectFolder, SIGNAL(clicked()), this, SLOT(selectFolder()));
|
||||
|
||||
selectFolder(qApp->documentsFolderPath());
|
||||
selectFolder(qApp->documentsFolderPath());
|
||||
m_ui->m_txtBackupName->lineEdit()->setText(QString(APP_LOW_NAME) + "_" + QDateTime::currentDateTime().toString("yyyyMMddHHmm"));
|
||||
m_ui->m_lblResult->setStatus(WidgetWithStatus::Warning, tr("No operation executed yet."), tr("No operation executed yet."));
|
||||
|
||||
|
@ -56,19 +56,15 @@ FormBackupDatabaseSettings::~FormBackupDatabaseSettings() {
|
|||
}
|
||||
|
||||
void FormBackupDatabaseSettings::performBackup() {
|
||||
if (qApp->backupDatabaseSettings(m_ui->m_checkBackupDatabase->isChecked(),
|
||||
m_ui->m_checkBackupSettings->isChecked(),
|
||||
m_ui->m_lblSelectFolder->label()->text(),
|
||||
m_ui->m_txtBackupName->lineEdit()->text())) {
|
||||
try {
|
||||
qApp->backupDatabaseSettings(m_ui->m_checkBackupDatabase->isChecked(), m_ui->m_checkBackupSettings->isChecked(),
|
||||
m_ui->m_lblSelectFolder->label()->text(), m_ui->m_txtBackupName->lineEdit()->text());
|
||||
m_ui->m_lblResult->setStatus(WidgetWithStatus::Ok,
|
||||
tr("Backup was created successfully and stored in target folder."),
|
||||
tr("Backup was created successfully."));
|
||||
}
|
||||
else {
|
||||
m_ui->m_lblResult->setStatus(WidgetWithStatus::Error,
|
||||
tr("Backup failed, database and/or settings is probably not backed."),
|
||||
tr("Backup failed. Check the output folder if your database\nand/or "
|
||||
"settings were backed or not. Also make sure that target foder is writable."));
|
||||
catch (ApplicationException &ex) {
|
||||
m_ui->m_lblResult->setStatus(WidgetWithStatus::Error, ex.message(), tr("Backup failed."));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<item>
|
||||
<widget class="QGroupBox" name="m_groupFile">
|
||||
<property name="title">
|
||||
<string/>
|
||||
<string>Output folder</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
|
@ -125,18 +125,18 @@
|
|||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>LabelWithStatus</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>labelwithstatus.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<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>
|
||||
|
|
|
@ -50,20 +50,21 @@ FormRestoreDatabaseSettings::~FormRestoreDatabaseSettings() {
|
|||
void FormRestoreDatabaseSettings::performRestoration() {
|
||||
m_ui->m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
|
||||
|
||||
if (qApp->restoreDatabaseSettings(m_ui->m_groupDatabase->isChecked(),
|
||||
m_ui->m_groupSettings->isChecked(),
|
||||
m_ui->m_listDatabase->currentRow() >= 0 ?
|
||||
try {
|
||||
qApp->restoreDatabaseSettings(m_ui->m_groupDatabase->isChecked(),
|
||||
m_ui->m_groupSettings->isChecked(),
|
||||
m_ui->m_listDatabase->currentRow() >= 0 ?
|
||||
m_ui->m_listDatabase->currentItem()->data(Qt::UserRole).toString() :
|
||||
QString(),
|
||||
m_ui->m_listSettings->currentRow() >= 0 ?
|
||||
m_ui->m_listSettings->currentRow() >= 0 ?
|
||||
m_ui->m_listSettings->currentItem()->data(Qt::UserRole).toString() :
|
||||
QString())) {
|
||||
QString());
|
||||
m_btnRestart->setEnabled(true);
|
||||
m_ui->m_lblResult->setStatus(WidgetWithStatus::Ok, tr("Restoration was initiated. Restart to proceed."),
|
||||
tr("You need to restart application for restoration process to finish."));
|
||||
}
|
||||
else {
|
||||
m_ui->m_lblResult->setStatus(WidgetWithStatus::Error, tr("Restoration was not initiated successfully."),
|
||||
catch (ApplicationException &ex) {
|
||||
m_ui->m_lblResult->setStatus(WidgetWithStatus::Error, ex.message(),
|
||||
tr("Database and/or settings were not copied to restoration folder successully."));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="m_groupFile">
|
||||
<property name="title">
|
||||
<string/>
|
||||
<string>Source folder</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
|
|
|
@ -44,8 +44,7 @@ WidgetWithStatus::WidgetWithStatus(QWidget *parent)
|
|||
WidgetWithStatus::~WidgetWithStatus() {
|
||||
}
|
||||
|
||||
void WidgetWithStatus::setStatus(WidgetWithStatus::StatusType status,
|
||||
const QString &tooltip_text) {
|
||||
void WidgetWithStatus::setStatus(WidgetWithStatus::StatusType status, const QString &tooltip_text) {
|
||||
m_status = status;
|
||||
|
||||
switch (status) {
|
||||
|
|
|
@ -72,18 +72,18 @@ DownloadManager *Application::downloadManager() {
|
|||
return m_downloadManager;
|
||||
}
|
||||
|
||||
bool Application::backupDatabaseSettings(bool backup_database, bool backup_settings,
|
||||
void Application::backupDatabaseSettings(bool backup_database, bool backup_settings,
|
||||
const QString &target_path, const QString &backup_name) {
|
||||
if (!QFileInfo(target_path).isWritable()) {
|
||||
return false;
|
||||
throw ApplicationException(tr("Output folder is not writable."));
|
||||
}
|
||||
|
||||
bool final_result = true;
|
||||
|
||||
if (backup_settings) {
|
||||
settings()->sync();
|
||||
final_result = final_result && IOFactory::copyFile(settings()->fileName(),
|
||||
target_path + QDir::separator() + backup_name + BACKUP_SUFFIX_SETTINGS);
|
||||
|
||||
if (!IOFactory::copyFile(settings()->fileName(), target_path + QDir::separator() + backup_name + BACKUP_SUFFIX_SETTINGS)) {
|
||||
throw ApplicationException(tr("Settings file not copied to output folder successfully."));
|
||||
}
|
||||
}
|
||||
|
||||
if (backup_database &&
|
||||
|
@ -91,26 +91,26 @@ bool Application::backupDatabaseSettings(bool backup_database, bool backup_setti
|
|||
database()->activeDatabaseDriver() == DatabaseFactory::SQLITE_MEMORY)) {
|
||||
// We need to save the database first.
|
||||
database()->saveDatabase();
|
||||
final_result = final_result && IOFactory::copyFile(database()->sqliteDatabaseFilePath(),
|
||||
target_path + QDir::separator() + backup_name + BACKUP_SUFFIX_DATABASE);
|
||||
}
|
||||
|
||||
return final_result;
|
||||
if (!IOFactory::copyFile(database()->sqliteDatabaseFilePath(), target_path + QDir::separator() + backup_name + BACKUP_SUFFIX_DATABASE)) {
|
||||
throw ApplicationException(tr("Database file not copied to output folder successfully."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Application::restoreDatabaseSettings(bool restore_database, bool restore_settings,
|
||||
void Application::restoreDatabaseSettings(bool restore_database, bool restore_settings,
|
||||
const QString &source_database_file_path, const QString &source_settings_file_path) {
|
||||
bool result = true;
|
||||
|
||||
if (restore_database) {
|
||||
result &= qApp->database()->initiateRestoration(source_database_file_path);
|
||||
if (!qApp->database()->initiateRestoration(source_database_file_path)) {
|
||||
throw ApplicationException(tr("Database restoration was not initiated. Make sure that output folder is writable."));
|
||||
}
|
||||
}
|
||||
|
||||
if (restore_settings) {
|
||||
result &= qApp->settings()->initiateRestoration(source_settings_file_path);
|
||||
if (!qApp->settings()->initiateRestoration(source_settings_file_path)) {
|
||||
throw ApplicationException(tr("Settings restoration was not initiated. Make sure that output folder is writable."));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Application::processExecutionMessage(const QString &message) {
|
||||
|
@ -243,3 +243,13 @@ void Application::restart() {
|
|||
m_shouldRestart = true;
|
||||
quit();
|
||||
}
|
||||
|
||||
ApplicationException::ApplicationException(const QString &message) : m_message(message) {
|
||||
}
|
||||
|
||||
ApplicationException::~ApplicationException() {
|
||||
}
|
||||
|
||||
QString ApplicationException::message() const {
|
||||
return m_message;
|
||||
}
|
||||
|
|
|
@ -45,6 +45,17 @@ class FormMain;
|
|||
class IconFactory;
|
||||
class QAction;
|
||||
|
||||
class ApplicationException {
|
||||
public:
|
||||
explicit ApplicationException(const QString &message = QString());
|
||||
virtual ~ApplicationException();
|
||||
|
||||
QString message() const;
|
||||
|
||||
private:
|
||||
QString m_message;
|
||||
};
|
||||
|
||||
class Application : public QtSingleApplication {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -127,8 +138,8 @@ class Application : public QtSingleApplication {
|
|||
return IOFactory::getSystemFolder(SYSTEM_FOLDER_ENUM::HomeLocation);
|
||||
}
|
||||
|
||||
bool backupDatabaseSettings(bool backup_database, bool backup_settings, const QString &target_path, const QString &backup_name);
|
||||
bool restoreDatabaseSettings(bool restore_database, bool restore_settings,
|
||||
void backupDatabaseSettings(bool backup_database, bool backup_settings, const QString &target_path, const QString &backup_name);
|
||||
void restoreDatabaseSettings(bool restore_database, bool restore_settings,
|
||||
const QString &source_database_file_path = QString(),
|
||||
const QString &source_settings_file_path = QString());
|
||||
|
||||
|
|
|
@ -218,6 +218,10 @@ void WebBrowser::navigateToMessages(const QList<Message> &messages) {
|
|||
QString single_message_layout = factory->currentMarkup();
|
||||
|
||||
foreach (const Message &message, messages) {
|
||||
QString enclosures = message.m_enclosures.join("</br>");
|
||||
|
||||
// TODO: upravit skiny aby brali další argument
|
||||
|
||||
messages_layout.append(single_message_layout.arg(message.m_title,
|
||||
tr("Written by ") + (message.m_author.isEmpty() ?
|
||||
tr("uknown author") :
|
||||
|
|
Loading…
Add table
Reference in a new issue