More complete downloader.

This commit is contained in:
Martin Rotter 2015-02-01 16:36:07 +01:00
parent e0db0c3ed9
commit 1663f2a9c0
10 changed files with 96 additions and 109 deletions

View file

@ -10,7 +10,12 @@ Fixed:
Added: Added:
<ul> <ul>
<li></li> <li>Completely new downloader (see menu Tools -> Downloads) forked from original Qt examples.</li>
</ul>
Changed:
<ul>
<li>Updater now displays full changelog.</li>
</ul> </ul>
<hr/> <hr/>

View file

@ -2,19 +2,5 @@
<releases> <releases>
<release version="2.1.0" type="feature"> <release version="2.1.0" type="feature">
<url platform="x86" os="Windows">https://bitbucket.org/skunkos/rssguard/downloads/rssguard-2.1.0-win32.exe</url> <url platform="x86" os="Windows">https://bitbucket.org/skunkos/rssguard/downloads/rssguard-2.1.0-win32.exe</url>
<changes>
<![CDATA[<body>
Fixed:
<ul>
<li>Fixed bug #105, #103.</li>
</ul>
Added:
<ul>
<li>Embedded web browser supports printing of its contents, feature is accessible via web browser context menu.</li>
<li>Embedded web browser now displays navigation toolbar even in message preview mode/newspaper mode when user loads external links.</li>
</ul>
</body>]]>
</changes>
</release> </release>
</releases> </releases>

View file

@ -41,6 +41,7 @@
#define URI_SCHEME_FEED "feed://" #define URI_SCHEME_FEED "feed://"
#define URI_SCHEME_HTTP "http://" #define URI_SCHEME_HTTP "http://"
#define RELEASES_LIST "https://bitbucket.org/skunkos/rssguard/raw/master/resources/text/UPDATES?at=master" #define RELEASES_LIST "https://bitbucket.org/skunkos/rssguard/raw/master/resources/text/UPDATES?at=master"
#define CHANGELOG "https://bitbucket.org/skunkos/rssguard/raw/master/resources/text/CHANGELOG?at=master"
#define DEFAULT_LOCALE "en_GB" #define DEFAULT_LOCALE "en_GB"
#define DEFAULT_FEED_ENCODING "UTF-8" #define DEFAULT_FEED_ENCODING "UTF-8"
#define DEFAULT_FEED_TYPE "RSS" #define DEFAULT_FEED_TYPE "RSS"

View file

