This commit is contained in:
Martin Rotter 2014-01-10 08:36:08 +01:00
parent 6cff2dcd0b
commit a3e189671c
16 changed files with 76 additions and 44 deletions

View File

@ -120,11 +120,11 @@
</message> </message>
<message> <message>
<source>Title</source> <source>Title</source>
<translation type="unfinished">Nadpis</translation> <translation>Název</translation>
</message> </message>
<message> <message>
<source>Title of the category</source> <source>Title of the category</source>
<translation type="unfinished"></translation> <translation>Název kategorie</translation>
</message> </message>
<message> <message>
<source>Description</source> <source>Description</source>
@ -359,11 +359,11 @@
</message> </message>
<message> <message>
<source>Update &amp;all items</source> <source>Update &amp;all items</source>
<translation type="unfinished"></translation> <translation>Aktualizov&amp;at všechny položky</translation>
</message> </message>
<message> <message>
<source>Update &amp;selected items</source> <source>Update &amp;selected items</source>
<translation type="unfinished"></translation> <translation>Aktualizovat v&amp;ybrané položky</translation>
</message> </message>
<message> <message>
<source>&amp;Delete selected feeds/categories</source> <source>&amp;Delete selected feeds/categories</source>
@ -371,31 +371,31 @@
</message> </message>
<message> <message>
<source>Mark &amp;selected items read</source> <source>Mark &amp;selected items read</source>
<translation type="unfinished"></translation> <translation>Označit vybrané položky jako přečte&amp;</translation>
</message> </message>
<message> <message>
<source>Mark selected items unread</source> <source>Mark selected items unread</source>
<translation type="unfinished"></translation> <translation>Označit vybrané položky jako nepřečtené</translation>
</message> </message>
<message> <message>
<source>Clear selected items</source> <source>Clear selected items</source>
<translation type="unfinished"></translation> <translation>Vyprázdnit vybrané položky</translation>
</message> </message>
<message> <message>
<source>Mark all &amp;items read</source> <source>Mark all &amp;items read</source>
<translation type="unfinished"></translation> <translation>Označ&amp;it všechny položky jako přečtené</translation>
</message> </message>
<message> <message>
<source>Mark all messages in all feeds read. This does not take message filters into account.</source> <source>Mark all messages in all feeds read. This does not take message filters into account.</source>
<translation type="unfinished"></translation> <translation>Označí všechny zprávy ve všech kanálech jako přečtené. Toto nebere v potaz filtry zpráv.</translation>
</message> </message>
<message> <message>
<source>View selected items in newspaper mode</source> <source>View selected items in newspaper mode</source>
<translation type="unfinished"></translation> <translation>Zobrazit vybrané položky v novinovém náhledu</translation>
</message> </message>
<message> <message>
<source>Displays all messages from selected feeds/categories in a new &quot;newspaper mode&quot; tab. All selected feeds are marked as read.</source> <source>Displays all messages from selected feeds/categories in a new &quot;newspaper mode&quot; tab. All selected feeds are marked as read.</source>
<translation type="unfinished"></translation> <translation>Zobrazí všechny zprávy z vybraných kanálů v novinovém náhledu v novém panelu.</translation>
</message> </message>
</context> </context>
<context> <context>
@ -874,11 +874,11 @@
</message> </message>
<message> <message>
<source>Meesage without URL</source> <source>Meesage without URL</source>
<translation type="unfinished"></translation> <translation>Zpráva bez URL</translation>
</message> </message>
<message> <message>
<source>Message &apos;%s&apos; does not contain URL.</source> <source>Message &apos;%s&apos; does not contain URL.</source>
<translation type="unfinished"></translation> <translation>Zpráva &apos;%s&apos; neobsahuje URL.</translation>
</message> </message>
</context> </context>
<context> <context>

View File

