Introduced application-wide close lock.

This commit is contained in:
Martin Rotter 2013-12-22 18:47:00 +01:00
parent 175e657af7
commit 80e8fcd0f6
9 changed files with 73 additions and 7 deletions

View file

@ -1,6 +1,11 @@
<body> <body>
[2.0.0] [2.0.0]
<ul> <ul>
<li>Initial second generation release.</li> <li>[@] Initial second generation release.</li>
</ul> </ul>
[+] added <br/>
[#] fixed <br/>
[~] changed <br/>
[@] other action <br/>
</body> </body>

View file

@ -29,6 +29,7 @@
#define NO_PARENT_CATEGORY -1 #define NO_PARENT_CATEGORY -1
#define TRAY_ICON_BUBBLE_TIMEOUT 15000 #define TRAY_ICON_BUBBLE_TIMEOUT 15000
#define KEY_MESSAGES_VIEW "messages_view_column_" #define KEY_MESSAGES_VIEW "messages_view_column_"
#define CLOSE_LOCK_TIMEOUT 2000
#define APP_DB_INIT_FILE "db_init.sql" #define APP_DB_INIT_FILE "db_init.sql"
#define APP_DB_INIT_SPLIT "-- !\n" #define APP_DB_INIT_SPLIT "-- !\n"

View file

@ -56,15 +56,15 @@ void MessagesModel::setupFonts() {
} }
QList<int> MessagesModel::currentFeeds() const { QList<int> MessagesModel::currentFeeds() const {
return m_currentFeeds; return m_currentFeeds;
} }
void MessagesModel::loadMessages(const QList<int> feed_ids) { void MessagesModel::loadMessages(const QList<int> feed_ids) {
// Conversion of parameter. // Conversion of parameter.
m_currentFeeds = feed_ids; m_currentFeeds = feed_ids;
setFilter(QString("feed IN (%1) AND deleted = 0").arg(textualFeeds().join(", "))); setFilter(QString("feed IN (%1) AND deleted = 0").arg(textualFeeds().join(", ")));
select(); select();
fetchAll(); fetchAll();
} }
@ -428,7 +428,7 @@ bool MessagesModel::setAllMessagesDeleted(int deleted) {
QSqlQuery query_delete_msg(db_handle); QSqlQuery query_delete_msg(db_handle);
if (!query_delete_msg.prepare(QString("UPDATE messages SET deleted = :deleted " if (!query_delete_msg.prepare(QString("UPDATE messages SET deleted = :deleted "
"WHERE feed IN (%1) AND deleted = 0").arg(textualFeeds().join(", ")))) { "WHERE feed IN (%1) AND deleted = 0").arg(textualFeeds().join(", ")))) {
qWarning("Query preparation failed for message deletion."); qWarning("Query preparation failed for message deletion.");
db_handle.rollback(); db_handle.rollback();

View file

@ -17,10 +17,13 @@
QPointer<SystemFactory> SystemFactory::s_instance; QPointer<SystemFactory> SystemFactory::s_instance;
SystemFactory::SystemFactory(QObject *parent) : QObject(parent) { SystemFactory::SystemFactory(QObject *parent) : QObject(parent) {
m_applicationCloseLock = new QReadWriteLock(QReadWriteLock::NonRecursive);
} }
SystemFactory::~SystemFactory() { SystemFactory::~SystemFactory() {
qDebug("Destroying SystemFactory instance."); qDebug("Destroying SystemFactory instance.");
delete m_applicationCloseLock;
} }
@ -99,6 +102,10 @@ SystemFactory *SystemFactory::getInstance() {
return s_instance; return s_instance;
} }
QReadWriteLock *SystemFactory::applicationCloseLock() const {
return m_applicationCloseLock;
}
bool SystemFactory::setAutoStartStatus(const AutoStartStatus &new_status) { bool SystemFactory::setAutoStartStatus(const AutoStartStatus &new_status) {
SystemFactory::AutoStartStatus current_status = SystemFactory::getAutoStartStatus(); SystemFactory::AutoStartStatus current_status = SystemFactory::getAutoStartStatus();

View file

@ -6,14 +6,17 @@
class QReadWriteLock; class QReadWriteLock;
class QMutex;
class SystemFactory : public QObject { class SystemFactory : public QObject {
Q_OBJECT Q_OBJECT
private: private:
// Constructors and destructors.
explicit SystemFactory(QObject *parent = 0); explicit SystemFactory(QObject *parent = 0);
public: public:
// Constructors and destructors.
virtual ~SystemFactory(); virtual ~SystemFactory();
// Specifies possible states of auto-start functionality. // Specifies possible states of auto-start functionality.
@ -40,7 +43,24 @@ class SystemFactory : public QObject {
// Singleton getter. // Singleton getter.
static SystemFactory *getInstance(); static SystemFactory *getInstance();
// Access to application-wide close lock.
QReadWriteLock *applicationCloseLock() const;
private: private:
// This read-write lock is used by application on its close.
// Application locks this lock for WRITTING.
// This means that if application locks that lock, then
// no other transaction-critical action can acquire lock
// for reading and won't be executed, so no critical action
// will be running when application quits
//
// EACH critical action locks this lock for READING.
// Several actions can lock this lock for reading.
// But of user decides to close the application (in other words,
// tries to lock the lock for writting), then no other
// action will be allowed to lock for reading.
QReadWriteLock *m_applicationCloseLock;
static QPointer<SystemFactory> s_instance; static QPointer<SystemFactory> s_instance;
}; };

View file

@ -18,6 +18,7 @@ class FeedsView : public QTreeView {
void setSortingEnabled(bool enable); void setSortingEnabled(bool enable);
// Returns list of selected feeds.
QList<FeedsModelFeed*> selectedFeeds() const; QList<FeedsModelFeed*> selectedFeeds() const;
public slots: public slots:
@ -25,7 +26,10 @@ class FeedsView : public QTreeView {
void updateCountsOfSelectedFeeds(); void updateCountsOfSelectedFeeds();
protected: protected:
// Sets up appearance of this widget.
void setupAppearance(); void setupAppearance();
void selectionChanged(const QItemSelection &selected, void selectionChanged(const QItemSelection &selected,
const QItemSelection &deselected); const QItemSelection &deselected);

View file

@ -2,6 +2,7 @@
#include "core/defs.h" #include "core/defs.h"
#include "core/settings.h" #include "core/settings.h"
#include "core/systemfactory.h"
#include "gui/formabout.h" #include "gui/formabout.h"
#include "gui/formsettings.h" #include "gui/formsettings.h"
#include "gui/webbrowser.h" #include "gui/webbrowser.h"
@ -17,6 +18,7 @@
#include <QSessionManager> #include <QSessionManager>
#include <QRect> #include <QRect>
#include <QDesktopWidget> #include <QDesktopWidget>
#include <QReadWriteLock>
FormMain *FormMain::s_instance; FormMain *FormMain::s_instance;
@ -129,6 +131,20 @@ void FormMain::processExecutionMessage(const QString &message) {
void FormMain::quit() { void FormMain::quit() {
qDebug("Quitting the application."); qDebug("Quitting the application.");
// Make sure that we obtain close lock
// BEFORE even trying to quit the application.
if (SystemFactory::getInstance()->applicationCloseLock()->tryLockForWrite(CLOSE_LOCK_TIMEOUT)) {
// Application obtained permission to close
// in a safety way.
qDebug("Close lock obtained safely.");
}
else {
// Request for write lock timed-out. This means
// that some critical action can be processed right now.
qDebug("Close lock timed-out.");
}
qApp->quit(); qApp->quit();
} }
@ -178,6 +194,7 @@ void FormMain::onSaveState(QSessionManager &manager) {
void FormMain::onAboutToQuit() { void FormMain::onAboutToQuit() {
qDebug("Cleaning up resources and saving application state."); qDebug("Cleaning up resources and saving application state.");
saveSize(); saveSize();
} }

View file

@ -103,6 +103,11 @@ void MessagesView::setupAppearance() {
setSortingEnabled(true); setSortingEnabled(true);
setAllColumnsShowFocus(true); setAllColumnsShowFocus(true);
setSelectionMode(QAbstractItemView::ExtendedSelection); setSelectionMode(QAbstractItemView::ExtendedSelection);
// Make sure that initial sorting is that unread messages are visible
// first.
// NOTE: This can be rewritten so that it's changeable.
sortByColumn(MSG_DB_READ_INDEX, Qt::AscendingOrder);
} }
void MessagesView::keyPressEvent(QKeyEvent *event) { void MessagesView::keyPressEvent(QKeyEvent *event) {
@ -198,7 +203,13 @@ void MessagesView::currentChanged(const QModelIndex &current,
} }
void MessagesView::loadFeeds(const QList<int> &feed_ids) { void MessagesView::loadFeeds(const QList<int> &feed_ids) {
// Load messages.
// TODO: Here we could load user-defined default sorting
// column/order AND possibly hide/show user-defined columns.
m_sourceModel->loadMessages(feed_ids); m_sourceModel->loadMessages(feed_ids);
// Messages are loaded, make sure that previously
// active message is not shown in browser.
emit currentMessageRemoved(); emit currentMessageRemoved();
} }

View file

@ -23,6 +23,7 @@ class MessagesView : public QTreeView {
MessagesModel *sourceModel(); MessagesModel *sourceModel();
public slots: public slots:
// Loads un-deleted messages from selected feeds.
void loadFeeds(const QList<int> &feed_ids); void loadFeeds(const QList<int> &feed_ids);
// Message manipulators. // Message manipulators.