This commit is contained in:
Martin Rotter 2016-01-07 07:39:52 +01:00
parent 1489365d32
commit b4b244d634
12 changed files with 96 additions and 59 deletions

View file

@ -4,6 +4,7 @@
Added: Added:
▪ Added generic "Add new feed" action, which can be accessed via "Feeds & messages" menu. (issue #146) ▪ Added generic "Add new feed" action, which can be accessed via "Feeds & messages" menu. (issue #146)
▪ Added support for import/export to/from plain TXT file (one feed URL per line). (issue #142) ▪ Added support for import/export to/from plain TXT file (one feed URL per line). (issue #142)
▪ Optimized menu items in "Add new item" submenu. Added two new bindable actions for adding feeds & categories. (issues #146 and #148)
Changed: Changed:
▪ Some GUI refinements and fixes. ▪ Some GUI refinements and fixes.

View file

@ -135,6 +135,7 @@ QList<QAction*> FormMain::allActions() {
actions << m_ui->m_actionServiceEdit; actions << m_ui->m_actionServiceEdit;
actions << m_ui->m_actionServiceDelete; actions << m_ui->m_actionServiceDelete;
actions << m_ui->m_actionAddFeedIntoSelectedAccount; actions << m_ui->m_actionAddFeedIntoSelectedAccount;
actions << m_ui->m_actionAddCategoryIntoSelectedAccount;
actions << m_ui->m_actionViewSelectedItemsNewspaperMode; actions << m_ui->m_actionViewSelectedItemsNewspaperMode;
actions << m_ui->m_actionSelectNextItem; actions << m_ui->m_actionSelectNextItem;
actions << m_ui->m_actionSelectPreviousItem; actions << m_ui->m_actionSelectPreviousItem;
@ -185,28 +186,39 @@ void FormMain::updateAddItemMenu() {
root_menu->setIcon(activated_root->icon()); root_menu->setIcon(activated_root->icon());
root_menu->setToolTip(activated_root->description()); root_menu->setToolTip(activated_root->description());
QList<QAction*> root_actions = activated_root->addItemMenu(); QList<QAction*> specific_root_actions = activated_root->addItemMenu();
if (root_actions.isEmpty()) { if (activated_root->supportsCategoryAdding()) {
QAction *no_action = new QAction(qApp->icons()->fromTheme(QSL("dialog-error")), QAction *action_new_category = new QAction(qApp->icons()->fromTheme(QSL("folder-category")),
tr("No possible actions"), tr("Add new category"),
m_ui->m_menuAddItem); m_ui->m_menuAddItem);
no_action->setEnabled(false); root_menu->addAction(action_new_category);
root_menu->addAction(no_action); connect(action_new_category, SIGNAL(triggered()), activated_root, SLOT(addNewCategory()));
} }
else {
root_menu->addActions(root_actions); if (activated_root->supportsFeedAdding()) {
QAction *action_new_feed = new QAction(qApp->icons()->fromTheme(QSL("folder-feed")),
tr("Add new feed"),
m_ui->m_menuAddItem);
root_menu->addAction(action_new_feed);
connect(action_new_feed, SIGNAL(triggered()), activated_root, SLOT(addNewFeed()));
}
if (!specific_root_actions.isEmpty()) {
if (!root_menu->isEmpty()) {
root_menu->addSeparator();
}
root_menu->addActions(specific_root_actions);
} }
m_ui->m_menuAddItem->addMenu(root_menu); m_ui->m_menuAddItem->addMenu(root_menu);
} }
if (m_ui->m_menuAddItem->isEmpty()) { if (!m_ui->m_menuAddItem->isEmpty()) {
QAction *no_action = new QAction(qApp->icons()->fromTheme(QSL("dialog-error")), m_ui->m_menuAddItem->addSeparator();
tr("No accounts activated"), m_ui->m_menuAddItem->addAction(m_ui->m_actionAddCategoryIntoSelectedAccount);
m_ui->m_menuAddItem); m_ui->m_menuAddItem->addAction(m_ui->m_actionAddFeedIntoSelectedAccount);
no_action->setEnabled(false);
m_ui->m_menuAddItem->addAction(no_action);
} }
} }
@ -386,7 +398,8 @@ void FormMain::setupIcons() {
m_ui->m_actionServiceAdd->setIcon(icon_theme_factory->fromTheme(QSL("item-new"))); m_ui->m_actionServiceAdd->setIcon(icon_theme_factory->fromTheme(QSL("item-new")));
m_ui->m_actionServiceEdit->setIcon(icon_theme_factory->fromTheme(QSL("item-edit"))); m_ui->m_actionServiceEdit->setIcon(icon_theme_factory->fromTheme(QSL("item-edit")));
m_ui->m_actionServiceDelete->setIcon(icon_theme_factory->fromTheme(QSL("item-remove"))); m_ui->m_actionServiceDelete->setIcon(icon_theme_factory->fromTheme(QSL("item-remove")));
m_ui->m_actionAddFeedIntoSelectedAccount->setIcon(icon_theme_factory->fromTheme(QSL("item-new"))); m_ui->m_actionAddFeedIntoSelectedAccount->setIcon(icon_theme_factory->fromTheme(QSL("folder-feed")));
m_ui->m_actionAddCategoryIntoSelectedAccount->setIcon(icon_theme_factory->fromTheme(QSL("folder-category")));
// Setup icons for underlying components: opened web browsers... // Setup icons for underlying components: opened web browsers...
foreach (WebBrowser *browser, WebBrowser::runningWebBrowsers()) { foreach (WebBrowser *browser, WebBrowser::runningWebBrowsers()) {

View file

@ -137,7 +137,6 @@
<addaction name="m_actionUpdateSelectedItems"/> <addaction name="m_actionUpdateSelectedItems"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="m_menuAddItem"/> <addaction name="m_menuAddItem"/>
<addaction name="m_actionAddFeedIntoSelectedAccount"/>
<addaction name="m_actionEditSelectedItem"/> <addaction name="m_actionEditSelectedItem"/>
<addaction name="m_actionDeleteSelectedItem"/> <addaction name="m_actionDeleteSelectedItem"/>
<addaction name="separator"/> <addaction name="separator"/>
@ -790,6 +789,14 @@
<string notr="true"/> <string notr="true"/>
</property> </property>
</action> </action>
<action name="m_actionAddCategoryIntoSelectedAccount">
<property name="text">
<string>Add new category into selected account</string>
</property>
<property name="shortcut">
<string notr="true"/>
</property>
</action>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget> <customwidget>

View file

@ -63,8 +63,8 @@ void DiscoverFeedsButton::linkTriggered(QAction *action) {
QString url = action->property("url").toString(); QString url = action->property("url").toString();
ServiceRoot *root = static_cast<ServiceRoot*>(action->property("root").value<void*>()); ServiceRoot *root = static_cast<ServiceRoot*>(action->property("root").value<void*>());
if (root->supportsFeedAddingByUrl()) { if (root->supportsFeedAdding()) {
root->addFeedByUrl(url); root->addNewFeed(url);
} }
else { else {
qApp->showGuiMessage(tr("Not supported"), qApp->showGuiMessage(tr("Not supported"),
@ -81,7 +81,7 @@ void DiscoverFeedsButton::fillMenu() {
QMenu *root_menu = menu()->addMenu(root->icon(), root->title()); QMenu *root_menu = menu()->addMenu(root->icon(), root->title());
foreach (const QString &url, m_addresses) { foreach (const QString &url, m_addresses) {
if (root->supportsFeedAddingByUrl()) { if (root->supportsFeedAdding()) {
QAction *url_action = root_menu->addAction(root->icon(), url); QAction *url_action = root_menu->addAction(root->icon(), url);
url_action->setProperty("url", url); url_action->setProperty("url", url);

View file

@ -257,6 +257,8 @@ void FeedMessageViewer::createConnections() {
// Toolbar forwardings. // Toolbar forwardings.
connect(form_main->m_ui->m_actionAddFeedIntoSelectedAccount, SIGNAL(triggered()), connect(form_main->m_ui->m_actionAddFeedIntoSelectedAccount, SIGNAL(triggered()),
m_feedsView, SLOT(addFeedIntoSelectedAccount())); m_feedsView, SLOT(addFeedIntoSelectedAccount()));
connect(form_main->m_ui->m_actionAddCategoryIntoSelectedAccount, SIGNAL(triggered()),
m_feedsView, SLOT(addCategoryIntoSelectedAccount()));
connect(form_main->m_ui->m_actionCleanupDatabase, connect(form_main->m_ui->m_actionCleanupDatabase,
SIGNAL(triggered()), this, SLOT(showDbCleanupAssistant())); SIGNAL(triggered()), this, SLOT(showDbCleanupAssistant()));
connect(form_main->m_ui->m_actionSwitchImportanceOfSelectedMessages, connect(form_main->m_ui->m_actionSwitchImportanceOfSelectedMessages,

View file

@ -140,8 +140,8 @@ void FeedsView::addFeedIntoSelectedAccount() {
if (selected != NULL) { if (selected != NULL) {
ServiceRoot *root = selected->getParentServiceRoot(); ServiceRoot *root = selected->getParentServiceRoot();
if (root->supportsFeedAddingByUrl()) { if (root->supportsFeedAdding()) {
root->addFeedByUrl(); root->addNewFeed();
} }
else { else {
qApp->showGuiMessage(tr("Not supported"), qApp->showGuiMessage(tr("Not supported"),
@ -152,6 +152,24 @@ void FeedsView::addFeedIntoSelectedAccount() {
} }
} }
void FeedsView::addCategoryIntoSelectedAccount() {
RootItem *selected = selectedItem();
if (selected != NULL) {
ServiceRoot *root = selected->getParentServiceRoot();
if (root->supportsCategoryAdding()) {
root->addNewCategory();
}
else {
qApp->showGuiMessage(tr("Not supported"),
tr("Selected account does not support adding of new categories."),
QSystemTrayIcon::Warning,
qApp->mainForm(), true);
}
}
}
void FeedsView::expandCollapseCurrentItem() { void FeedsView::expandCollapseCurrentItem() {
if (selectionModel()->selectedRows().size() == 1) { if (selectionModel()->selectedRows().size() == 1) {
QModelIndex index = selectionModel()->selectedRows().at(0); QModelIndex index = selectionModel()->selectedRows().at(0);

View file

@ -63,6 +63,7 @@ class FeedsView : public QTreeView {
public slots: public slots:
void addFeedIntoSelectedAccount(); void addFeedIntoSelectedAccount();
void addCategoryIntoSelectedAccount();
void expandCollapseCurrentItem(); void expandCollapseCurrentItem();
// Feed updating. // Feed updating.

View file

@ -51,7 +51,8 @@ class ServiceRoot : public RootItem {
bool deleteViaGui(); bool deleteViaGui();
bool markAsReadUnread(ReadStatus status); bool markAsReadUnread(ReadStatus status);
virtual bool supportsFeedAddingByUrl() const = 0; virtual bool supportsFeedAdding() const = 0;
virtual bool supportsCategoryAdding() const = 0;
// Returns list of specific actions for "Add new item" main window menu. // Returns list of specific actions for "Add new item" main window menu.
// So typical list of returned actions could look like: // So typical list of returned actions could look like:
@ -159,7 +160,8 @@ class ServiceRoot : public RootItem {
void setAccountId(int account_id); void setAccountId(int account_id);
public slots: public slots:
virtual void addFeedByUrl(const QString &url = QString()) = 0; virtual void addNewFeed(const QString &url = QString()) = 0;
virtual void addNewCategory() = 0;
protected: protected:
// Takes lists of feeds/categories and assembles them into the tree structure. // Takes lists of feeds/categories and assembles them into the tree structure.

View file

@ -47,7 +47,7 @@
StandardServiceRoot::StandardServiceRoot(RootItem *parent) StandardServiceRoot::StandardServiceRoot(RootItem *parent)
: ServiceRoot(parent), m_recycleBin(new StandardRecycleBin(this)), : ServiceRoot(parent), m_recycleBin(new StandardRecycleBin(this)),
m_actionExportFeeds(NULL), m_actionImportFeeds(NULL), m_serviceMenu(QList<QAction*>()), m_actionExportFeeds(NULL), m_actionImportFeeds(NULL), m_serviceMenu(QList<QAction*>()),
m_addItemMenu(QList<QAction*>()), m_feedContextMenu(QList<QAction*>()), m_actionFeedFetchMetadata(NULL) { m_feedContextMenu(QList<QAction*>()), m_actionFeedFetchMetadata(NULL) {
setTitle(qApp->system()->getUsername() + QL1S("@") + QL1S(APP_LOW_NAME)); setTitle(qApp->system()->getUsername() + QL1S("@") + QL1S(APP_LOW_NAME));
setIcon(StandardServiceEntryPoint().icon()); setIcon(StandardServiceEntryPoint().icon());
@ -57,7 +57,6 @@ StandardServiceRoot::StandardServiceRoot(RootItem *parent)
StandardServiceRoot::~StandardServiceRoot() { StandardServiceRoot::~StandardServiceRoot() {
qDeleteAll(m_serviceMenu); qDeleteAll(m_serviceMenu);
qDeleteAll(m_addItemMenu);
qDeleteAll(m_feedContextMenu); qDeleteAll(m_feedContextMenu);
} }
@ -125,11 +124,15 @@ bool StandardServiceRoot::markAsReadUnread(RootItem::ReadStatus status) {
return ServiceRoot::markAsReadUnread(status); return ServiceRoot::markAsReadUnread(status);
} }
bool StandardServiceRoot::supportsFeedAddingByUrl() const { bool StandardServiceRoot::supportsFeedAdding() const {
return true; return true;
} }
void StandardServiceRoot::addFeedByUrl(const QString &url) { bool StandardServiceRoot::supportsCategoryAdding() const {
return true;
}
void StandardServiceRoot::addNewFeed(const QString &url) {
QPointer<FormStandardFeedDetails> form_pointer = new FormStandardFeedDetails(this, qApp->mainForm()); QPointer<FormStandardFeedDetails> form_pointer = new FormStandardFeedDetails(this, qApp->mainForm());
form_pointer.data()->exec(NULL, NULL, url); form_pointer.data()->exec(NULL, NULL, url);
delete form_pointer.data(); delete form_pointer.data();
@ -300,7 +303,7 @@ void StandardServiceRoot::checkArgumentsForFeedAdding() {
void StandardServiceRoot::checkArgumentForFeedAdding(const QString &argument) { void StandardServiceRoot::checkArgumentForFeedAdding(const QString &argument) {
if (argument.startsWith(QL1S("feed:"))) { if (argument.startsWith(QL1S("feed:"))) {
addFeedByUrl(argument); addNewFeed(argument);
} }
} }
@ -441,18 +444,7 @@ QStringList StandardServiceRoot::textualFeedIds(const QList<Feed*> &feeds) {
} }
QList<QAction*> StandardServiceRoot::addItemMenu() { QList<QAction*> StandardServiceRoot::addItemMenu() {
if (m_addItemMenu.isEmpty()) { return QList<QAction*>();
QAction *action_new_category = new QAction(qApp->icons()->fromTheme("folder-category"), tr("Add new category"), this);
connect(action_new_category, SIGNAL(triggered()), this, SLOT(addNewCategory()));
QAction *action_new_feed = new QAction(qApp->icons()->fromTheme("folder-feed"), tr("Add new feed"), this);
connect(action_new_feed, SIGNAL(triggered()), this, SLOT(addFeedByUrl()));
m_addItemMenu.append(action_new_category);
m_addItemMenu.append(action_new_feed);
}
return m_addItemMenu;
} }
QList<QAction*> StandardServiceRoot::serviceMenu() { QList<QAction*> StandardServiceRoot::serviceMenu() {

View file

@ -49,7 +49,8 @@ class StandardServiceRoot : public ServiceRoot {
bool markAsReadUnread(ReadStatus status); bool markAsReadUnread(ReadStatus status);
bool supportsFeedAddingByUrl() const; bool supportsFeedAdding() const;
bool supportsCategoryAdding() const;
QVariant data(int column, int role) const; QVariant data(int column, int role) const;
Qt::ItemFlags additionalFlags() const; Qt::ItemFlags additionalFlags() const;
@ -100,7 +101,7 @@ class StandardServiceRoot : public ServiceRoot {
void checkArgumentForFeedAdding(const QString &argument); void checkArgumentForFeedAdding(const QString &argument);
public slots: public slots:
void addFeedByUrl(const QString &url = QString()); void addNewFeed(const QString &url = QString());
void addNewCategory(); void addNewCategory();
void importFeeds(); void importFeeds();
void exportFeeds(); void exportFeeds();
@ -119,7 +120,6 @@ class StandardServiceRoot : public ServiceRoot {
QAction *m_actionImportFeeds; QAction *m_actionImportFeeds;
QList<QAction*> m_serviceMenu; QList<QAction*> m_serviceMenu;
QList<QAction*> m_addItemMenu;
QList<QAction*> m_feedContextMenu; QList<QAction*> m_feedContextMenu;
QAction *m_actionFeedFetchMetadata; QAction *m_actionFeedFetchMetadata;

View file

@ -41,8 +41,7 @@
TtRssServiceRoot::TtRssServiceRoot(RootItem *parent) TtRssServiceRoot::TtRssServiceRoot(RootItem *parent)
: ServiceRoot(parent), m_recycleBin(new TtRssRecycleBin(this)), : ServiceRoot(parent), m_recycleBin(new TtRssRecycleBin(this)),
m_actionSyncIn(NULL), m_serviceMenu(QList<QAction*>()), m_addItemMenu(QList<QAction*>()), m_actionSyncIn(NULL), m_serviceMenu(QList<QAction*>()), m_network(new TtRssNetworkFactory) {
m_network(new TtRssNetworkFactory) {
setIcon(TtRssServiceEntryPoint().icon()); setIcon(TtRssServiceEntryPoint().icon());
setCreationDate(QDateTime::currentDateTime()); setCreationDate(QDateTime::currentDateTime());
} }
@ -111,17 +110,25 @@ bool TtRssServiceRoot::markAsReadUnread(RootItem::ReadStatus status) {
} }
} }
bool TtRssServiceRoot::supportsFeedAddingByUrl() const { bool TtRssServiceRoot::supportsFeedAdding() const {
return true; return true;
} }
void TtRssServiceRoot::addFeedByUrl(const QString &url) { bool TtRssServiceRoot::supportsCategoryAdding() const {
return false;
}
void TtRssServiceRoot::addNewFeed(const QString &url) {
QPointer<FormEditFeed> form_pointer = new FormEditFeed(this, qApp->mainForm()); QPointer<FormEditFeed> form_pointer = new FormEditFeed(this, qApp->mainForm());
form_pointer.data()->execForAdd(url); form_pointer.data()->execForAdd(url);
delete form_pointer.data(); delete form_pointer.data();
} }
void TtRssServiceRoot::addNewCategory() {
// Do nothing.
}
bool TtRssServiceRoot::canBeEdited() { bool TtRssServiceRoot::canBeEdited() {
return true; return true;
} }
@ -153,14 +160,7 @@ QVariant TtRssServiceRoot::data(int column, int role) const {
} }
QList<QAction*> TtRssServiceRoot::addItemMenu() { QList<QAction*> TtRssServiceRoot::addItemMenu() {
if (m_addItemMenu.isEmpty()) { return QList<QAction*>();
QAction *action_new_feed = new QAction(qApp->icons()->fromTheme("folder-feed"), tr("Add new feed"), this);
connect(action_new_feed, SIGNAL(triggered()), this, SLOT(addFeedByUrl()));
m_addItemMenu.append(action_new_feed);
}
return m_addItemMenu;
} }
RecycleBin *TtRssServiceRoot::recycleBin() { RecycleBin *TtRssServiceRoot::recycleBin() {

View file

@ -47,7 +47,8 @@ class TtRssServiceRoot : public ServiceRoot {
bool markAsReadUnread(ReadStatus status); bool markAsReadUnread(ReadStatus status);
bool supportsFeedAddingByUrl() const; bool supportsFeedAdding() const;
bool supportsCategoryAdding() const;
QVariant data(int column, int role) const; QVariant data(int column, int role) const;
@ -85,7 +86,8 @@ class TtRssServiceRoot : public ServiceRoot {
void completelyRemoveAllData(); void completelyRemoveAllData();
public slots: public slots:
void addFeedByUrl(const QString &url = QString()); void addNewFeed(const QString &url = QString());
void addNewCategory();
void syncIn(); void syncIn();
private: private:
@ -105,7 +107,6 @@ class TtRssServiceRoot : public ServiceRoot {
QAction *m_actionSyncIn; QAction *m_actionSyncIn;
QList<QAction*> m_serviceMenu; QList<QAction*> m_serviceMenu;
QList<QAction*> m_addItemMenu;
TtRssNetworkFactory *m_network; TtRssNetworkFactory *m_network;
}; };