@ -51,7 +51,8 @@ QNetworkReply *BaseNetworkAccessManager::createRequest(QNetworkAccessManager::Op
// This rapidly speeds up loading of web sites. // This rapidly speeds up loading of web sites.
// NOTE: https://en.wikipedia.org/wiki/HTTP_pipelining // NOTE: https://en.wikipedia.org/wiki/HTTP_pipelining
new_request.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true); new_request.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute,
true);
// Setup custom user-agent. // Setup custom user-agent.
new_request.setRawHeader(USER_AGENT_HTTP_HEADER, new_request.setRawHeader(USER_AGENT_HTTP_HEADER,

View File

@ -19,6 +19,7 @@ class BaseNetworkAccessManager : public QNetworkAccessManager {
virtual void loadSettings(); virtual void loadSettings();
protected: protected:
// Creates custom request.
QNetworkReply *createRequest(Operation op, QNetworkReply *createRequest(Operation op,
const QNetworkRequest &request, const QNetworkRequest &request,
QIODevice *outgoingData); QIODevice *outgoingData);

View File

@ -21,7 +21,7 @@ DatabaseFactory::~DatabaseFactory() {
qDebug("Destroying DatabaseFactory object."); qDebug("Destroying DatabaseFactory object.");
} }
DatabaseFactory *DatabaseFactory::getInstance() { DatabaseFactory *DatabaseFactory::instance() {
if (s_instance.isNull()) { if (s_instance.isNull()) {
s_instance = new DatabaseFactory(qApp); s_instance = new DatabaseFactory(qApp);
} }
@ -126,12 +126,14 @@ QSqlDatabase DatabaseFactory::initialize(const QString &connection_name) {
query_db.finish(); query_db.finish();
} }
// Everything is initialized now.
m_initialized = true;
return database; return database;
} }
QSqlDatabase DatabaseFactory::connection(const QString &connection_name) { QSqlDatabase DatabaseFactory::connection(const QString &connection_name) {
if (!m_initialized) { if (!m_initialized) {
m_initialized = true;
return initialize(connection_name); return initialize(connection_name);
} }
else { else {

View File

@ -23,7 +23,7 @@ class DatabaseFactory : public QObject {
void removeConnection(const QString &connection_name); void removeConnection(const QString &connection_name);
// Singleton getter. // Singleton getter.
static DatabaseFactory *getInstance(); static DatabaseFactory *instance();
private: private:
// Conctructor. // Conctructor.

View File

@ -35,9 +35,7 @@
#define DOWNLOAD_TIMEOUT 5000 #define DOWNLOAD_TIMEOUT 5000
#define MESSAGES_VIEW_DEFAULT_COL 170 #define MESSAGES_VIEW_DEFAULT_COL 170
#define ELLIPSIS_LENGTH 3 #define ELLIPSIS_LENGTH 3
#define INTERNAL_URL_SCHEME APP_LOW_NAME
#define INTERNAL_URL_NEWSPAPER "@APP_LOW_NAME@:newspaper" #define INTERNAL_URL_NEWSPAPER "@APP_LOW_NAME@:newspaper"
#define INTERNAL_URL_NEWSPAPER_PATH "newspaper"
#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

@ -18,6 +18,7 @@ void FeedDownloader::updateFeeds(const QList<FeedsModelFeed *> &feeds) {
qDebug().nospace() << "Performing feed updates in thread: \'" << qDebug().nospace() << "Performing feed updates in thread: \'" <<
QThread::currentThreadId() << "\'."; QThread::currentThreadId() << "\'.";
// Job starts now.
emit started(); emit started();
for (int i = 0, total = feeds.size(); i < total; i++) { for (int i = 0, total = feeds.size(); i < total; i++) {

View File

@ -23,7 +23,7 @@ FeedsModel::FeedsModel(QObject *parent) : QAbstractItemModel(parent) {
m_rootItem->setId(NO_PARENT_CATEGORY); m_rootItem->setId(NO_PARENT_CATEGORY);
m_rootItem->setTitle(tr("root")); m_rootItem->setTitle(tr("root"));
m_rootItem->setIcon(IconThemeFactory::getInstance()->fromTheme("folder-red")); m_rootItem->setIcon(IconThemeFactory::getInstance()->fromTheme("folder-red"));
m_countsIcon = IconThemeFactory::getInstance()->fromTheme("mail-mark-unread"); m_countsIcon = IconThemeFactory::getInstance()->fromTheme("mail-mark-important");
m_headerData << tr("Title"); m_headerData << tr("Title");
m_tooltipData << tr("Titles of feeds/categories.") << m_tooltipData << tr("Titles of feeds/categories.") <<
tr("Counts of unread/all meesages."); tr("Counts of unread/all meesages.");
@ -34,8 +34,11 @@ FeedsModel::FeedsModel(QObject *parent) : QAbstractItemModel(parent) {
FeedsModel::~FeedsModel() { FeedsModel::~FeedsModel() {
qDebug("Destroying FeedsModel instance."); qDebug("Destroying FeedsModel instance.");
// Delete all model items.
delete m_rootItem; delete m_rootItem;
DatabaseFactory::getInstance()->removeConnection(objectName());
// Remove connection.
DatabaseFactory::instance()->removeConnection(objectName());
} }
QVariant FeedsModel::data(const QModelIndex &index, int role) const { QVariant FeedsModel::data(const QModelIndex &index, int role) const {
@ -81,6 +84,8 @@ QModelIndex FeedsModel::index(int row, int column, const QModelIndex &parent) co
FeedsModelRootItem *parent_item; FeedsModelRootItem *parent_item;
// TODO: overit zda zde misto internalPointer nepouzit
// metodu itemFornIndex a overit vykonnostni dopady
if (!parent.isValid()) { if (!parent.isValid()) {
parent_item = m_rootItem; parent_item = m_rootItem;
} }
@ -103,6 +108,8 @@ QModelIndex FeedsModel::parent(const QModelIndex &child) const {
return QModelIndex(); return QModelIndex();
} }
// TODO: overit zda zde misto internalPointer nepouzit
// metodu itemFornIndex a overit vykonnostni dopady
FeedsModelRootItem *child_item = static_cast<FeedsModelRootItem*>(child.internalPointer()); FeedsModelRootItem *child_item = static_cast<FeedsModelRootItem*>(child.internalPointer());
FeedsModelRootItem *parent_item = child_item->parent(); FeedsModelRootItem *parent_item = child_item->parent();
@ -121,6 +128,8 @@ int FeedsModel::rowCount(const QModelIndex &parent) const {
return 0; return 0;
} }
// TODO: overit zda zde misto internalPointer nepouzit
// metodu itemFornIndex a overit vykonnostni dopady
if (!parent.isValid()) { if (!parent.isValid()) {
parent_item = m_rootItem; parent_item = m_rootItem;
} }
@ -157,7 +166,9 @@ bool FeedsModel::removeItems(const QModelIndexList &indexes) {
FeedsModelRootItem *parent_item = itemForIndex(parent_index); FeedsModelRootItem *parent_item = itemForIndex(parent_index);
beginRemoveRows(parent_index, index.row(), index.row()); beginRemoveRows(parent_index, index.row(), index.row());
items_for_deletion << parent_item->removeChild(index.row()); if (parent_item->removeChild(index.row())) {
items_for_deletion << item;
}
endRemoveRows(); endRemoveRows();
} }
} }
@ -167,14 +178,13 @@ bool FeedsModel::removeItems(const QModelIndexList &indexes) {
delete items_for_deletion.takeFirst(); delete items_for_deletion.takeFirst();
} }
return true; return true;
} }
QList<Message> FeedsModel::messagesForFeeds(const QList<FeedsModelFeed *> &feeds) { QList<Message> FeedsModel::messagesForFeeds(const QList<FeedsModelFeed*> &feeds) {
QList<Message> messages; QList<Message> messages;
QSqlDatabase database = DatabaseFactory::getInstance()->connection(objectName()); QSqlDatabase database = DatabaseFactory::instance()->connection(objectName());
QSqlQuery query_read_msg(database); QSqlQuery query_read_msg(database);
query_read_msg.setForwardOnly(true); query_read_msg.setForwardOnly(true);
query_read_msg.prepare("SELECT title, url, author, date_created, contents " query_read_msg.prepare("SELECT title, url, author, date_created, contents "
@ -203,6 +213,8 @@ QList<Message> FeedsModel::messagesForFeeds(const QList<FeedsModelFeed *> &feeds
} }
int FeedsModel::columnCount(const QModelIndex &parent) const { int FeedsModel::columnCount(const QModelIndex &parent) const {
// TODO: overit zda zde misto internalPointer nepouzit
// metodu itemFornIndex a overit vykonnostni dopady
if (parent.isValid()) { if (parent.isValid()) {
return static_cast<FeedsModelRootItem*>(parent.internalPointer())->columnCount(); return static_cast<FeedsModelRootItem*>(parent.internalPointer())->columnCount();
} }
@ -314,7 +326,7 @@ void FeedsModel::loadFromDatabase() {
qDeleteAll(m_rootItem->childItems()); qDeleteAll(m_rootItem->childItems());
m_rootItem->clearChilds(); m_rootItem->clearChilds();
QSqlDatabase database = DatabaseFactory::getInstance()->connection(objectName()); QSqlDatabase database = DatabaseFactory::instance()->connection(objectName());
CategoryAssignment categories; CategoryAssignment categories;
FeedAssignment feeds; FeedAssignment feeds;
@ -416,7 +428,8 @@ QList<FeedsModelFeed*> FeedsModel::feedsForIndexes(const QModelIndexList &indexe
// example situation where feed and its parent category are both // example situation where feed and its parent category are both
// selected). So, remove duplicates from the list. // selected). So, remove duplicates from the list.
qSort(feeds.begin(), feeds.end(), FeedsModelRootItem::lessThan); qSort(feeds.begin(), feeds.end(), FeedsModelRootItem::lessThan);
feeds.erase(std::unique(feeds.begin(), feeds.end(), FeedsModelRootItem::isEqual), feeds.erase(std::unique(feeds.begin(),
feeds.end(), FeedsModelRootItem::isEqual),
feeds.end()); feeds.end());
} }
@ -425,7 +438,7 @@ QList<FeedsModelFeed*> FeedsModel::feedsForIndexes(const QModelIndexList &indexe
bool FeedsModel::markFeedsRead(const QList<FeedsModelFeed*> &feeds, bool FeedsModel::markFeedsRead(const QList<FeedsModelFeed*> &feeds,
int read) { int read) {
QSqlDatabase db_handle = DatabaseFactory::getInstance()->connection(objectName()); QSqlDatabase db_handle = DatabaseFactory::instance()->connection(objectName());
if (!db_handle.transaction()) { if (!db_handle.transaction()) {
qWarning("Starting transaction for feeds read change."); qWarning("Starting transaction for feeds read change.");
@ -461,7 +474,7 @@ bool FeedsModel::markFeedsRead(const QList<FeedsModelFeed*> &feeds,
bool FeedsModel::markFeedsDeleted(const QList<FeedsModelFeed *> &feeds, bool FeedsModel::markFeedsDeleted(const QList<FeedsModelFeed *> &feeds,
int deleted) { int deleted) {
QSqlDatabase db_handle = DatabaseFactory::getInstance()->connection(objectName()); QSqlDatabase db_handle = DatabaseFactory::instance()->connection(objectName());
if (!db_handle.transaction()) { if (!db_handle.transaction()) {
qWarning("Starting transaction for feeds clearing."); qWarning("Starting transaction for feeds clearing.");

View File

@ -36,7 +36,7 @@ class FeedsModel : public QAbstractItemModel {
// Feed/category manipulators. // Feed/category manipulators.
bool removeItems(const QModelIndexList &indexes); bool removeItems(const QModelIndexList &indexes);
// Returns all (undeleted) messages for given feeds. // Returns (undeleted) messages for given feeds.
QList<Message> messagesForFeeds(const QList<FeedsModelFeed*> &feeds); QList<Message> messagesForFeeds(const QList<FeedsModelFeed*> &feeds);
// Returns all categories, each pair // Returns all categories, each pair

View File

@ -58,7 +58,7 @@ QString FeedsModelFeed::typeToString(FeedsModelFeed::Type type) {
} }
void FeedsModelFeed::updateCounts(bool including_total_count) { void FeedsModelFeed::updateCounts(bool including_total_count) {
QSqlDatabase database = DatabaseFactory::getInstance()->connection("FeedsModelFeed"); QSqlDatabase database = DatabaseFactory::instance()->connection("FeedsModelFeed");
QSqlQuery query_all(database); QSqlQuery query_all(database);
query_all.setForwardOnly(true); query_all.setForwardOnly(true);

View File

@ -56,7 +56,7 @@ int FeedsModelRootItem::row() const {
} }
int FeedsModelRootItem::childCount() const { int FeedsModelRootItem::childCount() const {
return m_childItems.count(); return m_childItems.size();
} }
QVariant FeedsModelRootItem::data(int column, int role) const { QVariant FeedsModelRootItem::data(int column, int role) const {
@ -103,12 +103,14 @@ void FeedsModelRootItem::clearChilds() {
m_childItems.clear(); m_childItems.clear();
} }
FeedsModelRootItem *FeedsModelRootItem::removeChild(int index) { bool FeedsModelRootItem::removeChild(int index) {
FeedsModelRootItem *item_to_delete = m_childItems.at(index); if (index >= 0 && index < m_childItems.size()) {
m_childItems.removeAt(index); m_childItems.removeAt(index);
return true;
return item_to_delete; }
else {
return false;
}
} }

View File

@ -66,7 +66,7 @@ class FeedsModelRootItem {
// Removes particular child at given index. // Removes particular child at given index.
// NOTE: Child is NOT freed from the memory. // NOTE: Child is NOT freed from the memory.
FeedsModelRootItem *removeChild(int index); bool removeChild(int index);
// Compares two model items. // Compares two model items.
static bool isEqual(FeedsModelRootItem *lhs, FeedsModelRootItem *rhs); static bool isEqual(FeedsModelRootItem *lhs, FeedsModelRootItem *rhs);

View File

@ -189,7 +189,7 @@ void FeedsModelStandardFeed::update() {
void FeedsModelStandardFeed::updateMessages(const QList<Message> &messages) { void FeedsModelStandardFeed::updateMessages(const QList<Message> &messages) {
int feed_id = id(), message_id; int feed_id = id(), message_id;
qint64 message_creation_date; qint64 message_creation_date;
QSqlDatabase database = DatabaseFactory::getInstance()->connection("FeedsModelStandardFeed"); QSqlDatabase database = DatabaseFactory::instance()->connection("FeedsModelStandardFeed");
// Prepare queries. // Prepare queries.
QSqlQuery query_select(database); QSqlQuery query_select(database);

View File

@ -33,8 +33,8 @@ bool FeedsProxyModel::lessThan(const QModelIndex &left,
const QModelIndex &right) const { const QModelIndex &right) const {
if (left.isValid() && right.isValid()) { if (left.isValid() && right.isValid()) {
// Make necessary castings. // Make necessary castings.
FeedsModelRootItem *left_item = static_cast<FeedsModelRootItem*>(left.internalPointer()); FeedsModelRootItem *left_item = m_sourceModel->itemForIndex(left);
FeedsModelRootItem *right_item = static_cast<FeedsModelRootItem*>(right.internalPointer()); FeedsModelRootItem *right_item = m_sourceModel->itemForIndex(right);
// NOTE: Here we want to accomplish that ALL // NOTE: Here we want to accomplish that ALL
// categories are queued one after another and all // categories are queued one after another and all
@ -59,7 +59,10 @@ bool FeedsProxyModel::lessThan(const QModelIndex &left,
return false; return false;
} }
else { else {
// Left item is category, right item is feed.*/ // Left item is category, right item is feed.
// NOTE: Category is in fact "more" than feed but
// we consider it to be "less" because it should be "placed"
// above the "smalles" feed when ascending sort is used.
return true; return true;
} }
} }

View File

@ -13,7 +13,7 @@
MessagesModel::MessagesModel(QObject *parent) MessagesModel::MessagesModel(QObject *parent)
: QSqlTableModel(parent, : QSqlTableModel(parent,
DatabaseFactory::getInstance()->connection("MessagesModel")) { DatabaseFactory::instance()->connection("MessagesModel")) {
setObjectName("MessagesModel"); setObjectName("MessagesModel");
setupFonts(); setupFonts();

View File

@ -111,7 +111,18 @@ void FeedsView::deleteSelectedItems() {
QModelIndexList selection = selectionModel()->selectedRows(); QModelIndexList selection = selectionModel()->selectedRows();
QModelIndexList mapped_selection = m_proxyModel->mapListToSource(selection); QModelIndexList mapped_selection = m_proxyModel->mapListToSource(selection);
FeedsModelRootItem *parent = m_sourceModel->itemForIndex(mapped_selection.at(0).parent());
m_sourceModel->removeItems(mapped_selection); m_sourceModel->removeItems(mapped_selection);
QModelIndex id = m_sourceModel->indexForItem(parent);
if (id.isValid()) {
selectionModel()->clearSelection();
selectionModel()->select(m_proxyModel->mapFromSource(id),
QItemSelectionModel::Rows |
QItemSelectionModel::Select);
}
} }
void FeedsView::markSelectedFeedsReadStatus(int read) { void FeedsView::markSelectedFeedsReadStatus(int read) {