@ -15,55 +15,54 @@
// 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 "edittableview.h" #include "gui/edittableview.h"
#include <qevent.h> #include <QKeyEvent>
EditTableView::EditTableView(QWidget *parent)
: QTableView(parent) EditTableView::EditTableView(QWidget *parent) : QTableView(parent) {
{
} }
void EditTableView::keyPressEvent(QKeyEvent *event) void EditTableView::keyPressEvent(QKeyEvent *event) {
{
if (model() && event->key() == Qt::Key_Delete) { if (model() && event->key() == Qt::Key_Delete) {
removeSelected(); removeSelected();
event->setAccepted(true); event->accept();
} else { }
else {
QAbstractItemView::keyPressEvent(event); QAbstractItemView::keyPressEvent(event);
} }
} }
void EditTableView::removeSelected() void EditTableView::removeSelected() {
{ if (!model() || !selectionModel() || !selectionModel()->hasSelection()) {
if (!model() || !selectionModel() || !selectionModel()->hasSelection())
return; return;
}
QModelIndexList selectedRows = selectionModel()->selectedRows(); QModelIndexList selectedRows = selectionModel()->selectedRows();
if (selectedRows.isEmpty())
if (selectedRows.isEmpty()) {
return; return;
}
int newSelectedRow = selectedRows.at(0).row(); int newSelectedRow = selectedRows.at(0).row();
for (int i = selectedRows.count() - 1; i >= 0; --i) {
for (int i = selectedRows.count() - 1; i >= 0; i--) {
QModelIndex idx = selectedRows.at(i); QModelIndex idx = selectedRows.at(i);
model()->removeRow(idx.row(), rootIndex()); model()->removeRow(idx.row(), rootIndex());
} }
// select the item at the same position
QModelIndex newSelectedIndex = model()->index(newSelectedRow, 0, rootIndex()); QModelIndex newSelectedIndex = model()->index(newSelectedRow, 0, rootIndex());
// if that was the last item
if (!newSelectedIndex.isValid()) if (!newSelectedIndex.isValid()) {
newSelectedIndex = model()->index(newSelectedRow - 1, 0, rootIndex()); newSelectedIndex = model()->index(newSelectedRow - 1, 0, rootIndex());
}
selectionModel()->select(newSelectedIndex, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); selectionModel()->select(newSelectedIndex, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
setCurrentIndex(newSelectedIndex); setCurrentIndex(newSelectedIndex);
} }
void EditTableView::removeAll() void EditTableView::removeAll() {
{ if (model() != NULL) {
if (!model()) model()->removeRows(0, model()->rowCount(rootIndex()), rootIndex());
return; }
model()->removeRows(0, model()->rowCount(rootIndex()), rootIndex());
} }

View file

@ -18,20 +18,20 @@
#ifndef EDITTABLEVIEW_H #ifndef EDITTABLEVIEW_H
#define EDITTABLEVIEW_H #define EDITTABLEVIEW_H
#include <qtableview.h> #include <QTableView>
class EditTableView : public QTableView
{ class EditTableView : public QTableView {
Q_OBJECT Q_OBJECT
public: public:
EditTableView(QWidget *parent = 0); explicit EditTableView(QWidget *parent = 0);
void keyPressEvent(QKeyEvent *event); void keyPressEvent(QKeyEvent *event);
public slots: public slots:
void removeSelected(); void removeSelected();
void removeAll(); void removeAll();
}; };
#endif // EDITTABLEVIEW_H #endif // EDITTABLEVIEW_H

View file

@ -15,60 +15,59 @@
// 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 "autosaver.h" #include "miscellaneous/autosaver.h"
#include <qdir.h> #include <QDir>
#include <qcoreapplication.h> #include <QCoreApplication>
#include <qmetaobject.h> #include <QMetaObject>
#include <qdebug.h>
#define AUTOSAVE_IN 1000 * 3 // seconds #define AUTOSAVE_IN 1000 * 3 // seconds
#define MAXWAIT 1000 * 15 // seconds #define MAXWAIT 1000 * 15 // seconds
AutoSaver::AutoSaver(QObject *parent) : QObject(parent)
{ AutoSaver::AutoSaver(QObject *parent) : QObject(parent) {
Q_ASSERT(parent); Q_ASSERT(parent);
} }
AutoSaver::~AutoSaver() AutoSaver::~AutoSaver() {
{ if (m_timer.isActive()) {
if (m_timer.isActive()) { qWarning("AutoSaver: still active when destroyed, changes not saved.");
qWarning() << "AutoSaver: still active when destroyed, changes not saved.";
if (parent() && parent()->metaObject()) if (parent() && parent()->metaObject()) {
qWarning() << parent() << parent()->metaObject()->className() << "should call saveIfNeccessary"; qWarning("Should call saveIfNeccessary.");
} }
}
} }
void AutoSaver::changeOccurred() void AutoSaver::changeOccurred() {
{ if (m_firstChange.isNull()) {
if (m_firstChange.isNull()) m_firstChange.start();
m_firstChange.start(); }
if (m_firstChange.elapsed() > MAXWAIT) { if (m_firstChange.elapsed() > MAXWAIT) {
saveIfNeccessary(); saveIfNeccessary();
} else { }
m_timer.start(AUTOSAVE_IN, this); else {
} m_timer.start(AUTOSAVE_IN, this);
}
} }
void AutoSaver::timerEvent(QTimerEvent *event) void AutoSaver::timerEvent(QTimerEvent *event) {
{ if (event->timerId() == m_timer.timerId()) {
if (event->timerId() == m_timer.timerId()) { saveIfNeccessary();
saveIfNeccessary(); }
} else { else {
QObject::timerEvent(event); QObject::timerEvent(event);
} }
} }
void AutoSaver::saveIfNeccessary() void AutoSaver::saveIfNeccessary() {
{ if (m_timer.isActive()) {
if (!m_timer.isActive())
return;
m_timer.stop(); m_timer.stop();
m_firstChange = QTime(); m_firstChange = QTime();
if (!QMetaObject::invokeMethod(parent(), "save", Qt::DirectConnection)) {
qWarning() << "AutoSaver: error invoking slot save() on parent";
}
}
if (!QMetaObject::invokeMethod(parent(), "save", Qt::DirectConnection)) {
qWarning("AutoSaver: error invoking slot save() on parent.");
}
}
}

View file

@ -18,36 +18,30 @@
#ifndef AUTOSAVER_H #ifndef AUTOSAVER_H
#define AUTOSAVER_H #define AUTOSAVER_H
#include <qobject.h> #include <QObject>
#include <qbasictimer.h> #include <QBasicTimer>
#include <qdatetime.h> #include <QDateTime>
/*
This class will call the save() slot on the parent object when the parent changes. class AutoSaver : public QObject{
It will wait several seconds after changed() to combining multiple changes and
prevent continuous writing to disk.
*/
class AutoSaver : public QObject
{
Q_OBJECT Q_OBJECT
public: public:
AutoSaver(QObject *parent); explicit AutoSaver(QObject *parent);
~AutoSaver(); virtual ~AutoSaver();
void saveIfNeccessary(); void saveIfNeccessary();
public slots: public slots:
void changeOccurred(); void changeOccurred();
protected: protected:
void timerEvent(QTimerEvent *event); void timerEvent(QTimerEvent *event);
private: private:
QBasicTimer m_timer; QBasicTimer m_timer;
QTime m_firstChange; QTime m_firstChange;
}; };
#endif // AUTOSAVER_H #endif // AUTOSAVER_H

