mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
FeedReader:
- switched to tabbed ui - load/save open folders git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@6032 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
parent
e569c89476
commit
cb9c998fe0
@ -7,6 +7,7 @@ SOURCES = FeedReaderPlugin.cpp \
|
|||||||
services/p3FeedReaderThread.cc \
|
services/p3FeedReaderThread.cc \
|
||||||
services/rsFeedReaderItems.cc \
|
services/rsFeedReaderItems.cc \
|
||||||
gui/FeedReaderDialog.cpp \
|
gui/FeedReaderDialog.cpp \
|
||||||
|
gui/FeedReaderMessageWidget.cpp \
|
||||||
gui/AddFeedDialog.cpp \
|
gui/AddFeedDialog.cpp \
|
||||||
gui/PreviewFeedDialog.cpp \
|
gui/PreviewFeedDialog.cpp \
|
||||||
gui/FeedReaderNotify.cpp \
|
gui/FeedReaderNotify.cpp \
|
||||||
@ -24,6 +25,7 @@ HEADERS = FeedReaderPlugin.h \
|
|||||||
services/p3FeedReaderThread.h \
|
services/p3FeedReaderThread.h \
|
||||||
services/rsFeedReaderItems.h \
|
services/rsFeedReaderItems.h \
|
||||||
gui/FeedReaderDialog.h \
|
gui/FeedReaderDialog.h \
|
||||||
|
gui/FeedReaderMessageWidget.h \
|
||||||
gui/AddFeedDialog.h \
|
gui/AddFeedDialog.h \
|
||||||
gui/PreviewFeedDialog.h \
|
gui/PreviewFeedDialog.h \
|
||||||
gui/FeedReaderNotify.h \
|
gui/FeedReaderNotify.h \
|
||||||
@ -36,6 +38,7 @@ HEADERS = FeedReaderPlugin.h \
|
|||||||
util/XPathWrapper.h
|
util/XPathWrapper.h
|
||||||
|
|
||||||
FORMS = gui/FeedReaderDialog.ui \
|
FORMS = gui/FeedReaderDialog.ui \
|
||||||
|
gui/FeedReaderMessageWidget.ui \
|
||||||
gui/AddFeedDialog.ui \
|
gui/AddFeedDialog.ui \
|
||||||
gui/PreviewFeedDialog.ui \
|
gui/PreviewFeedDialog.ui \
|
||||||
gui/FeedReaderConfig.ui
|
gui/FeedReaderConfig.ui
|
||||||
|
@ -19,23 +19,19 @@
|
|||||||
* Boston, MA 02110-1301, USA.
|
* Boston, MA 02110-1301, USA.
|
||||||
****************************************************************/
|
****************************************************************/
|
||||||
|
|
||||||
#include <QDateTime>
|
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QInputDialog>
|
#include <QInputDialog>
|
||||||
#include <QPixmap>
|
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QClipboard>
|
|
||||||
#include <QDesktopServices>
|
|
||||||
|
|
||||||
#include "FeedReaderDialog.h"
|
#include "FeedReaderDialog.h"
|
||||||
|
#include "FeedReaderMessageWidget.h"
|
||||||
#include "ui_FeedReaderDialog.h"
|
#include "ui_FeedReaderDialog.h"
|
||||||
#include "FeedReaderNotify.h"
|
#include "FeedReaderNotify.h"
|
||||||
#include "AddFeedDialog.h"
|
#include "AddFeedDialog.h"
|
||||||
#include "FeedReaderStringDefs.h"
|
#include "FeedReaderStringDefs.h"
|
||||||
#include "gui/common/RSTreeWidgetItem.h"
|
#include "gui/common/RSTreeWidgetItem.h"
|
||||||
#include "util/HandleRichText.h"
|
|
||||||
#include "gui/settings/rsharesettings.h"
|
#include "gui/settings/rsharesettings.h"
|
||||||
#include "FeedReaderUserNotify.h"
|
#include "FeedReaderUserNotify.h"
|
||||||
|
|
||||||
@ -57,55 +53,29 @@
|
|||||||
#define ROLE_FEED_ERROR Qt::UserRole + 8
|
#define ROLE_FEED_ERROR Qt::UserRole + 8
|
||||||
#define ROLE_FEED_DEACTIVATED Qt::UserRole + 9
|
#define ROLE_FEED_DEACTIVATED Qt::UserRole + 9
|
||||||
|
|
||||||
#define COLUMN_MSG_COUNT 4
|
|
||||||
#define COLUMN_MSG_TITLE 0
|
|
||||||
#define COLUMN_MSG_READ 1
|
|
||||||
#define COLUMN_MSG_PUBDATE 2
|
|
||||||
#define COLUMN_MSG_AUTHOR 3
|
|
||||||
#define COLUMN_MSG_DATA 0
|
|
||||||
|
|
||||||
#define ROLE_MSG_ID Qt::UserRole
|
|
||||||
#define ROLE_MSG_SORT Qt::UserRole + 1
|
|
||||||
#define ROLE_MSG_NEW Qt::UserRole + 2
|
|
||||||
#define ROLE_MSG_READ Qt::UserRole + 3
|
|
||||||
#define ROLE_MSG_LINK Qt::UserRole + 4
|
|
||||||
|
|
||||||
FeedReaderDialog::FeedReaderDialog(RsFeedReader *feedReader, QWidget *parent)
|
FeedReaderDialog::FeedReaderDialog(RsFeedReader *feedReader, QWidget *parent)
|
||||||
: MainPage(parent), mFeedReader(feedReader), ui(new Ui::FeedReaderDialog)
|
: MainPage(parent), mFeedReader(feedReader), ui(new Ui::FeedReaderDialog)
|
||||||
{
|
{
|
||||||
/* Invoke the Qt Designer generated object setup routine */
|
/* Invoke the Qt Designer generated object setup routine */
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
mProcessSettings = false;
|
||||||
|
mOpenFeedIds = NULL;
|
||||||
|
|
||||||
mNotify = new FeedReaderNotify();
|
mNotify = new FeedReaderNotify();
|
||||||
mFeedReader->setNotify(mNotify);
|
mFeedReader->setNotify(mNotify);
|
||||||
connect(mNotify, SIGNAL(notifyFeedChanged(QString,int)), this, SLOT(feedChanged(QString,int)));
|
connect(mNotify, SIGNAL(notifyFeedChanged(QString,int)), this, SLOT(feedChanged(QString,int)));
|
||||||
connect(mNotify, SIGNAL(notifyMsgChanged(QString,QString,int)), this, SLOT(msgChanged(QString,QString,int)));
|
connect(mNotify, SIGNAL(notifyMsgChanged(QString,QString,int)), this, SLOT(msgChanged(QString,QString,int)));
|
||||||
|
|
||||||
mProcessSettings = false;
|
|
||||||
|
|
||||||
/* connect signals */
|
/* connect signals */
|
||||||
connect(ui->feedTreeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(feedItemChanged(QTreeWidgetItem*)));
|
connect(ui->feedTreeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(feedItemChanged(QTreeWidgetItem*)));
|
||||||
connect(ui->msgTreeWidget, SIGNAL(itemSelectionChanged()), this, SLOT(msgItemChanged()));
|
connect(ui->messageTabWidget, SIGNAL(tabCloseRequested(int)), this, SLOT(messageTabCloseRequested(int)));
|
||||||
connect(ui->msgTreeWidget, SIGNAL(itemClicked(QTreeWidgetItem*,int)), this, SLOT(msgItemClicked(QTreeWidgetItem*,int)));
|
|
||||||
|
|
||||||
connect(ui->feedTreeWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(feedTreeCustomPopupMenu(QPoint)));
|
connect(ui->feedTreeWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(feedTreeCustomPopupMenu(QPoint)));
|
||||||
connect(ui->msgTreeWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(msgTreeCustomPopupMenu(QPoint)));
|
|
||||||
|
|
||||||
connect(ui->filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterItems(QString)));
|
|
||||||
connect(ui->filterLineEdit, SIGNAL(filterChanged(int)), this, SLOT(filterColumnChanged(int)));
|
|
||||||
|
|
||||||
connect(ui->linkButton, SIGNAL(clicked()), this, SLOT(openLinkMsg()));
|
|
||||||
connect(ui->expandButton, SIGNAL(clicked()), this, SLOT(toggleMsgText()));
|
|
||||||
|
|
||||||
mFeedCompareRole = new RSTreeWidgetItemCompareRole;
|
mFeedCompareRole = new RSTreeWidgetItemCompareRole;
|
||||||
mFeedCompareRole->setRole(COLUMN_FEED_NAME, ROLE_FEED_SORT);
|
mFeedCompareRole->setRole(COLUMN_FEED_NAME, ROLE_FEED_SORT);
|
||||||
|
|
||||||
mMsgCompareRole = new RSTreeWidgetItemCompareRole;
|
|
||||||
mMsgCompareRole->setRole(COLUMN_MSG_TITLE, ROLE_MSG_SORT);
|
|
||||||
mMsgCompareRole->setRole(COLUMN_MSG_READ, ROLE_MSG_SORT);
|
|
||||||
mMsgCompareRole->setRole(COLUMN_MSG_PUBDATE, ROLE_MSG_SORT);
|
|
||||||
mMsgCompareRole->setRole(COLUMN_MSG_AUTHOR, ROLE_MSG_SORT);
|
|
||||||
|
|
||||||
/* initialize root item */
|
/* initialize root item */
|
||||||
mRootItem = new QTreeWidgetItem(ui->feedTreeWidget);
|
mRootItem = new QTreeWidgetItem(ui->feedTreeWidget);
|
||||||
QString name = tr("Message Folders");
|
QString name = tr("Message Folders");
|
||||||
@ -116,54 +86,18 @@ FeedReaderDialog::FeedReaderDialog(RsFeedReader *feedReader, QWidget *parent)
|
|||||||
mRootItem->setData(COLUMN_FEED_DATA, ROLE_FEED_ICON, QIcon(":/images/Root.png"));
|
mRootItem->setData(COLUMN_FEED_DATA, ROLE_FEED_ICON, QIcon(":/images/Root.png"));
|
||||||
mRootItem->setExpanded(true);
|
mRootItem->setExpanded(true);
|
||||||
|
|
||||||
/* initialize msg list */
|
|
||||||
ui->msgTreeWidget->sortItems(COLUMN_MSG_PUBDATE, Qt::DescendingOrder);
|
|
||||||
|
|
||||||
/* set initial size the splitter */
|
/* set initial size the splitter */
|
||||||
QList<int> sizes;
|
QList<int> sizes;
|
||||||
sizes << 300 << width(); // Qt calculates the right sizes
|
sizes << 300 << width(); // Qt calculates the right sizes
|
||||||
ui->splitter->setSizes(sizes);
|
ui->splitter->setSizes(sizes);
|
||||||
|
|
||||||
/* set header resize modes and initial section sizes */
|
|
||||||
QHeaderView *header = ui->msgTreeWidget->header();
|
|
||||||
header->setResizeMode(COLUMN_MSG_TITLE, QHeaderView::Interactive);
|
|
||||||
header->resizeSection(COLUMN_MSG_TITLE, 350);
|
|
||||||
header->resizeSection(COLUMN_MSG_PUBDATE, 140);
|
|
||||||
header->resizeSection(COLUMN_MSG_AUTHOR, 150);
|
|
||||||
|
|
||||||
/* set text of column "Read" to empty - without this the column has a number as header text */
|
|
||||||
QTreeWidgetItem *headerItem = ui->msgTreeWidget->headerItem();
|
|
||||||
headerItem->setText(COLUMN_MSG_READ, "");
|
|
||||||
|
|
||||||
/* add filter actions */
|
|
||||||
ui->filterLineEdit->addFilter(QIcon(), tr("Title"), COLUMN_MSG_TITLE, tr("Search Title"));
|
|
||||||
ui->filterLineEdit->addFilter(QIcon(), tr("Date"), COLUMN_MSG_PUBDATE, tr("Search Date"));
|
|
||||||
ui->filterLineEdit->addFilter(QIcon(), tr("Author"), COLUMN_MSG_AUTHOR, tr("Search Author"));
|
|
||||||
ui->filterLineEdit->setCurrentFilter(COLUMN_MSG_TITLE);
|
|
||||||
|
|
||||||
/* load settings */
|
/* load settings */
|
||||||
processSettings(true);
|
processSettings(true);
|
||||||
|
|
||||||
/* Set header sizes for the fixed columns and resize modes, must be set after processSettings */
|
|
||||||
header->resizeSection(COLUMN_MSG_READ, 24);
|
|
||||||
header->setResizeMode(COLUMN_MSG_READ, QHeaderView::Fixed);
|
|
||||||
|
|
||||||
/* initialize feed list */
|
/* initialize feed list */
|
||||||
ui->feedTreeWidget->sortItems(COLUMN_FEED_NAME, Qt::AscendingOrder);
|
ui->feedTreeWidget->sortItems(COLUMN_FEED_NAME, Qt::AscendingOrder);
|
||||||
|
|
||||||
/* build menu for link button */
|
ui->feedTreeWidget->installEventFilter(this);
|
||||||
QMenu *menu = new QMenu(this);
|
|
||||||
QAction *action = menu->addAction(tr("Open link in browser"), this, SLOT(openLinkMsg()));
|
|
||||||
menu->addAction(tr("Copy link to clipboard"), this, SLOT(copyLinkMsg()));
|
|
||||||
|
|
||||||
QFont font = action->font();
|
|
||||||
font.setBold(true);
|
|
||||||
action->setFont(font);
|
|
||||||
|
|
||||||
ui->linkButton->setMenu(menu);
|
|
||||||
ui->linkButton->setEnabled(false);
|
|
||||||
|
|
||||||
ui->msgTreeWidget->installEventFilter(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FeedReaderDialog::~FeedReaderDialog()
|
FeedReaderDialog::~FeedReaderDialog()
|
||||||
@ -172,11 +106,15 @@ FeedReaderDialog::~FeedReaderDialog()
|
|||||||
processSettings(false);
|
processSettings(false);
|
||||||
|
|
||||||
delete(mFeedCompareRole);
|
delete(mFeedCompareRole);
|
||||||
delete(mMsgCompareRole);
|
|
||||||
delete(ui);
|
delete(ui);
|
||||||
|
|
||||||
mFeedReader->setNotify(NULL);
|
mFeedReader->setNotify(NULL);
|
||||||
delete(mNotify);
|
delete(mNotify);
|
||||||
|
|
||||||
|
if (mOpenFeedIds) {
|
||||||
|
delete mOpenFeedIds;
|
||||||
|
mOpenFeedIds = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UserNotify *FeedReaderDialog::getUserNotify(QObject *parent)
|
UserNotify *FeedReaderDialog::getUserNotify(QObject *parent)
|
||||||
@ -187,43 +125,74 @@ UserNotify *FeedReaderDialog::getUserNotify(QObject *parent)
|
|||||||
void FeedReaderDialog::processSettings(bool load)
|
void FeedReaderDialog::processSettings(bool load)
|
||||||
{
|
{
|
||||||
mProcessSettings = true;
|
mProcessSettings = true;
|
||||||
|
|
||||||
QHeaderView *header = ui->msgTreeWidget->header ();
|
|
||||||
|
|
||||||
Settings->beginGroup(QString("FeedReaderDialog"));
|
Settings->beginGroup(QString("FeedReaderDialog"));
|
||||||
|
|
||||||
if (load) {
|
if (load) {
|
||||||
// load settings
|
// load settings
|
||||||
|
|
||||||
// expandButton
|
|
||||||
bool value = Settings->value("expandButton", true).toBool();
|
|
||||||
ui->expandButton->setChecked(value);
|
|
||||||
toggleMsgText_internal();
|
|
||||||
|
|
||||||
// filterColumn
|
|
||||||
ui->filterLineEdit->setCurrentFilter(Settings->value("filterColumn", COLUMN_MSG_TITLE).toInt());
|
|
||||||
|
|
||||||
// state of thread tree
|
|
||||||
header->restoreState(Settings->value("msgTree").toByteArray());
|
|
||||||
|
|
||||||
// state of splitter
|
// state of splitter
|
||||||
ui->splitter->restoreState(Settings->value("Splitter").toByteArray());
|
ui->splitter->restoreState(Settings->value("Splitter").toByteArray());
|
||||||
ui->msgSplitter->restoreState(Settings->value("msgSplitter").toByteArray());
|
|
||||||
|
// open feeds
|
||||||
|
int arrayIndex = Settings->beginReadArray("Feeds");
|
||||||
|
for (int index = 0; index < arrayIndex; index++) {
|
||||||
|
Settings->setArrayIndex(index);
|
||||||
|
addFeedToExpand(Settings->value("open").toString().toStdString());
|
||||||
|
}
|
||||||
|
Settings->endArray();
|
||||||
} else {
|
} else {
|
||||||
// save settings
|
// save settings
|
||||||
|
|
||||||
// state of thread tree
|
|
||||||
Settings->setValue("msgTree", header->saveState());
|
|
||||||
|
|
||||||
// state of splitter
|
// state of splitter
|
||||||
Settings->setValue("Splitter", ui->splitter->saveState());
|
Settings->setValue("Splitter", ui->splitter->saveState());
|
||||||
Settings->setValue("msgSplitter", ui->msgSplitter->saveState());
|
|
||||||
|
// open groups
|
||||||
|
Settings->beginWriteArray("Feeds");
|
||||||
|
int arrayIndex = 0;
|
||||||
|
QList<std::string> expandedFeedIds;
|
||||||
|
getExpandedFeedIds(expandedFeedIds);
|
||||||
|
foreach (std::string feedId, expandedFeedIds) {
|
||||||
|
Settings->setArrayIndex(arrayIndex++);
|
||||||
|
Settings->setValue("open", QString::fromStdString(feedId));
|
||||||
|
}
|
||||||
|
Settings->endArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
Settings->endGroup();
|
Settings->endGroup();
|
||||||
mProcessSettings = false;
|
mProcessSettings = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FeedReaderDialog::addFeedToExpand(const std::string &feedId)
|
||||||
|
{
|
||||||
|
if (mOpenFeedIds == NULL) {
|
||||||
|
mOpenFeedIds = new QList<std::string>;
|
||||||
|
}
|
||||||
|
if (mOpenFeedIds->contains(feedId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mOpenFeedIds->push_back(feedId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FeedReaderDialog::getExpandedFeedIds(QList<std::string> &feedIds)
|
||||||
|
{
|
||||||
|
QTreeWidgetItemIterator it(ui->feedTreeWidget);
|
||||||
|
QTreeWidgetItem *item;
|
||||||
|
while ((item = *it) != NULL) {
|
||||||
|
++it;
|
||||||
|
if (!item->isExpanded()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!item->data(COLUMN_FEED_DATA, ROLE_FEED_FOLDER).toBool()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::string feedId = item->data(COLUMN_FEED_DATA, ROLE_FEED_ID).toString().toStdString();
|
||||||
|
if (feedId.empty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
feedIds.push_back(feedId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void FeedReaderDialog::showEvent(QShowEvent */*event*/)
|
void FeedReaderDialog::showEvent(QShowEvent */*event*/)
|
||||||
{
|
{
|
||||||
updateFeeds("", mRootItem);
|
updateFeeds("", mRootItem);
|
||||||
@ -231,24 +200,6 @@ void FeedReaderDialog::showEvent(QShowEvent */*event*/)
|
|||||||
|
|
||||||
bool FeedReaderDialog::eventFilter(QObject *obj, QEvent *event)
|
bool FeedReaderDialog::eventFilter(QObject *obj, QEvent *event)
|
||||||
{
|
{
|
||||||
if (obj == ui->msgTreeWidget) {
|
|
||||||
if (event->type() == QEvent::KeyPress) {
|
|
||||||
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
|
|
||||||
if (keyEvent) {
|
|
||||||
if (keyEvent->key() == Qt::Key_Space) {
|
|
||||||
/* Space pressed */
|
|
||||||
QTreeWidgetItem *item = ui->msgTreeWidget->currentItem();
|
|
||||||
msgItemClicked(item, COLUMN_MSG_READ);
|
|
||||||
return true; // eat event
|
|
||||||
}
|
|
||||||
if (keyEvent->key() == Qt::Key_Delete) {
|
|
||||||
/* Delete pressed */
|
|
||||||
removeMsg();
|
|
||||||
return true; // eat event
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (obj == ui->feedTreeWidget) {
|
if (obj == ui->feedTreeWidget) {
|
||||||
if (event->type() == QEvent::KeyPress) {
|
if (event->type() == QEvent::KeyPress) {
|
||||||
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
|
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
|
||||||
@ -275,16 +226,6 @@ std::string FeedReaderDialog::currentFeedId()
|
|||||||
return item->data(COLUMN_FEED_DATA, ROLE_FEED_ID).toString().toStdString();
|
return item->data(COLUMN_FEED_DATA, ROLE_FEED_ID).toString().toStdString();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string FeedReaderDialog::currentMsgId()
|
|
||||||
{
|
|
||||||
QTreeWidgetItem *item = ui->msgTreeWidget->currentItem();
|
|
||||||
if (!item) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
return item->data(COLUMN_MSG_DATA, ROLE_MSG_ID).toString().toStdString();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FeedReaderDialog::feedTreeCustomPopupMenu(QPoint /*point*/)
|
void FeedReaderDialog::feedTreeCustomPopupMenu(QPoint /*point*/)
|
||||||
{
|
{
|
||||||
QMenu contextMnu(this);
|
QMenu contextMnu(this);
|
||||||
@ -335,31 +276,6 @@ void FeedReaderDialog::feedTreeCustomPopupMenu(QPoint /*point*/)
|
|||||||
contextMnu.exec(QCursor::pos());
|
contextMnu.exec(QCursor::pos());
|
||||||
}
|
}
|
||||||
|
|
||||||
void FeedReaderDialog::msgTreeCustomPopupMenu(QPoint /*point*/)
|
|
||||||
{
|
|
||||||
QMenu contextMnu(this);
|
|
||||||
|
|
||||||
QList<QTreeWidgetItem*> selectedItems = ui->msgTreeWidget->selectedItems();
|
|
||||||
|
|
||||||
QAction *action = contextMnu.addAction(QIcon(""), tr("Mark as read"), this, SLOT(markAsReadMsg()));
|
|
||||||
action->setEnabled(!selectedItems.empty());
|
|
||||||
|
|
||||||
action = contextMnu.addAction(QIcon(""), tr("Mark as unread"), this, SLOT(markAsUnreadMsg()));
|
|
||||||
action->setEnabled(!selectedItems.empty());
|
|
||||||
|
|
||||||
action = contextMnu.addAction(QIcon(""), tr("Mark all as read"), this, SLOT(markAllAsReadMsg()));
|
|
||||||
|
|
||||||
contextMnu.addSeparator();
|
|
||||||
|
|
||||||
action = contextMnu.addAction(QIcon(""), tr("Copy link"), this, SLOT(copyLinskMsg()));
|
|
||||||
action->setEnabled(!selectedItems.empty());
|
|
||||||
|
|
||||||
action = contextMnu.addAction(QIcon(""), tr("Remove"), this, SLOT(removeMsg()));
|
|
||||||
action->setEnabled(!selectedItems.empty());
|
|
||||||
|
|
||||||
contextMnu.exec(QCursor::pos());
|
|
||||||
}
|
|
||||||
|
|
||||||
void FeedReaderDialog::updateFeeds(const std::string &parentId, QTreeWidgetItem *parentItem)
|
void FeedReaderDialog::updateFeeds(const std::string &parentId, QTreeWidgetItem *parentItem)
|
||||||
{
|
{
|
||||||
if (!parentItem) {
|
if (!parentItem) {
|
||||||
@ -412,8 +328,22 @@ void FeedReaderDialog::updateFeeds(const std::string &parentId, QTreeWidgetItem
|
|||||||
if (feedIt->flag.folder) {
|
if (feedIt->flag.folder) {
|
||||||
/* process child feeds */
|
/* process child feeds */
|
||||||
updateFeeds(feedIt->feedId, item);
|
updateFeeds(feedIt->feedId, item);
|
||||||
|
|
||||||
|
if (mOpenFeedIds) {
|
||||||
|
int index = mOpenFeedIds->indexOf(feedIt->feedId);
|
||||||
|
if (index >= 0) {
|
||||||
|
item->setExpanded(true);
|
||||||
|
mOpenFeedIds->removeAt(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mOpenFeedIds && mOpenFeedIds->empty()) {
|
||||||
|
delete mOpenFeedIds;
|
||||||
|
mOpenFeedIds = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
calculateFeedItems();
|
calculateFeedItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -534,113 +464,6 @@ void FeedReaderDialog::updateFeedItem(QTreeWidgetItem *item, FeedInfo &info)
|
|||||||
item->setToolTip(COLUMN_FEED_NAME, (info.errorState != RS_FEED_ERRORSTATE_OK) ? FeedReaderStringDefs::errorString(info) : "");
|
item->setToolTip(COLUMN_FEED_NAME, (info.errorState != RS_FEED_ERRORSTATE_OK) ? FeedReaderStringDefs::errorString(info) : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
void FeedReaderDialog::updateMsgs(const std::string &feedId)
|
|
||||||
{
|
|
||||||
std::list<FeedMsgInfo> msgInfos;
|
|
||||||
if (!mFeedReader->getFeedMsgList(feedId, msgInfos)) {
|
|
||||||
ui->msgTreeWidget->clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int index = 0;
|
|
||||||
QTreeWidgetItem *item;
|
|
||||||
std::list<FeedMsgInfo>::iterator msgIt;
|
|
||||||
|
|
||||||
/* update existing and delete not existing msgs */
|
|
||||||
while (index < ui->msgTreeWidget->topLevelItemCount()) {
|
|
||||||
item = ui->msgTreeWidget->topLevelItem(index);
|
|
||||||
std::string msgId = item->data(COLUMN_MSG_DATA, ROLE_MSG_ID).toString().toStdString();
|
|
||||||
|
|
||||||
/* search existing msg */
|
|
||||||
int found = -1;
|
|
||||||
for (msgIt = msgInfos.begin (); msgIt != msgInfos.end (); ++msgIt) {
|
|
||||||
if (msgIt->msgId == msgId) {
|
|
||||||
/* found it, update it */
|
|
||||||
updateMsgItem(item, *msgIt);
|
|
||||||
|
|
||||||
msgInfos.erase(msgIt);
|
|
||||||
found = index;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (found >= 0) {
|
|
||||||
++index;
|
|
||||||
} else {
|
|
||||||
delete(ui->msgTreeWidget->takeTopLevelItem(index));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* add new msgs */
|
|
||||||
for (msgIt = msgInfos.begin (); msgIt != msgInfos.end (); ++msgIt) {
|
|
||||||
item = new RSTreeWidgetItem(mMsgCompareRole);
|
|
||||||
updateMsgItem(item, *msgIt);
|
|
||||||
ui->msgTreeWidget->addTopLevelItem(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
filterItems(ui->filterLineEdit->text());
|
|
||||||
}
|
|
||||||
|
|
||||||
void FeedReaderDialog::calculateMsgIconsAndFonts(QTreeWidgetItem *item)
|
|
||||||
{
|
|
||||||
if (!item) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isnew = item->data(COLUMN_MSG_DATA, ROLE_MSG_NEW).toBool();
|
|
||||||
bool read = item->data(COLUMN_MSG_DATA, ROLE_MSG_READ).toBool();
|
|
||||||
|
|
||||||
if (read) {
|
|
||||||
item->setIcon(COLUMN_MSG_READ, QIcon(":/images/message-state-read.png"));
|
|
||||||
} else {
|
|
||||||
item->setIcon(COLUMN_MSG_READ, QIcon(":/images/message-state-unread.png"));
|
|
||||||
}
|
|
||||||
if (isnew) {
|
|
||||||
item->setIcon(COLUMN_MSG_TITLE, QIcon(":/images/message-state-new.png"));
|
|
||||||
} else {
|
|
||||||
item->setIcon(COLUMN_MSG_TITLE, QIcon());
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < COLUMN_FEED_COUNT; i++) {
|
|
||||||
QFont font = item->font(i);
|
|
||||||
font.setBold(isnew || !read);
|
|
||||||
item->setFont(i, font);
|
|
||||||
}
|
|
||||||
|
|
||||||
item->setData(COLUMN_MSG_READ, ROLE_MSG_SORT, QString("%1_%2_%3").arg(QString(isnew ? "1" : "0"), QString(read ? "0" : "1"), item->data(COLUMN_MSG_TITLE, ROLE_MSG_SORT).toString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void FeedReaderDialog::updateMsgItem(QTreeWidgetItem *item, FeedMsgInfo &info)
|
|
||||||
{
|
|
||||||
QString title = QString::fromUtf8(info.title.c_str());
|
|
||||||
QDateTime qdatetime;
|
|
||||||
qdatetime.setTime_t(info.pubDate);
|
|
||||||
|
|
||||||
/* add string to all data */
|
|
||||||
QString sort = QString("%1_%2_%2").arg(title, qdatetime.toString("yyyyMMdd_hhmmss"), QString::fromStdString(info.feedId));
|
|
||||||
|
|
||||||
item->setText(COLUMN_MSG_TITLE, title);
|
|
||||||
item->setData(COLUMN_MSG_TITLE, ROLE_MSG_SORT, sort);
|
|
||||||
|
|
||||||
QString author = QString::fromUtf8(info.author.c_str());
|
|
||||||
item->setText(COLUMN_MSG_AUTHOR, author);
|
|
||||||
item->setData(COLUMN_MSG_AUTHOR, ROLE_MSG_SORT, author + "_" + sort);
|
|
||||||
|
|
||||||
/* if the message is on same date show only time */
|
|
||||||
if (qdatetime.daysTo(QDateTime::currentDateTime()) == 0) {
|
|
||||||
item->setData(COLUMN_MSG_PUBDATE, Qt::DisplayRole, qdatetime.time());
|
|
||||||
} else {
|
|
||||||
item->setData(COLUMN_MSG_PUBDATE, Qt::DisplayRole, qdatetime);
|
|
||||||
}
|
|
||||||
item->setData(COLUMN_MSG_PUBDATE, ROLE_MSG_SORT, QString("%1_%2_%3").arg(qdatetime.toString("yyyyMMdd_hhmmss"), title, QString::fromStdString(info.msgId)));
|
|
||||||
|
|
||||||
item->setData(COLUMN_MSG_DATA, ROLE_MSG_ID, QString::fromStdString(info.msgId));
|
|
||||||
item->setData(COLUMN_MSG_DATA, ROLE_MSG_LINK, QString::fromUtf8(info.link.c_str()));
|
|
||||||
item->setData(COLUMN_MSG_DATA, ROLE_MSG_READ, info.flag.read);
|
|
||||||
item->setData(COLUMN_MSG_DATA, ROLE_MSG_NEW, info.flag.isnew);
|
|
||||||
|
|
||||||
calculateMsgIconsAndFonts(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FeedReaderDialog::feedChanged(const QString &feedId, int type)
|
void FeedReaderDialog::feedChanged(const QString &feedId, int type)
|
||||||
{
|
{
|
||||||
if (!isVisible()) {
|
if (!isVisible()) {
|
||||||
@ -697,218 +520,66 @@ void FeedReaderDialog::feedChanged(const QString &feedId, int type)
|
|||||||
calculateFeedItems();
|
calculateFeedItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FeedReaderDialog::msgChanged(const QString &feedId, const QString &msgId, int type)
|
FeedReaderMessageWidget *FeedReaderDialog::feedMessageWidget(const std::string &id)
|
||||||
{
|
{
|
||||||
if (!isVisible()) {
|
int tabCount = ui->messageTabWidget->count();
|
||||||
/* complete update in showEvent */
|
for (int index = 0; index < tabCount; ++index) {
|
||||||
return;
|
FeedReaderMessageWidget *childWidget = dynamic_cast<FeedReaderMessageWidget*>(ui->messageTabWidget->widget(index));
|
||||||
}
|
if (childWidget && childWidget->feedId() == id) {
|
||||||
|
return childWidget;
|
||||||
if (feedId.isEmpty() || msgId.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (feedId.toStdString() != currentFeedId()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
FeedMsgInfo msgInfo;
|
|
||||||
if (type != NOTIFY_TYPE_DEL) {
|
|
||||||
if (!mFeedReader->getMsgInfo(feedId.toStdString(), msgId.toStdString(), msgInfo)) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == NOTIFY_TYPE_MOD || type == NOTIFY_TYPE_DEL) {
|
return NULL;
|
||||||
QTreeWidgetItemIterator it(ui->msgTreeWidget);
|
|
||||||
QTreeWidgetItem *item;
|
|
||||||
while ((item = *it) != NULL) {
|
|
||||||
if (item->data(COLUMN_MSG_DATA, ROLE_MSG_ID).toString() == msgId) {
|
|
||||||
if (type == NOTIFY_TYPE_MOD) {
|
|
||||||
updateMsgItem(item, msgInfo);
|
|
||||||
filterItem(item);
|
|
||||||
} else {
|
|
||||||
delete(item);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == NOTIFY_TYPE_ADD) {
|
|
||||||
QTreeWidgetItem *item = new RSTreeWidgetItem(mMsgCompareRole);
|
|
||||||
updateMsgItem(item, msgInfo);
|
|
||||||
ui->msgTreeWidget->addTopLevelItem(item);
|
|
||||||
filterItem(item);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FeedReaderDialog::feedItemChanged(QTreeWidgetItem *item)
|
void FeedReaderDialog::feedItemChanged(QTreeWidgetItem *item)
|
||||||
{
|
{
|
||||||
if (!item) {
|
if (!item) {
|
||||||
ui->msgTreeWidget->clear();
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item->data(COLUMN_FEED_DATA, ROLE_FEED_FOLDER).toBool()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string feedId = item->data(COLUMN_FEED_DATA, ROLE_FEED_ID).toString().toStdString();
|
std::string feedId = item->data(COLUMN_FEED_DATA, ROLE_FEED_ID).toString().toStdString();
|
||||||
updateMsgs(feedId);
|
/* search exisiting tab */
|
||||||
|
FeedReaderMessageWidget *messageWidget = feedMessageWidget(feedId);
|
||||||
|
|
||||||
|
if (!messageWidget) {
|
||||||
|
/* create a message widget */
|
||||||
|
messageWidget = new FeedReaderMessageWidget(feedId, mFeedReader, mNotify);
|
||||||
|
int index = ui->messageTabWidget->addTab(messageWidget, messageWidget->feedName(true));
|
||||||
|
ui->messageTabWidget->setTabIcon(index, messageWidget->feedIcon());
|
||||||
|
connect(messageWidget, SIGNAL(feedMessageChanged(QWidget*)), this, SLOT(messageTabChanged(QWidget*)));
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->messageTabWidget->setCurrentWidget(messageWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FeedReaderDialog::msgItemClicked(QTreeWidgetItem *item, int column)
|
void FeedReaderDialog::messageTabCloseRequested(int index)
|
||||||
{
|
{
|
||||||
if (item == NULL) {
|
FeedReaderMessageWidget *messageWidget = dynamic_cast<FeedReaderMessageWidget*>(ui->messageTabWidget->widget(index));
|
||||||
|
if (messageWidget) {
|
||||||
|
delete(messageWidget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FeedReaderDialog::messageTabChanged(QWidget *widget)
|
||||||
|
{
|
||||||
|
int index = ui->messageTabWidget->indexOf(widget);
|
||||||
|
if (index < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (column == COLUMN_MSG_READ) {
|
FeedReaderMessageWidget *messageWidget = dynamic_cast<FeedReaderMessageWidget*>(ui->messageTabWidget->widget(index));
|
||||||
QList<QTreeWidgetItem*> rows;
|
if (!messageWidget) {
|
||||||
rows.append(item);
|
|
||||||
bool read = item->data(COLUMN_MSG_DATA, ROLE_MSG_READ).toBool();
|
|
||||||
setMsgAsReadUnread(rows, !read);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FeedReaderDialog::msgItemChanged()
|
|
||||||
{
|
|
||||||
long todo; // show link somewhere
|
|
||||||
|
|
||||||
std::string feedId = currentFeedId();
|
|
||||||
std::string msgId = currentMsgId();
|
|
||||||
|
|
||||||
if (feedId.empty() || msgId.empty()) {
|
|
||||||
ui->msgTitle->clear();
|
|
||||||
// ui->msgLink->clear();
|
|
||||||
ui->msgText->clear();
|
|
||||||
ui->linkButton->setEnabled(false);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QTreeWidgetItem *item = ui->msgTreeWidget->currentItem();
|
ui->messageTabWidget->setTabText(index, messageWidget->feedName(true));
|
||||||
if (!item) {
|
ui->messageTabWidget->setTabIcon(index, messageWidget->feedIcon());
|
||||||
/* there is something wrong */
|
|
||||||
ui->msgTitle->clear();
|
|
||||||
// ui->msgLink->clear();
|
|
||||||
ui->msgText->clear();
|
|
||||||
ui->linkButton->setEnabled(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get msg */
|
|
||||||
FeedMsgInfo msgInfo;
|
|
||||||
if (!mFeedReader->getMsgInfo(feedId, msgId, msgInfo)) {
|
|
||||||
ui->msgTitle->clear();
|
|
||||||
// ui->msgLink->clear();
|
|
||||||
ui->msgText->clear();
|
|
||||||
ui->linkButton->setEnabled(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool setToReadOnActive = Settings->valueFromGroup("FeedReaderDialog", "SetMsgToReadOnActivate", true).toBool();
|
|
||||||
bool isnew = item->data(COLUMN_MSG_DATA, ROLE_MSG_NEW).toBool();
|
|
||||||
bool read = item->data(COLUMN_MSG_DATA, ROLE_MSG_READ).toBool();
|
|
||||||
|
|
||||||
QList<QTreeWidgetItem*> row;
|
|
||||||
row.append(item);
|
|
||||||
if (read) {
|
|
||||||
if (isnew) {
|
|
||||||
/* something wrong, but set as read again to clear the new flag */
|
|
||||||
setMsgAsReadUnread(row, true);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* set to read/unread */
|
|
||||||
setMsgAsReadUnread(row, setToReadOnActive);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString msgTxt = RsHtml().formatText(ui->msgText->document(), QString::fromUtf8(msgInfo.description.c_str()), RSHTML_FORMATTEXT_EMBED_LINKS);
|
|
||||||
|
|
||||||
ui->msgText->setHtml(msgTxt);
|
|
||||||
ui->msgTitle->setText(QString::fromUtf8(msgInfo.title.c_str()));
|
|
||||||
|
|
||||||
ui->linkButton->setEnabled(!msgInfo.link.empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
void FeedReaderDialog::setMsgAsReadUnread(QList<QTreeWidgetItem *> &rows, bool read)
|
|
||||||
{
|
|
||||||
QList<QTreeWidgetItem*>::iterator rowIt;
|
|
||||||
|
|
||||||
std::string feedId = currentFeedId();
|
|
||||||
if (feedId.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (rowIt = rows.begin(); rowIt != rows.end(); rowIt++) {
|
|
||||||
QTreeWidgetItem *item = *rowIt;
|
|
||||||
bool rowRead = item->data(COLUMN_MSG_DATA, ROLE_MSG_READ).toBool();
|
|
||||||
bool rowNew = item->data(COLUMN_MSG_DATA, ROLE_MSG_NEW).toBool();
|
|
||||||
|
|
||||||
if (rowNew || read != rowRead) {
|
|
||||||
std::string msgId = item->data(COLUMN_MSG_DATA, ROLE_MSG_ID).toString().toStdString();
|
|
||||||
mFeedReader->setMessageRead(feedId, msgId, read);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FeedReaderDialog::filterColumnChanged(int column)
|
|
||||||
{
|
|
||||||
if (mProcessSettings) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
filterItems(ui->filterLineEdit->text());
|
|
||||||
|
|
||||||
// save index
|
|
||||||
Settings->setValueToGroup("FeedReaderDialog", "filterColumn", column);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FeedReaderDialog::filterItems(const QString& text)
|
|
||||||
{
|
|
||||||
int filterColumn = ui->filterLineEdit->currentFilter();
|
|
||||||
|
|
||||||
int count = ui->msgTreeWidget->topLevelItemCount();
|
|
||||||
for (int index = 0; index < count; ++index) {
|
|
||||||
filterItem(ui->msgTreeWidget->topLevelItem(index), text, filterColumn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FeedReaderDialog::filterItem(QTreeWidgetItem *item, const QString &text, int filterColumn)
|
|
||||||
{
|
|
||||||
if (text.isEmpty() == false) {
|
|
||||||
if (item->text(filterColumn).contains(text, Qt::CaseInsensitive)) {
|
|
||||||
item->setHidden(false);
|
|
||||||
} else {
|
|
||||||
item->setHidden(true);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
item->setHidden(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FeedReaderDialog::filterItem(QTreeWidgetItem *item)
|
|
||||||
{
|
|
||||||
filterItem(item, ui->filterLineEdit->text(), ui->filterLineEdit->currentFilter());
|
|
||||||
}
|
|
||||||
|
|
||||||
void FeedReaderDialog::toggleMsgText()
|
|
||||||
{
|
|
||||||
// save state of button
|
|
||||||
Settings->setValueToGroup("FeedReaderDialog", "expandButton", ui->expandButton->isChecked());
|
|
||||||
|
|
||||||
toggleMsgText_internal();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FeedReaderDialog::toggleMsgText_internal()
|
|
||||||
{
|
|
||||||
if (ui->expandButton->isChecked()) {
|
|
||||||
ui->msgText->setVisible(true);
|
|
||||||
ui->expandButton->setIcon(QIcon(QString(":/images/edit_remove24.png")));
|
|
||||||
ui->expandButton->setToolTip(tr("Hide"));
|
|
||||||
} else {
|
|
||||||
ui->msgText->setVisible(false);
|
|
||||||
ui->expandButton->setIcon(QIcon(QString(":/images/edit_add24.png")));
|
|
||||||
ui->expandButton->setToolTip(tr("Expand"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FeedReaderDialog::newFolder()
|
void FeedReaderDialog::newFolder()
|
||||||
@ -1014,98 +685,3 @@ void FeedReaderDialog::processFeed()
|
|||||||
|
|
||||||
mFeedReader->processFeed(feedId);
|
mFeedReader->processFeed(feedId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FeedReaderDialog::markAsReadMsg()
|
|
||||||
{
|
|
||||||
QList<QTreeWidgetItem*> selectedItems = ui->msgTreeWidget->selectedItems();
|
|
||||||
setMsgAsReadUnread(selectedItems, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FeedReaderDialog::markAsUnreadMsg()
|
|
||||||
{
|
|
||||||
QList<QTreeWidgetItem*> selectedItems = ui->msgTreeWidget->selectedItems();
|
|
||||||
setMsgAsReadUnread(selectedItems, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FeedReaderDialog::markAllAsReadMsg()
|
|
||||||
{
|
|
||||||
QList<QTreeWidgetItem*> items;
|
|
||||||
|
|
||||||
QTreeWidgetItemIterator it(ui->msgTreeWidget);
|
|
||||||
QTreeWidgetItem *item;
|
|
||||||
while ((item = *it) != NULL) {
|
|
||||||
if (!item->isHidden()) {
|
|
||||||
items.push_back(item);
|
|
||||||
}
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
setMsgAsReadUnread(items, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FeedReaderDialog::copyLinksMsg()
|
|
||||||
{
|
|
||||||
QString links;
|
|
||||||
|
|
||||||
QTreeWidgetItemIterator it(ui->msgTreeWidget, QTreeWidgetItemIterator::Selected);
|
|
||||||
QTreeWidgetItem *item;
|
|
||||||
while ((item = *it) != NULL) {
|
|
||||||
QString link = item->data(COLUMN_MSG_DATA, ROLE_MSG_LINK).toString();
|
|
||||||
if (!link.isEmpty()) {
|
|
||||||
links += link + "\n";
|
|
||||||
}
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (links.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QApplication::clipboard()->setText(links);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FeedReaderDialog::removeMsg()
|
|
||||||
{
|
|
||||||
std::string feedId = currentFeedId();
|
|
||||||
if (feedId.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<QTreeWidgetItem*> selectedItems = ui->msgTreeWidget->selectedItems();
|
|
||||||
QList<QTreeWidgetItem*>::iterator it;
|
|
||||||
std::list<std::string> msgIds;
|
|
||||||
|
|
||||||
for (it = selectedItems.begin(); it != selectedItems.end(); ++it) {
|
|
||||||
msgIds.push_back((*it)->data(COLUMN_MSG_DATA, ROLE_MSG_ID).toString().toStdString());
|
|
||||||
}
|
|
||||||
mFeedReader->removeMsgs(feedId, msgIds);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FeedReaderDialog::copyLinkMsg()
|
|
||||||
{
|
|
||||||
QTreeWidgetItem *item = ui->msgTreeWidget->currentItem();
|
|
||||||
if (!item) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString link = item->data(COLUMN_MSG_DATA, ROLE_MSG_LINK).toString();
|
|
||||||
if (link.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QApplication::clipboard()->setText(link);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FeedReaderDialog::openLinkMsg()
|
|
||||||
{
|
|
||||||
QTreeWidgetItem *item = ui->msgTreeWidget->currentItem();
|
|
||||||
if (!item) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString link = item->data(COLUMN_MSG_DATA, ROLE_MSG_LINK).toString();
|
|
||||||
if (link.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QDesktopServices::openUrl(QUrl(link));
|
|
||||||
}
|
|
||||||
|
@ -33,6 +33,7 @@ class QTreeWidgetItem;
|
|||||||
class RsFeedReader;
|
class RsFeedReader;
|
||||||
class RSTreeWidgetItemCompareRole;
|
class RSTreeWidgetItemCompareRole;
|
||||||
class FeedReaderNotify;
|
class FeedReaderNotify;
|
||||||
|
class FeedReaderMessageWidget;
|
||||||
|
|
||||||
class FeedReaderDialog : public MainPage
|
class FeedReaderDialog : public MainPage
|
||||||
{
|
{
|
||||||
@ -50,52 +51,37 @@ protected:
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void feedTreeCustomPopupMenu(QPoint point);
|
void feedTreeCustomPopupMenu(QPoint point);
|
||||||
void msgTreeCustomPopupMenu(QPoint point);
|
|
||||||
void feedItemChanged(QTreeWidgetItem *item);
|
void feedItemChanged(QTreeWidgetItem *item);
|
||||||
void msgItemChanged();
|
|
||||||
void msgItemClicked(QTreeWidgetItem *item, int column);
|
|
||||||
void filterColumnChanged(int column);
|
|
||||||
void filterItems(const QString &text);
|
|
||||||
void toggleMsgText();
|
|
||||||
void newFolder();
|
void newFolder();
|
||||||
void newFeed();
|
void newFeed();
|
||||||
void removeFeed();
|
void removeFeed();
|
||||||
void editFeed();
|
void editFeed();
|
||||||
void activateFeed();
|
void activateFeed();
|
||||||
void processFeed();
|
void processFeed();
|
||||||
void markAsReadMsg();
|
|
||||||
void markAsUnreadMsg();
|
void messageTabCloseRequested(int index);
|
||||||
void markAllAsReadMsg();
|
void messageTabChanged(QWidget *widget);
|
||||||
void copyLinksMsg();
|
|
||||||
void removeMsg();
|
|
||||||
void openLinkMsg();
|
|
||||||
void copyLinkMsg();
|
|
||||||
|
|
||||||
/* FeedReaderNotify */
|
/* FeedReaderNotify */
|
||||||
void feedChanged(const QString &feedId, int type);
|
void feedChanged(const QString &feedId, int type);
|
||||||
void msgChanged(const QString &feedId, const QString &msgId, int type);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string currentFeedId();
|
std::string currentFeedId();
|
||||||
std::string currentMsgId();
|
|
||||||
void processSettings(bool load);
|
void processSettings(bool load);
|
||||||
|
void addFeedToExpand(const std::string &feedId);
|
||||||
|
void getExpandedFeedIds(QList<std::string> &feedIds);
|
||||||
void updateFeeds(const std::string &parentId, QTreeWidgetItem *parentItem);
|
void updateFeeds(const std::string &parentId, QTreeWidgetItem *parentItem);
|
||||||
void updateFeedItem(QTreeWidgetItem *item, FeedInfo &info);
|
void updateFeedItem(QTreeWidgetItem *item, FeedInfo &info);
|
||||||
void updateMsgs(const std::string &feedId);
|
|
||||||
void calculateMsgIconsAndFonts(QTreeWidgetItem *item);
|
|
||||||
void updateMsgItem(QTreeWidgetItem *item, FeedMsgInfo &info);
|
|
||||||
void setMsgAsReadUnread(QList<QTreeWidgetItem*> &rows, bool read);
|
|
||||||
void filterItem(QTreeWidgetItem *item, const QString &text, int filterColumn);
|
|
||||||
void filterItem(QTreeWidgetItem *item);
|
|
||||||
void toggleMsgText_internal();
|
|
||||||
|
|
||||||
void calculateFeedItems();
|
void calculateFeedItems();
|
||||||
void calculateFeedItem(QTreeWidgetItem *item, uint32_t &unreadCount, bool &loading);
|
void calculateFeedItem(QTreeWidgetItem *item, uint32_t &unreadCount, bool &loading);
|
||||||
|
|
||||||
|
FeedReaderMessageWidget *feedMessageWidget(const std::string &id);
|
||||||
|
|
||||||
bool mProcessSettings;
|
bool mProcessSettings;
|
||||||
|
QList<std::string> *mOpenFeedIds;
|
||||||
QTreeWidgetItem *mRootItem;
|
QTreeWidgetItem *mRootItem;
|
||||||
RSTreeWidgetItemCompareRole *mFeedCompareRole;
|
RSTreeWidgetItemCompareRole *mFeedCompareRole;
|
||||||
RSTreeWidgetItemCompareRole *mMsgCompareRole;
|
|
||||||
|
|
||||||
// gui interface
|
// gui interface
|
||||||
RsFeedReader *mFeedReader;
|
RsFeedReader *mFeedReader;
|
||||||
|
@ -86,7 +86,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QTreeWidget" name="feedTreeWidget">
|
<widget class="RSTreeWidget" name="feedTreeWidget">
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
<pointsize>9</pointsize>
|
<pointsize>9</pointsize>
|
||||||
@ -113,171 +113,13 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QSplitter" name="msgSplitter">
|
<widget class="QTabWidget" name="messageTabWidget">
|
||||||
<property name="orientation">
|
<property name="tabsClosable">
|
||||||
<enum>Qt::Vertical</enum>
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="movable">
|
||||||
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="layoutWidget">
|
|
||||||
<layout class="QGridLayout" name="msgFrame">
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QFrame" name="toolBarFrame">
|
|
||||||
<property name="frameShape">
|
|
||||||
<enum>QFrame::Box</enum>
|
|
||||||
</property>
|
|
||||||
<property name="frameShadow">
|
|
||||||
<enum>QFrame::Sunken</enum>
|
|
||||||
</property>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
|
||||||
<property name="margin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<widget class="LineEditClear" name="filterLineEdit">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Search forums</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0">
|
|
||||||
<widget class="QTreeWidget" name="msgTreeWidget">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<pointsize>9</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="contextMenuPolicy">
|
|
||||||
<enum>Qt::CustomContextMenu</enum>
|
|
||||||
</property>
|
|
||||||
<property name="editTriggers">
|
|
||||||
<set>QAbstractItemView::NoEditTriggers</set>
|
|
||||||
</property>
|
|
||||||
<property name="selectionMode">
|
|
||||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sortingEnabled">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="allColumnsShowFocus">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<column>
|
|
||||||
<property name="text">
|
|
||||||
<string>Title</string>
|
|
||||||
</property>
|
|
||||||
</column>
|
|
||||||
<column>
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset resource="../../../retroshare-gui/src/gui/images.qrc">
|
|
||||||
<normaloff>:/images/message-state-header.png</normaloff>:/images/message-state-header.png</iconset>
|
|
||||||
</property>
|
|
||||||
</column>
|
|
||||||
<column>
|
|
||||||
<property name="text">
|
|
||||||
<string>Date</string>
|
|
||||||
</property>
|
|
||||||
</column>
|
|
||||||
<column>
|
|
||||||
<property name="text">
|
|
||||||
<string>Author</string>
|
|
||||||
</property>
|
|
||||||
</column>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="0">
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="msgLabel">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<pointsize>10</pointsize>
|
|
||||||
<weight>75</weight>
|
|
||||||
<bold>true</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Message:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="msgTitle">
|
|
||||||
<property name="wordWrap">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="textInteractionFlags">
|
|
||||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QToolButton" name="linkButton">
|
|
||||||
<property name="icon">
|
|
||||||
<iconset resource="FeedReader_images.qrc">
|
|
||||||
<normaloff>:/images/Link.png</normaloff>:/images/Link.png</iconset>
|
|
||||||
</property>
|
|
||||||
<property name="popupMode">
|
|
||||||
<enum>QToolButton::MenuButtonPopup</enum>
|
|
||||||
</property>
|
|
||||||
<property name="autoRaise">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="expandButton">
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>24</width>
|
|
||||||
<height>24</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="focusPolicy">
|
|
||||||
<enum>Qt::NoFocus</enum>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset resource="../../../retroshare-gui/src/gui/images.qrc">
|
|
||||||
<normaloff>:/images/edit_remove24.png</normaloff>:/images/edit_remove24.png</iconset>
|
|
||||||
</property>
|
|
||||||
<property name="checkable">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="checked">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<widget class="LinkTextBrowser" name="msgText">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>10</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<pointsize>9</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -285,19 +127,13 @@
|
|||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>LineEditClear</class>
|
<class>RSTreeWidget</class>
|
||||||
<extends>QLineEdit</extends>
|
<extends>QTreeWidget</extends>
|
||||||
<header>gui/common/LineEditClear.h</header>
|
<header>gui/common/RSTreeWidget.h</header>
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>LinkTextBrowser</class>
|
|
||||||
<extends>QTextBrowser</extends>
|
|
||||||
<header>gui/common/LinkTextBrowser.h</header>
|
|
||||||
</customwidget>
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="FeedReader_images.qrc"/>
|
<include location="FeedReader_images.qrc"/>
|
||||||
<include location="../../../retroshare-gui/src/gui/images.qrc"/>
|
|
||||||
</resources>
|
</resources>
|
||||||
<connections/>
|
<connections/>
|
||||||
</ui>
|
</ui>
|
||||||
|
688
plugins/FeedReader/gui/FeedReaderMessageWidget.cpp
Normal file
688
plugins/FeedReader/gui/FeedReaderMessageWidget.cpp
Normal file
@ -0,0 +1,688 @@
|
|||||||
|
#include <QDateTime>
|
||||||
|
#include <QMenu>
|
||||||
|
#include <QKeyEvent>
|
||||||
|
#include <QClipboard>
|
||||||
|
#include <QDesktopServices>
|
||||||
|
|
||||||
|
#include "FeedReaderMessageWidget.h"
|
||||||
|
#include "ui_FeedReaderMessageWidget.h"
|
||||||
|
#include "FeedReaderNotify.h"
|
||||||
|
|
||||||
|
#include "gui/common/RSTreeWidgetItem.h"
|
||||||
|
#include "gui/settings/rsharesettings.h"
|
||||||
|
#include "util/HandleRichText.h"
|
||||||
|
|
||||||
|
#include "interface/rsFeedReader.h"
|
||||||
|
#include "retroshare/rsiface.h"
|
||||||
|
|
||||||
|
#define COLUMN_MSG_COUNT 4
|
||||||
|
#define COLUMN_MSG_TITLE 0
|
||||||
|
#define COLUMN_MSG_READ 1
|
||||||
|
#define COLUMN_MSG_PUBDATE 2
|
||||||
|
#define COLUMN_MSG_AUTHOR 3
|
||||||
|
#define COLUMN_MSG_DATA 0
|
||||||
|
|
||||||
|
#define ROLE_MSG_ID Qt::UserRole
|
||||||
|
#define ROLE_MSG_SORT Qt::UserRole + 1
|
||||||
|
#define ROLE_MSG_NEW Qt::UserRole + 2
|
||||||
|
#define ROLE_MSG_READ Qt::UserRole + 3
|
||||||
|
#define ROLE_MSG_LINK Qt::UserRole + 4
|
||||||
|
|
||||||
|
FeedReaderMessageWidget::FeedReaderMessageWidget(const std::string &feedId, RsFeedReader *feedReader, FeedReaderNotify *notify, QWidget *parent) :
|
||||||
|
QWidget(parent), mFeedId(feedId), mFeedReader(feedReader), mNotify(notify), ui(new Ui::FeedReaderMessageWidget)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
mProcessSettings = false;
|
||||||
|
mUnreadCount = 0;
|
||||||
|
|
||||||
|
/* connect signals */
|
||||||
|
connect(mNotify, SIGNAL(notifyFeedChanged(QString,int)), this, SLOT(feedChanged(QString,int)));
|
||||||
|
connect(mNotify, SIGNAL(notifyMsgChanged(QString,QString,int)), this, SLOT(msgChanged(QString,QString,int)));
|
||||||
|
|
||||||
|
connect(ui->msgTreeWidget, SIGNAL(itemSelectionChanged()), this, SLOT(msgItemChanged()));
|
||||||
|
connect(ui->msgTreeWidget, SIGNAL(itemClicked(QTreeWidgetItem*,int)), this, SLOT(msgItemClicked(QTreeWidgetItem*,int)));
|
||||||
|
|
||||||
|
connect(ui->msgTreeWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(msgTreeCustomPopupMenu(QPoint)));
|
||||||
|
|
||||||
|
connect(ui->filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterItems(QString)));
|
||||||
|
connect(ui->filterLineEdit, SIGNAL(filterChanged(int)), this, SLOT(filterColumnChanged(int)));
|
||||||
|
|
||||||
|
connect(ui->linkButton, SIGNAL(clicked()), this, SLOT(openLinkMsg()));
|
||||||
|
connect(ui->expandButton, SIGNAL(clicked()), this, SLOT(toggleMsgText()));
|
||||||
|
|
||||||
|
mMsgCompareRole = new RSTreeWidgetItemCompareRole;
|
||||||
|
mMsgCompareRole->setRole(COLUMN_MSG_TITLE, ROLE_MSG_SORT);
|
||||||
|
mMsgCompareRole->setRole(COLUMN_MSG_READ, ROLE_MSG_SORT);
|
||||||
|
mMsgCompareRole->setRole(COLUMN_MSG_PUBDATE, ROLE_MSG_SORT);
|
||||||
|
mMsgCompareRole->setRole(COLUMN_MSG_AUTHOR, ROLE_MSG_SORT);
|
||||||
|
|
||||||
|
/* initialize msg list */
|
||||||
|
ui->msgTreeWidget->sortItems(COLUMN_MSG_PUBDATE, Qt::DescendingOrder);
|
||||||
|
|
||||||
|
/* set header resize modes and initial section sizes */
|
||||||
|
QHeaderView *header = ui->msgTreeWidget->header();
|
||||||
|
header->setResizeMode(COLUMN_MSG_TITLE, QHeaderView::Interactive);
|
||||||
|
header->resizeSection(COLUMN_MSG_TITLE, 350);
|
||||||
|
header->resizeSection(COLUMN_MSG_PUBDATE, 140);
|
||||||
|
header->resizeSection(COLUMN_MSG_AUTHOR, 150);
|
||||||
|
|
||||||
|
/* set text of column "Read" to empty - without this the column has a number as header text */
|
||||||
|
QTreeWidgetItem *headerItem = ui->msgTreeWidget->headerItem();
|
||||||
|
headerItem->setText(COLUMN_MSG_READ, "");
|
||||||
|
|
||||||
|
/* add filter actions */
|
||||||
|
ui->filterLineEdit->addFilter(QIcon(), tr("Title"), COLUMN_MSG_TITLE, tr("Search Title"));
|
||||||
|
ui->filterLineEdit->addFilter(QIcon(), tr("Date"), COLUMN_MSG_PUBDATE, tr("Search Date"));
|
||||||
|
ui->filterLineEdit->addFilter(QIcon(), tr("Author"), COLUMN_MSG_AUTHOR, tr("Search Author"));
|
||||||
|
ui->filterLineEdit->setCurrentFilter(COLUMN_MSG_TITLE);
|
||||||
|
|
||||||
|
/* load settings */
|
||||||
|
processSettings(true);
|
||||||
|
|
||||||
|
/* Set header sizes for the fixed columns and resize modes, must be set after processSettings */
|
||||||
|
header->resizeSection(COLUMN_MSG_READ, 24);
|
||||||
|
header->setResizeMode(COLUMN_MSG_READ, QHeaderView::Fixed);
|
||||||
|
|
||||||
|
/* build menu for link button */
|
||||||
|
QMenu *menu = new QMenu(this);
|
||||||
|
QAction *action = menu->addAction(tr("Open link in browser"), this, SLOT(openLinkMsg()));
|
||||||
|
menu->addAction(tr("Copy link to clipboard"), this, SLOT(copyLinkMsg()));
|
||||||
|
|
||||||
|
QFont font = action->font();
|
||||||
|
font.setBold(true);
|
||||||
|
action->setFont(font);
|
||||||
|
|
||||||
|
ui->linkButton->setMenu(menu);
|
||||||
|
ui->linkButton->setEnabled(false);
|
||||||
|
|
||||||
|
ui->msgTreeWidget->installEventFilter(this);
|
||||||
|
|
||||||
|
FeedInfo feedInfo;
|
||||||
|
if (mFeedReader->getFeedInfo(mFeedId, feedInfo)) {
|
||||||
|
mFeedName = QString::fromUtf8(feedInfo.name.c_str());
|
||||||
|
|
||||||
|
mFeedReader->getMessageCount(mFeedId, NULL, NULL, &mUnreadCount);
|
||||||
|
} else {
|
||||||
|
mFeedId.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
updateMsgs();
|
||||||
|
}
|
||||||
|
|
||||||
|
FeedReaderMessageWidget::~FeedReaderMessageWidget()
|
||||||
|
{
|
||||||
|
/* save settings */
|
||||||
|
processSettings(false);
|
||||||
|
|
||||||
|
delete(mMsgCompareRole);
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FeedReaderMessageWidget::processSettings(bool load)
|
||||||
|
{
|
||||||
|
mProcessSettings = true;
|
||||||
|
Settings->beginGroup(QString("FeedReaderDialog"));
|
||||||
|
|
||||||
|
QHeaderView *header = ui->msgTreeWidget->header ();
|
||||||
|
|
||||||
|
if (load) {
|
||||||
|
// load settings
|
||||||
|
|
||||||
|
// expandButton
|
||||||
|
bool value = Settings->value("expandButton", true).toBool();
|
||||||
|
ui->expandButton->setChecked(value);
|
||||||
|
toggleMsgText_internal();
|
||||||
|
|
||||||
|
// filterColumn
|
||||||
|
ui->filterLineEdit->setCurrentFilter(Settings->value("filterColumn", COLUMN_MSG_TITLE).toInt());
|
||||||
|
|
||||||
|
// state of thread tree
|
||||||
|
header->restoreState(Settings->value("msgTree").toByteArray());
|
||||||
|
|
||||||
|
// state of splitter
|
||||||
|
ui->msgSplitter->restoreState(Settings->value("msgSplitter").toByteArray());
|
||||||
|
} else {
|
||||||
|
// save settings
|
||||||
|
|
||||||
|
// state of thread tree
|
||||||
|
Settings->setValue("msgTree", header->saveState());
|
||||||
|
|
||||||
|
// state of splitter
|
||||||
|
Settings->setValue("msgSplitter", ui->msgSplitter->saveState());
|
||||||
|
}
|
||||||
|
|
||||||
|
Settings->endGroup();
|
||||||
|
mProcessSettings = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FeedReaderMessageWidget::showEvent(QShowEvent */*event*/)
|
||||||
|
{
|
||||||
|
updateMsgs();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FeedReaderMessageWidget::eventFilter(QObject *obj, QEvent *event)
|
||||||
|
{
|
||||||
|
if (obj == ui->msgTreeWidget) {
|
||||||
|
if (event->type() == QEvent::KeyPress) {
|
||||||
|
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
|
||||||
|
if (keyEvent) {
|
||||||
|
if (keyEvent->key() == Qt::Key_Space) {
|
||||||
|
/* Space pressed */
|
||||||
|
QTreeWidgetItem *item = ui->msgTreeWidget->currentItem();
|
||||||
|
msgItemClicked(item, COLUMN_MSG_READ);
|
||||||
|
return true; // eat event
|
||||||
|
}
|
||||||
|
if (keyEvent->key() == Qt::Key_Delete) {
|
||||||
|
/* Delete pressed */
|
||||||
|
removeMsg();
|
||||||
|
return true; // eat event
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* pass the event on to the parent class */
|
||||||
|
return QWidget::eventFilter(obj, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString FeedReaderMessageWidget::feedName(bool withUnreadCount)
|
||||||
|
{
|
||||||
|
QString name = mFeedName.isEmpty() ? tr("No name") : mFeedName;
|
||||||
|
|
||||||
|
if (withUnreadCount && mUnreadCount) {
|
||||||
|
name += QString(" (%1)").arg(mUnreadCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
QIcon FeedReaderMessageWidget::feedIcon()
|
||||||
|
{
|
||||||
|
// if (mThreadQueue->activeRequestExist(TOKEN_TYPE_CURRENTFORUM) || mFillThread) {
|
||||||
|
// return QIcon(":/images/kalarm.png");
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (mNewCount) {
|
||||||
|
// return QIcon(":/images/message-state-new.png");
|
||||||
|
// }
|
||||||
|
|
||||||
|
return QIcon();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string FeedReaderMessageWidget::currentMsgId()
|
||||||
|
{
|
||||||
|
QTreeWidgetItem *item = ui->msgTreeWidget->currentItem();
|
||||||
|
if (!item) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return item->data(COLUMN_MSG_DATA, ROLE_MSG_ID).toString().toStdString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FeedReaderMessageWidget::msgTreeCustomPopupMenu(QPoint /*point*/)
|
||||||
|
{
|
||||||
|
QMenu contextMnu(this);
|
||||||
|
|
||||||
|
QList<QTreeWidgetItem*> selectedItems = ui->msgTreeWidget->selectedItems();
|
||||||
|
|
||||||
|
QAction *action = contextMnu.addAction(QIcon(""), tr("Mark as read"), this, SLOT(markAsReadMsg()));
|
||||||
|
action->setEnabled(!selectedItems.empty());
|
||||||
|
|
||||||
|
action = contextMnu.addAction(QIcon(""), tr("Mark as unread"), this, SLOT(markAsUnreadMsg()));
|
||||||
|
action->setEnabled(!selectedItems.empty());
|
||||||
|
|
||||||
|
action = contextMnu.addAction(QIcon(""), tr("Mark all as read"), this, SLOT(markAllAsReadMsg()));
|
||||||
|
|
||||||
|
contextMnu.addSeparator();
|
||||||
|
|
||||||
|
action = contextMnu.addAction(QIcon(""), tr("Copy link"), this, SLOT(copyLinskMsg()));
|
||||||
|
action->setEnabled(!selectedItems.empty());
|
||||||
|
|
||||||
|
action = contextMnu.addAction(QIcon(""), tr("Remove"), this, SLOT(removeMsg()));
|
||||||
|
action->setEnabled(!selectedItems.empty());
|
||||||
|
|
||||||
|
contextMnu.exec(QCursor::pos());
|
||||||
|
}
|
||||||
|
|
||||||
|
void FeedReaderMessageWidget::updateMsgs()
|
||||||
|
{
|
||||||
|
if (mFeedId.empty()) {
|
||||||
|
ui->msgTreeWidget->clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::list<FeedMsgInfo> msgInfos;
|
||||||
|
if (!mFeedReader->getFeedMsgList(mFeedId, msgInfos)) {
|
||||||
|
ui->msgTreeWidget->clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
QTreeWidgetItem *item;
|
||||||
|
std::list<FeedMsgInfo>::iterator msgIt;
|
||||||
|
|
||||||
|
/* update existing and delete not existing msgs */
|
||||||
|
while (index < ui->msgTreeWidget->topLevelItemCount()) {
|
||||||
|
item = ui->msgTreeWidget->topLevelItem(index);
|
||||||
|
std::string msgId = item->data(COLUMN_MSG_DATA, ROLE_MSG_ID).toString().toStdString();
|
||||||
|
|
||||||
|
/* search existing msg */
|
||||||
|
int found = -1;
|
||||||
|
for (msgIt = msgInfos.begin (); msgIt != msgInfos.end (); ++msgIt) {
|
||||||
|
if (msgIt->msgId == msgId) {
|
||||||
|
/* found it, update it */
|
||||||
|
updateMsgItem(item, *msgIt);
|
||||||
|
|
||||||
|
msgInfos.erase(msgIt);
|
||||||
|
found = index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (found >= 0) {
|
||||||
|
++index;
|
||||||
|
} else {
|
||||||
|
delete(ui->msgTreeWidget->takeTopLevelItem(index));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add new msgs */
|
||||||
|
for (msgIt = msgInfos.begin (); msgIt != msgInfos.end (); ++msgIt) {
|
||||||
|
item = new RSTreeWidgetItem(mMsgCompareRole);
|
||||||
|
updateMsgItem(item, *msgIt);
|
||||||
|
ui->msgTreeWidget->addTopLevelItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
filterItems(ui->filterLineEdit->text());
|
||||||
|
}
|
||||||
|
|
||||||
|
void FeedReaderMessageWidget::calculateMsgIconsAndFonts(QTreeWidgetItem *item)
|
||||||
|
{
|
||||||
|
if (!item) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isnew = item->data(COLUMN_MSG_DATA, ROLE_MSG_NEW).toBool();
|
||||||
|
bool read = item->data(COLUMN_MSG_DATA, ROLE_MSG_READ).toBool();
|
||||||
|
|
||||||
|
if (read) {
|
||||||
|
item->setIcon(COLUMN_MSG_READ, QIcon(":/images/message-state-read.png"));
|
||||||
|
} else {
|
||||||
|
item->setIcon(COLUMN_MSG_READ, QIcon(":/images/message-state-unread.png"));
|
||||||
|
}
|
||||||
|
if (isnew) {
|
||||||
|
item->setIcon(COLUMN_MSG_TITLE, QIcon(":/images/message-state-new.png"));
|
||||||
|
} else {
|
||||||
|
item->setIcon(COLUMN_MSG_TITLE, QIcon());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < COLUMN_MSG_COUNT; i++) {
|
||||||
|
QFont font = item->font(i);
|
||||||
|
font.setBold(isnew || !read);
|
||||||
|
item->setFont(i, font);
|
||||||
|
}
|
||||||
|
|
||||||
|
item->setData(COLUMN_MSG_READ, ROLE_MSG_SORT, QString("%1_%2_%3").arg(QString(isnew ? "1" : "0"), QString(read ? "0" : "1"), item->data(COLUMN_MSG_TITLE, ROLE_MSG_SORT).toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FeedReaderMessageWidget::updateMsgItem(QTreeWidgetItem *item, FeedMsgInfo &info)
|
||||||
|
{
|
||||||
|
QString title = QString::fromUtf8(info.title.c_str());
|
||||||
|
QDateTime qdatetime;
|
||||||
|
qdatetime.setTime_t(info.pubDate);
|
||||||
|
|
||||||
|
/* add string to all data */
|
||||||
|
QString sort = QString("%1_%2_%2").arg(title, qdatetime.toString("yyyyMMdd_hhmmss"), QString::fromStdString(info.feedId));
|
||||||
|
|
||||||
|
item->setText(COLUMN_MSG_TITLE, title);
|
||||||
|
item->setData(COLUMN_MSG_TITLE, ROLE_MSG_SORT, sort);
|
||||||
|
|
||||||
|
QString author = QString::fromUtf8(info.author.c_str());
|
||||||
|
item->setText(COLUMN_MSG_AUTHOR, author);
|
||||||
|
item->setData(COLUMN_MSG_AUTHOR, ROLE_MSG_SORT, author + "_" + sort);
|
||||||
|
|
||||||
|
/* if the message is on same date show only time */
|
||||||
|
if (qdatetime.daysTo(QDateTime::currentDateTime()) == 0) {
|
||||||
|
item->setData(COLUMN_MSG_PUBDATE, Qt::DisplayRole, qdatetime.time());
|
||||||
|
} else {
|
||||||
|
item->setData(COLUMN_MSG_PUBDATE, Qt::DisplayRole, qdatetime);
|
||||||
|
}
|
||||||
|
item->setData(COLUMN_MSG_PUBDATE, ROLE_MSG_SORT, QString("%1_%2_%3").arg(qdatetime.toString("yyyyMMdd_hhmmss"), title, QString::fromStdString(info.msgId)));
|
||||||
|
|
||||||
|
item->setData(COLUMN_MSG_DATA, ROLE_MSG_ID, QString::fromStdString(info.msgId));
|
||||||
|
item->setData(COLUMN_MSG_DATA, ROLE_MSG_LINK, QString::fromUtf8(info.link.c_str()));
|
||||||
|
item->setData(COLUMN_MSG_DATA, ROLE_MSG_READ, info.flag.read);
|
||||||
|
item->setData(COLUMN_MSG_DATA, ROLE_MSG_NEW, info.flag.isnew);
|
||||||
|
|
||||||
|
calculateMsgIconsAndFonts(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FeedReaderMessageWidget::feedChanged(const QString &feedId, int type)
|
||||||
|
{
|
||||||
|
if (feedId.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (feedId.toStdString() != mFeedId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == NOTIFY_TYPE_DEL) {
|
||||||
|
deleteLater();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == NOTIFY_TYPE_MOD) {
|
||||||
|
FeedInfo feedInfo;
|
||||||
|
if (!mFeedReader->getFeedInfo(mFeedId, feedInfo)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString name = QString::fromUtf8(feedInfo.name.c_str());
|
||||||
|
if (name != mFeedName) {
|
||||||
|
mFeedName = name;
|
||||||
|
emit feedMessageChanged(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FeedReaderMessageWidget::msgChanged(const QString &feedId, const QString &msgId, int type)
|
||||||
|
{
|
||||||
|
if (feedId.isEmpty() || msgId.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (feedId.toStdString() != mFeedId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t unreadCount;
|
||||||
|
mFeedReader->getMessageCount(mFeedId, NULL, NULL, &unreadCount);
|
||||||
|
if (unreadCount != mUnreadCount) {
|
||||||
|
mUnreadCount = unreadCount;
|
||||||
|
emit feedMessageChanged(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isVisible()) {
|
||||||
|
/* complete update in showEvent */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FeedMsgInfo msgInfo;
|
||||||
|
if (type != NOTIFY_TYPE_DEL) {
|
||||||
|
if (!mFeedReader->getMsgInfo(feedId.toStdString(), msgId.toStdString(), msgInfo)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == NOTIFY_TYPE_MOD || type == NOTIFY_TYPE_DEL) {
|
||||||
|
QTreeWidgetItemIterator it(ui->msgTreeWidget);
|
||||||
|
QTreeWidgetItem *item;
|
||||||
|
while ((item = *it) != NULL) {
|
||||||
|
if (item->data(COLUMN_MSG_DATA, ROLE_MSG_ID).toString() == msgId) {
|
||||||
|
if (type == NOTIFY_TYPE_MOD) {
|
||||||
|
updateMsgItem(item, msgInfo);
|
||||||
|
filterItem(item);
|
||||||
|
} else {
|
||||||
|
delete(item);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == NOTIFY_TYPE_ADD) {
|
||||||
|
QTreeWidgetItem *item = new RSTreeWidgetItem(mMsgCompareRole);
|
||||||
|
updateMsgItem(item, msgInfo);
|
||||||
|
ui->msgTreeWidget->addTopLevelItem(item);
|
||||||
|
filterItem(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FeedReaderMessageWidget::msgItemClicked(QTreeWidgetItem *item, int column)
|
||||||
|
{
|
||||||
|
if (item == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (column == COLUMN_MSG_READ) {
|
||||||
|
QList<QTreeWidgetItem*> rows;
|
||||||
|
rows.append(item);
|
||||||
|
bool read = item->data(COLUMN_MSG_DATA, ROLE_MSG_READ).toBool();
|
||||||
|
setMsgAsReadUnread(rows, !read);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FeedReaderMessageWidget::msgItemChanged()
|
||||||
|
{
|
||||||
|
long todo; // show link somewhere
|
||||||
|
|
||||||
|
std::string msgId = currentMsgId();
|
||||||
|
|
||||||
|
if (mFeedId.empty() || msgId.empty()) {
|
||||||
|
ui->msgTitle->clear();
|
||||||
|
// ui->msgLink->clear();
|
||||||
|
ui->msgText->clear();
|
||||||
|
ui->linkButton->setEnabled(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTreeWidgetItem *item = ui->msgTreeWidget->currentItem();
|
||||||
|
if (!item) {
|
||||||
|
/* there is something wrong */
|
||||||
|
ui->msgTitle->clear();
|
||||||
|
// ui->msgLink->clear();
|
||||||
|
ui->msgText->clear();
|
||||||
|
ui->linkButton->setEnabled(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get msg */
|
||||||
|
FeedMsgInfo msgInfo;
|
||||||
|
if (!mFeedReader->getMsgInfo(mFeedId, msgId, msgInfo)) {
|
||||||
|
ui->msgTitle->clear();
|
||||||
|
// ui->msgLink->clear();
|
||||||
|
ui->msgText->clear();
|
||||||
|
ui->linkButton->setEnabled(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool setToReadOnActive = Settings->valueFromGroup("FeedReaderDialog", "SetMsgToReadOnActivate", true).toBool();
|
||||||
|
bool isnew = item->data(COLUMN_MSG_DATA, ROLE_MSG_NEW).toBool();
|
||||||
|
bool read = item->data(COLUMN_MSG_DATA, ROLE_MSG_READ).toBool();
|
||||||
|
|
||||||
|
QList<QTreeWidgetItem*> row;
|
||||||
|
row.append(item);
|
||||||
|
if (read) {
|
||||||
|
if (isnew) {
|
||||||
|
/* something wrong, but set as read again to clear the new flag */
|
||||||
|
setMsgAsReadUnread(row, true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* set to read/unread */
|
||||||
|
setMsgAsReadUnread(row, setToReadOnActive);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString msgTxt = RsHtml().formatText(ui->msgText->document(), QString::fromUtf8(msgInfo.description.c_str()), RSHTML_FORMATTEXT_EMBED_LINKS);
|
||||||
|
|
||||||
|
ui->msgText->setHtml(msgTxt);
|
||||||
|
ui->msgTitle->setText(QString::fromUtf8(msgInfo.title.c_str()));
|
||||||
|
|
||||||
|
ui->linkButton->setEnabled(!msgInfo.link.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
void FeedReaderMessageWidget::setMsgAsReadUnread(QList<QTreeWidgetItem *> &rows, bool read)
|
||||||
|
{
|
||||||
|
QList<QTreeWidgetItem*>::iterator rowIt;
|
||||||
|
|
||||||
|
if (mFeedId.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (rowIt = rows.begin(); rowIt != rows.end(); rowIt++) {
|
||||||
|
QTreeWidgetItem *item = *rowIt;
|
||||||
|
bool rowRead = item->data(COLUMN_MSG_DATA, ROLE_MSG_READ).toBool();
|
||||||
|
bool rowNew = item->data(COLUMN_MSG_DATA, ROLE_MSG_NEW).toBool();
|
||||||
|
|
||||||
|
if (rowNew || read != rowRead) {
|
||||||
|
std::string msgId = item->data(COLUMN_MSG_DATA, ROLE_MSG_ID).toString().toStdString();
|
||||||
|
mFeedReader->setMessageRead(mFeedId, msgId, read);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FeedReaderMessageWidget::filterColumnChanged(int column)
|
||||||
|
{
|
||||||
|
if (mProcessSettings) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
filterItems(ui->filterLineEdit->text());
|
||||||
|
|
||||||
|
// save index
|
||||||
|
Settings->setValueToGroup("FeedReaderDialog", "filterColumn", column);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FeedReaderMessageWidget::filterItems(const QString& text)
|
||||||
|
{
|
||||||
|
int filterColumn = ui->filterLineEdit->currentFilter();
|
||||||
|
|
||||||
|
int count = ui->msgTreeWidget->topLevelItemCount();
|
||||||
|
for (int index = 0; index < count; ++index) {
|
||||||
|
filterItem(ui->msgTreeWidget->topLevelItem(index), text, filterColumn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FeedReaderMessageWidget::filterItem(QTreeWidgetItem *item, const QString &text, int filterColumn)
|
||||||
|
{
|
||||||
|
if (text.isEmpty() == false) {
|
||||||
|
if (item->text(filterColumn).contains(text, Qt::CaseInsensitive)) {
|
||||||
|
item->setHidden(false);
|
||||||
|
} else {
|
||||||
|
item->setHidden(true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
item->setHidden(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FeedReaderMessageWidget::filterItem(QTreeWidgetItem *item)
|
||||||
|
{
|
||||||
|
filterItem(item, ui->filterLineEdit->text(), ui->filterLineEdit->currentFilter());
|
||||||
|
}
|
||||||
|
|
||||||
|
void FeedReaderMessageWidget::toggleMsgText()
|
||||||
|
{
|
||||||
|
// save state of button
|
||||||
|
Settings->setValueToGroup("FeedReaderDialog", "expandButton", ui->expandButton->isChecked());
|
||||||
|
|
||||||
|
toggleMsgText_internal();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FeedReaderMessageWidget::toggleMsgText_internal()
|
||||||
|
{
|
||||||
|
if (ui->expandButton->isChecked()) {
|
||||||
|
ui->msgText->setVisible(true);
|
||||||
|
ui->expandButton->setIcon(QIcon(QString(":/images/edit_remove24.png")));
|
||||||
|
ui->expandButton->setToolTip(tr("Hide"));
|
||||||
|
} else {
|
||||||
|
ui->msgText->setVisible(false);
|
||||||
|
ui->expandButton->setIcon(QIcon(QString(":/images/edit_add24.png")));
|
||||||
|
ui->expandButton->setToolTip(tr("Expand"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FeedReaderMessageWidget::markAsReadMsg()
|
||||||
|
{
|
||||||
|
QList<QTreeWidgetItem*> selectedItems = ui->msgTreeWidget->selectedItems();
|
||||||
|
setMsgAsReadUnread(selectedItems, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FeedReaderMessageWidget::markAsUnreadMsg()
|
||||||
|
{
|
||||||
|
QList<QTreeWidgetItem*> selectedItems = ui->msgTreeWidget->selectedItems();
|
||||||
|
setMsgAsReadUnread(selectedItems, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FeedReaderMessageWidget::markAllAsReadMsg()
|
||||||
|
{
|
||||||
|
QList<QTreeWidgetItem*> items;
|
||||||
|
|
||||||
|
QTreeWidgetItemIterator it(ui->msgTreeWidget);
|
||||||
|
QTreeWidgetItem *item;
|
||||||
|
while ((item = *it) != NULL) {
|
||||||
|
if (!item->isHidden()) {
|
||||||
|
items.push_back(item);
|
||||||
|
}
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
setMsgAsReadUnread(items, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FeedReaderMessageWidget::copyLinksMsg()
|
||||||
|
{
|
||||||
|
QString links;
|
||||||
|
|
||||||
|
QTreeWidgetItemIterator it(ui->msgTreeWidget, QTreeWidgetItemIterator::Selected);
|
||||||
|
QTreeWidgetItem *item;
|
||||||
|
while ((item = *it) != NULL) {
|
||||||
|
QString link = item->data(COLUMN_MSG_DATA, ROLE_MSG_LINK).toString();
|
||||||
|
if (!link.isEmpty()) {
|
||||||
|
links += link + "\n";
|
||||||
|
}
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (links.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QApplication::clipboard()->setText(links);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FeedReaderMessageWidget::removeMsg()
|
||||||
|
{
|
||||||
|
if (mFeedId.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QTreeWidgetItem*> selectedItems = ui->msgTreeWidget->selectedItems();
|
||||||
|
QList<QTreeWidgetItem*>::iterator it;
|
||||||
|
std::list<std::string> msgIds;
|
||||||
|
|
||||||
|
for (it = selectedItems.begin(); it != selectedItems.end(); ++it) {
|
||||||
|
msgIds.push_back((*it)->data(COLUMN_MSG_DATA, ROLE_MSG_ID).toString().toStdString());
|
||||||
|
}
|
||||||
|
mFeedReader->removeMsgs(mFeedId, msgIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FeedReaderMessageWidget::copyLinkMsg()
|
||||||
|
{
|
||||||
|
QTreeWidgetItem *item = ui->msgTreeWidget->currentItem();
|
||||||
|
if (!item) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString link = item->data(COLUMN_MSG_DATA, ROLE_MSG_LINK).toString();
|
||||||
|
if (link.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QApplication::clipboard()->setText(link);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FeedReaderMessageWidget::openLinkMsg()
|
||||||
|
{
|
||||||
|
QTreeWidgetItem *item = ui->msgTreeWidget->currentItem();
|
||||||
|
if (!item) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString link = item->data(COLUMN_MSG_DATA, ROLE_MSG_LINK).toString();
|
||||||
|
if (link.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDesktopServices::openUrl(QUrl(link));
|
||||||
|
}
|
78
plugins/FeedReader/gui/FeedReaderMessageWidget.h
Normal file
78
plugins/FeedReader/gui/FeedReaderMessageWidget.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#ifndef FEEDREADERMESSAGEWIDGET_H
|
||||||
|
#define FEEDREADERMESSAGEWIDGET_H
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class FeedReaderMessageWidget;
|
||||||
|
}
|
||||||
|
|
||||||
|
class FeedMsgInfo;
|
||||||
|
class QTreeWidgetItem;
|
||||||
|
class RSTreeWidgetItemCompareRole;
|
||||||
|
class RsFeedReader;
|
||||||
|
class FeedReaderNotify;
|
||||||
|
|
||||||
|
class FeedReaderMessageWidget : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit FeedReaderMessageWidget(const std::string &feedId, RsFeedReader *feedReader, FeedReaderNotify *notify, QWidget *parent = 0);
|
||||||
|
~FeedReaderMessageWidget();
|
||||||
|
|
||||||
|
std::string feedId() { return mFeedId; }
|
||||||
|
QString feedName(bool withUnreadCount);
|
||||||
|
QIcon feedIcon();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void showEvent(QShowEvent *e);
|
||||||
|
bool eventFilter(QObject *obj, QEvent *ev);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void feedMessageChanged(QWidget *widget);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void msgTreeCustomPopupMenu(QPoint point);
|
||||||
|
void msgItemChanged();
|
||||||
|
void msgItemClicked(QTreeWidgetItem *item, int column);
|
||||||
|
void filterColumnChanged(int column);
|
||||||
|
void filterItems(const QString &text);
|
||||||
|
void toggleMsgText();
|
||||||
|
void markAsReadMsg();
|
||||||
|
void markAsUnreadMsg();
|
||||||
|
void markAllAsReadMsg();
|
||||||
|
void copyLinksMsg();
|
||||||
|
void removeMsg();
|
||||||
|
void openLinkMsg();
|
||||||
|
void copyLinkMsg();
|
||||||
|
|
||||||
|
/* FeedReaderNotify */
|
||||||
|
void feedChanged(const QString &feedId, int type);
|
||||||
|
void msgChanged(const QString &feedId, const QString &msgId, int type);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string currentMsgId();
|
||||||
|
void processSettings(bool load);
|
||||||
|
void updateMsgs();
|
||||||
|
void calculateMsgIconsAndFonts(QTreeWidgetItem *item);
|
||||||
|
void updateMsgItem(QTreeWidgetItem *item, FeedMsgInfo &info);
|
||||||
|
void setMsgAsReadUnread(QList<QTreeWidgetItem*> &rows, bool read);
|
||||||
|
void filterItem(QTreeWidgetItem *item, const QString &text, int filterColumn);
|
||||||
|
void filterItem(QTreeWidgetItem *item);
|
||||||
|
void toggleMsgText_internal();
|
||||||
|
|
||||||
|
bool mProcessSettings;
|
||||||
|
RSTreeWidgetItemCompareRole *mMsgCompareRole;
|
||||||
|
std::string mFeedId;
|
||||||
|
QString mFeedName;
|
||||||
|
unsigned int mUnreadCount;
|
||||||
|
|
||||||
|
// gui interface
|
||||||
|
RsFeedReader *mFeedReader;
|
||||||
|
FeedReaderNotify *mNotify;
|
||||||
|
|
||||||
|
Ui::FeedReaderMessageWidget *ui;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // FEEDREADERMESSAGEWIDGET_H
|
193
plugins/FeedReader/gui/FeedReaderMessageWidget.ui
Normal file
193
plugins/FeedReader/gui/FeedReaderMessageWidget.ui
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>FeedReaderMessageWidget</class>
|
||||||
|
<widget class="QWidget" name="FeedReaderMessageWidget">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>658</width>
|
||||||
|
<height>414</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="margin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QSplitter" name="msgSplitter">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="layoutWidget">
|
||||||
|
<layout class="QGridLayout" name="msgFrame">
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QFrame" name="toolBarFrame">
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::Box</enum>
|
||||||
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Sunken</enum>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||||
|
<property name="margin">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="LineEditClear" name="filterLineEdit">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Search forums</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QTreeWidget" name="msgTreeWidget">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>9</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="contextMenuPolicy">
|
||||||
|
<enum>Qt::CustomContextMenu</enum>
|
||||||
|
</property>
|
||||||
|
<property name="editTriggers">
|
||||||
|
<set>QAbstractItemView::NoEditTriggers</set>
|
||||||
|
</property>
|
||||||
|
<property name="selectionMode">
|
||||||
|
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sortingEnabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="allColumnsShowFocus">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Title</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../retroshare-gui/src/gui/images.qrc">
|
||||||
|
<normaloff>:/images/message-state-header.png</normaloff>:/images/message-state-header.png</iconset>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Date</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Author</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="msgTitle">
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="linkButton">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="FeedReader_images.qrc">
|
||||||
|
<normaloff>:/images/Link.png</normaloff>:/images/Link.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="popupMode">
|
||||||
|
<enum>QToolButton::MenuButtonPopup</enum>
|
||||||
|
</property>
|
||||||
|
<property name="autoRaise">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="expandButton">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>24</width>
|
||||||
|
<height>24</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../retroshare-gui/src/gui/images.qrc">
|
||||||
|
<normaloff>:/images/edit_remove24.png</normaloff>:/images/edit_remove24.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="LinkTextBrowser" name="msgText">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>10</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>9</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>LineEditClear</class>
|
||||||
|
<extends>QLineEdit</extends>
|
||||||
|
<header>gui/common/LineEditClear.h</header>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>LinkTextBrowser</class>
|
||||||
|
<extends>QTextBrowser</extends>
|
||||||
|
<header>gui/common/LinkTextBrowser.h</header>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
|
<resources>
|
||||||
|
<include location="FeedReader_images.qrc"/>
|
||||||
|
<include location="../../../retroshare-gui/src/gui/images.qrc"/>
|
||||||
|
</resources>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
Loading…
Reference in New Issue
Block a user