View file

@ -173,11 +173,13 @@ bool SystemFactory::removeTrolltechJunkRegistryKeys() {
QPair<UpdateInfo, QNetworkReply::NetworkError> SystemFactory::checkForUpdates() { QPair<UpdateInfo, QNetworkReply::NetworkError> SystemFactory::checkForUpdates() {
QPair<UpdateInfo, QNetworkReply::NetworkError> result; QPair<UpdateInfo, QNetworkReply::NetworkError> result;
QByteArray releases_xml; QByteArray releases_xml;
QByteArray changelog;
result.second = NetworkFactory::downloadFile(RELEASES_LIST, DOWNLOAD_TIMEOUT, releases_xml).first; result.second = NetworkFactory::downloadFile(RELEASES_LIST, DOWNLOAD_TIMEOUT, releases_xml).first;
NetworkFactory::downloadFile(CHANGELOG, DOWNLOAD_TIMEOUT, changelog).first;
if (result.second == QNetworkReply::NoError) { if (result.second == QNetworkReply::NoError) {
result.first = parseUpdatesFile(releases_xml); result.first = parseUpdatesFile(releases_xml, changelog);
} }
return result; return result;
@ -215,7 +217,7 @@ bool SystemFactory::isUpdateNewer(const QString &update_version) {
} }
} }
UpdateInfo SystemFactory::parseUpdatesFile(const QByteArray &updates_file) { UpdateInfo SystemFactory::parseUpdatesFile(const QByteArray &updates_file, const QByteArray &changelog) {
UpdateInfo update; UpdateInfo update;
QDomDocument document; document.setContent(updates_file, false); QDomDocument document; document.setContent(updates_file, false);
QDomNodeList releases = document.elementsByTagName("release"); QDomNodeList releases = document.elementsByTagName("release");
@ -225,7 +227,7 @@ UpdateInfo SystemFactory::parseUpdatesFile(const QByteArray &updates_file) {
QString type = rel_elem.attributes().namedItem("type").toAttr().value(); QString type = rel_elem.attributes().namedItem("type").toAttr().value();
update.m_availableVersion = rel_elem.attributes().namedItem("version").toAttr().value(); update.m_availableVersion = rel_elem.attributes().namedItem("version").toAttr().value();
update.m_changes = rel_elem.namedItem("changes").toElement().text(); update.m_changes = changelog;
QDomNodeList urls = rel_elem.elementsByTagName("url"); QDomNodeList urls = rel_elem.elementsByTagName("url");

View file

@ -106,7 +106,7 @@ class SystemFactory : public QObject {
private: private:
// Performs parsing of downloaded file with list of updates. // Performs parsing of downloaded file with list of updates.
UpdateInfo parseUpdatesFile(const QByteArray &updates_file); UpdateInfo parseUpdatesFile(const QByteArray &updates_file, const QByteArray &changelog);
}; };
#endif // SYSTEMFACTORY_H #endif // SYSTEMFACTORY_H

View file

@ -643,14 +643,15 @@ void DownloadManager::load() {
void DownloadManager::cleanup() { void DownloadManager::cleanup() {
if (!m_downloads.isEmpty()) { if (!m_downloads.isEmpty()) {
m_model->removeRows(0, m_downloads.count()); m_model->removeRows(0, m_downloads.count());
m_ui->m_btnCleanup->setEnabled(false);
} }
} }
void DownloadManager::setDownloadDirectory(const QString &directory) { void DownloadManager::setDownloadDirectory(const QString &directory) {
m_downloadDirectory = directory; m_downloadDirectory = directory;
if (!m_downloadDirectory.isEmpty() && !m_downloadDirectory.endsWith('/')) { if (!m_downloadDirectory.isEmpty() && !m_downloadDirectory.endsWith(QLatin1Char('/'))) {
m_downloadDirectory += '/'; m_downloadDirectory += QLatin1Char('/');
} }
} }