FeedReader:

- Added error handling to xml functions
- Added xslt transformation
- Added retransform of existing messages
- Redesigned preview dialog
- Enabled embed images for forum feeds
- Changed config format, switching back to an older version results in a loss of all data of the FeedReader

Added new base class RSPlainTextEdit with placeholder text.
New library libxslt needed

git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@6081 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
thunder2 2013-01-22 00:11:43 +00:00
parent 919fb3f62d
commit ef49000b9a
28 changed files with 1549 additions and 849 deletions

View file

@ -53,7 +53,6 @@ AddFeedDialog::AddFeedDialog(RsFeedReader *feedReader, FeedReaderNotify *notify,
/* currently only for loacl feeds */
connect(ui->saveCompletePageCheckBox, SIGNAL(toggled(bool)), this, SLOT(denyForumToggled()));
connect(ui->embedImagesCheckBox, SIGNAL(toggled(bool)), this, SLOT(denyForumToggled()));
connect(ui->urlLineEdit, SIGNAL(textChanged(QString)), this, SLOT(validate()));
connect(ui->nameLineEdit, SIGNAL(textChanged(QString)), this, SLOT(validate()));
@ -78,6 +77,9 @@ AddFeedDialog::AddFeedDialog(RsFeedReader *feedReader, FeedReaderNotify *notify,
/* not yet supported */
ui->authenticationGroupBox->setEnabled(false);
mTransformationType = RS_FEED_TRANSFORMATION_TYPE_NONE;
ui->transformationTypeLabel->setText(FeedReaderStringDefs::transforationTypeString(mTransformationType));
/* fill own forums */
std::list<ForumInfo> forumList;
if (rsForums->getForumList(forumList)) {
@ -163,7 +165,7 @@ void AddFeedDialog::typeForumToggled()
void AddFeedDialog::denyForumToggled()
{
if (ui->saveCompletePageCheckBox->isChecked() || ui->embedImagesCheckBox->isChecked()) {
if (ui->saveCompletePageCheckBox->isChecked()) {
ui->typeForumRadio->setEnabled(false);
ui->typeLocalRadio->setChecked(true);
} else {
@ -230,7 +232,6 @@ bool AddFeedDialog::fillFeed(const std::string &feedId)
if (feedInfo.flag.forum) {
ui->typeForumRadio->setChecked(true);
ui->saveCompletePageCheckBox->setEnabled(false);
ui->embedImagesCheckBox->setEnabled(false);
if (feedInfo.forumId.empty()) {
ui->forumNameLabel->setText(tr("Not yet created"));
@ -263,8 +264,12 @@ bool AddFeedDialog::fillFeed(const std::string &feedId)
ui->useStandardStorageTimeCheckBox->setChecked(feedInfo.flag.standardStorageTime);
ui->storageTimeSpinBox->setValue(feedInfo.storageTime / (60 * 60 *24));
mTransformationType = feedInfo.transformationType;
mXPathsToUse = feedInfo.xpathsToUse;
mXPathsToRemove = feedInfo.xpathsToRemove;
mXslt = feedInfo.xslt;
ui->transformationTypeLabel->setText(FeedReaderStringDefs::transforationTypeString(mTransformationType));
}
return true;
@ -306,8 +311,10 @@ void AddFeedDialog::getFeedInfo(FeedInfo &feedInfo)
feedInfo.flag.standardStorageTime = ui->useStandardStorageTimeCheckBox->isChecked();
feedInfo.storageTime = ui->storageTimeSpinBox->value() * 60 *60 * 24;
feedInfo.transformationType = mTransformationType;
feedInfo.xpathsToUse = mXPathsToUse;
feedInfo.xpathsToRemove = mXPathsToRemove;
feedInfo.xslt = mXslt;
}
void AddFeedDialog::createFeed()
@ -345,6 +352,7 @@ void AddFeedDialog::preview()
PreviewFeedDialog dialog(mFeedReader, mNotify, feedInfo, this);
if (dialog.exec() == QDialog::Accepted) {
dialog.getXPaths(mXPathsToUse, mXPathsToRemove);
mTransformationType = dialog.getData(mXPathsToUse, mXPathsToRemove, mXslt);
ui->transformationTypeLabel->setText(FeedReaderStringDefs::transforationTypeString(mTransformationType));
}
}

View file

@ -63,8 +63,10 @@ private:
std::string mFeedId;
std::string mParentId;
RsFeedTransformationType mTransformationType;
std::list<std::string> mXPathsToUse;
std::list<std::string> mXPathsToRemove;
std::string mXslt;
Ui::AddFeedDialog *ui;
};

View file

@ -21,7 +21,16 @@
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
@ -36,6 +45,61 @@
<enum>QFrame::Raised</enum>
</property>
<layout class="QGridLayout" name="gridLayout_7">
<item row="3" column="0">
<widget class="QGroupBox" name="typeGroupBox">
<property name="title">
<string>Type</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QRadioButton" name="typeForumRadio">
<property name="text">
<string>Forum</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="forumComboBox"/>
</item>
<item>
<widget class="QLabel" name="forumNameLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string notr="true">Forum name</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QRadioButton" name="typeLocalRadio">
<property name="text">
<string>Local Feed</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="7" column="0">
<widget class="QGroupBox" name="authenticationGroupBox">
<property name="title">
@ -76,63 +140,6 @@
</layout>
</widget>
</item>
<item row="8" column="0">
<widget class="QGroupBox" name="updateInteralGroupBox">
<property name="title">
<string>Update interval</string>
</property>
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0" colspan="2">
<widget class="QCheckBox" name="useStandardUpdateInterval">
<property name="text">
<string>Use standard update interval</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="updateIntervalLabel">
<property name="text">
<string>Interval in minutes (0 = manual)</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="updateIntervalSpinBox">
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<layout class="QHBoxLayout" name="lastUpdateLayout">
<item>
<widget class="QLabel" name="lastUpdateLabel">
<property name="text">
<string>Last update</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lastUpdate">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Never</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item row="7" column="1">
<widget class="QGroupBox" name="storageTimeGroupBox">
<property name="title">
@ -209,47 +216,47 @@
</layout>
</widget>
</item>
<item row="11" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="previewButton">
<property name="text">
<string>Preview</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="0">
<widget class="QGroupBox" name="typeGroupBox">
<item row="8" column="0">
<widget class="QGroupBox" name="updateInteralGroupBox">
<property name="title">
<string>Type</string>
<string>Update interval</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="margin">
<number>6</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0" colspan="2">
<widget class="QCheckBox" name="useStandardUpdateInterval">
<property name="text">
<string>Use standard update interval</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="updateIntervalLabel">
<property name="text">
<string>Interval in minutes (0 = manual)</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="updateIntervalSpinBox">
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<layout class="QHBoxLayout" name="lastUpdateLayout">
<item>
<widget class="QRadioButton" name="typeForumRadio">
<widget class="QLabel" name="lastUpdateLabel">
<property name="text">
<string>Forum</string>
<string>Last update</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="forumComboBox"/>
</item>
<item>
<widget class="QLabel" name="forumNameLabel">
<widget class="QLabel" name="lastUpdate">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
@ -257,78 +264,25 @@
</sizepolicy>
</property>
<property name="text">
<string notr="true">Forum name</string>
<string>Never</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QRadioButton" name="typeLocalRadio">
<property name="text">
<string>Local Feed</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item row="3" column="1">
<widget class="QGroupBox" name="flagGroupBox">
<property name="title">
<string>Misc</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QCheckBox" name="activatedCheckBox">
<property name="text">
<string>Activated</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="useInfoFromFeedCheckBox">
<property name="text">
<string>Use name and description from feed</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="updateForumInfoCheckBox">
<property name="text">
<string>Update forum information</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="embedImagesCheckBox">
<property name="text">
<string>Embed images (experimental for local feeds)</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="saveCompletePageCheckBox">
<property name="text">
<string>Save complete web page (experimental for local feeds)</string>
</property>
</widget>
</item>
</layout>
</widget>
<item row="11" column="0" colspan="2">
<layout class="QHBoxLayout" name="buttonLayout">
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0" colspan="2">
<layout class="QVBoxLayout" name="descriptionLayout">
@ -368,6 +322,83 @@
</item>
</layout>
</item>
<item row="4" column="0">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Transformation</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="transformationTypeLabel">
<property name="text">
<string>Transformation type</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="previewButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Preview &amp;&amp; Transformation</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item row="3" column="1" rowspan="2">
<widget class="QGroupBox" name="flagGroupBox">
<property name="title">
<string>Misc</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QCheckBox" name="activatedCheckBox">
<property name="text">
<string>Activated</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="useInfoFromFeedCheckBox">
<property name="text">
<string>Use name and description from feed</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="updateForumInfoCheckBox">
<property name="text">
<string>Update forum information</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="embedImagesCheckBox">
<property name="text">
<string>Embed images</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="saveCompletePageCheckBox">
<property name="text">
<string>Save complete web page (experimental for local feeds)</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>

View file

@ -67,7 +67,7 @@ FeedReaderFeedItem::FeedReaderFeedItem(RsFeedReader *feedReader, FeedReaderNotif
ui->titleLabel->setText(QString::fromUtf8(feedInfo.name.c_str()));
ui->msgTitleLabel->setText(QString::fromUtf8(msgInfo.title.c_str()));
ui->descriptionLabel->setText(QString::fromUtf8(msgInfo.description.c_str()));
ui->descriptionLabel->setText(QString::fromUtf8((msgInfo.descriptionTransformed.empty() ? msgInfo.description : msgInfo.descriptionTransformed).c_str()));
ui->dateTimeLabel->setText(DateTime::formatLongDateTime(msgInfo.pubDate));

View file

@ -219,7 +219,16 @@ void FeedReaderMessageWidget::setFeedId(const std::string &feedId)
mFeedInfo = FeedInfo();
}
ui->msgReadAllButton->setEnabled(!mFeedId.empty());
if (mFeedId.empty()) {
ui->msgReadAllButton->setEnabled(false);
ui->msgTreeWidget->setPlaceholderText("");
} else {
if (mFeedInfo.flag.forum) {
ui->msgTreeWidget->setPlaceholderText(tr("The messages will be added to the forum"));
} else {
ui->msgTreeWidget->setPlaceholderText("");
}
}
updateMsgs();
updateCurrentMessage();
@ -307,6 +316,11 @@ void FeedReaderMessageWidget::msgTreeCustomPopupMenu(QPoint /*point*/)
action = contextMnu.addAction(QIcon(""), tr("Remove"), this, SLOT(removeMsg()));
action->setEnabled(!selectedItems.empty());
contextMnu.addSeparator();
action = contextMnu.addAction(QIcon(""), tr("Retransform"), this, SLOT(retransformMsg()));
action->setEnabled((mFeedInfo.transformationType != RS_FEED_TRANSFORMATION_TYPE_NONE) && !selectedItems.empty());
contextMnu.exec(QCursor::pos());
}
@ -495,6 +509,12 @@ void FeedReaderMessageWidget::msgChanged(const QString &feedId, const QString &m
}
}
if (type == NOTIFY_TYPE_MOD) {
if (msgId.toStdString() == currentMsgId()) {
updateCurrentMessage();
}
}
if (type == NOTIFY_TYPE_ADD) {
QTreeWidgetItem *item = new RSTreeWidgetItem(mMsgCompareRole);
updateMsgItem(item, msgInfo);
@ -591,7 +611,7 @@ void FeedReaderMessageWidget::updateCurrentMessage()
setMsgAsReadUnread(row, setToReadOnActive);
}
QString msgTxt = RsHtml().formatText(ui->msgText->document(), QString::fromUtf8(msgInfo.description.c_str()), RSHTML_FORMATTEXT_EMBED_LINKS);
QString msgTxt = RsHtml().formatText(ui->msgText->document(), QString::fromUtf8((msgInfo.descriptionTransformed.empty() ? msgInfo.description : msgInfo.descriptionTransformed).c_str()), RSHTML_FORMATTEXT_EMBED_LINKS);
ui->msgText->setHtml(msgTxt);
ui->msgTitle->setText(QString::fromUtf8(msgInfo.title.c_str()));
@ -744,6 +764,20 @@ void FeedReaderMessageWidget::removeMsg()
mFeedReader->removeMsgs(mFeedId, msgIds);
}
void FeedReaderMessageWidget::retransformMsg()
{
if (mFeedId.empty()) {
return;
}
QList<QTreeWidgetItem*> selectedItems = ui->msgTreeWidget->selectedItems();
QList<QTreeWidgetItem*>::iterator it;
for (it = selectedItems.begin(); it != selectedItems.end(); ++it) {
mFeedReader->retransformMsg(mFeedId, (*it)->data(COLUMN_MSG_DATA, ROLE_MSG_ID).toString().toStdString());
}
}
void FeedReaderMessageWidget::processFeed()
{
if (mFeedId.empty()) {

View file

@ -52,6 +52,7 @@ private slots:
void processFeed();
void openLinkMsg();
void copyLinkMsg();
void retransformMsg();
/* FeedReaderNotify */
void feedChanged(const QString &feedId, int type);

View file

@ -17,7 +17,16 @@
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
@ -36,7 +45,16 @@
<enum>QFrame::Sunken</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<property name="margin">
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<item>
@ -138,7 +156,7 @@
</widget>
</item>
<item row="3" column="0">
<widget class="QTreeWidget" name="msgTreeWidget">
<widget class="RSTreeWidget" name="msgTreeWidget">
<property name="font">
<font>
<pointsize>9</pointsize>
@ -278,6 +296,11 @@
<extends>QLineEdit</extends>
<header location="global">gui/common/LineEditClear.h</header>
</customwidget>
<customwidget>
<class>RSTreeWidget</class>
<extends>QTreeWidget</extends>
<header>gui/common/RSTreeWidget.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="FeedReader_images.qrc"/>

View file

@ -71,7 +71,7 @@ QString FeedReaderStringDefs::workState(FeedInfo::WorkState state)
return QApplication::translate("FeedReaderStringDefs", "Processing");
}
return "";
return QApplication::translate("FeedReaderStringDefs", "Unknown");
}
QString FeedReaderStringDefs::errorString(const FeedInfo &feedInfo)
@ -135,6 +135,15 @@ QString FeedReaderStringDefs::errorString(RsFeedReaderErrorState errorState, con
case RS_FEED_ERRORSTATE_PROCESS_XPATH_NO_RESULT:
errorText = QApplication::translate("FeedReaderStringDefs", "Empty XPath result");
break;
case RS_FEED_ERRORSTATE_PROCESS_XSLT_FORMAT_ERROR:
errorText = QApplication::translate("FeedReaderStringDefs", "XSLT format error");
break;
case RS_FEED_ERRORSTATE_PROCESS_XSLT_TRANSFORM_ERROR:
errorText = QApplication::translate("FeedReaderStringDefs", "XSLT transformation error");
break;
case RS_FEED_ERRORSTATE_PROCESS_XSLT_NO_RESULT:
errorText = QApplication::translate("FeedReaderStringDefs", "Empty XSLT result");
break;
default:
errorText = QApplication::translate("FeedReaderStringDefs", "Unknown error");
@ -146,3 +155,17 @@ QString FeedReaderStringDefs::errorString(RsFeedReaderErrorState errorState, con
return errorText;
}
QString FeedReaderStringDefs::transforationTypeString(RsFeedTransformationType transformationType)
{
switch (transformationType) {
case RS_FEED_TRANSFORMATION_TYPE_NONE:
return QApplication::translate("FeedReaderStringDefs", "No transformation");
case RS_FEED_TRANSFORMATION_TYPE_XPATH:
return QApplication::translate("FeedReaderStringDefs", "XPath");
case RS_FEED_TRANSFORMATION_TYPE_XSLT:
return QApplication::translate("FeedReaderStringDefs", "XSLT");
}
return QApplication::translate("FeedReaderStringDefs", "Unknown");
}

View file

@ -35,6 +35,7 @@ public:
static QString workState(FeedInfo::WorkState state);
static QString errorString(const FeedInfo &feedInfo);
static QString errorString(RsFeedReaderErrorState errorState, const std::string &errorString);
static QString transforationTypeString(RsFeedTransformationType transformationType);
};
#endif

View file

@ -30,7 +30,6 @@
#include "util/HandleRichText.h"
#include "gui/settings/rsharesettings.h"
#include "interface/rsFeedReader.h"
#include "retroshare/rsiface.h"
#include "util/HTMLWrapper.h"
@ -146,35 +145,44 @@ PreviewFeedDialog::PreviewFeedDialog(RsFeedReader *feedReader, FeedReaderNotify
ui->setupUi(this);
ui->feedNameLabel->clear();
ui->useXPathCheckBox->setChecked(true);
/* connect signals */
connect(ui->previousPushButton, SIGNAL(clicked()), this, SLOT(previousMsg()));
connect(ui->nextPushButton, SIGNAL(clicked()), this, SLOT(nextMsg()));
connect(ui->closeStructureButton, SIGNAL(clicked()), this, SLOT(showStructureFrame()));
connect(ui->structureButton, SIGNAL(toggled(bool)), this, SLOT(showStructureFrame(bool)));
connect(ui->xpathPushButton, SIGNAL(toggled(bool)), this, SLOT(showXPathFrame(bool)));
connect(ui->useXPathCheckBox, SIGNAL(toggled(bool)), this, SLOT(fillStructureTree()));
connect(ui->structureButton, SIGNAL(toggled(bool)), this, SLOT(showStructureFrame()));
connect(ui->xpathUseListWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(xpathListCustomPopupMenu(QPoint)));
connect(ui->xpathRemoveListWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(xpathListCustomPopupMenu(QPoint)));
connect(ui->xpathUseListWidget->itemDelegate(), SIGNAL(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint)), this, SLOT(xpathCloseEditor(QWidget*,QAbstractItemDelegate::EndEditHint)));
connect(ui->xpathRemoveListWidget->itemDelegate(), SIGNAL(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint)), this, SLOT(xpathCloseEditor(QWidget*,QAbstractItemDelegate::EndEditHint)));
connect(ui->transformationTypeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(transformationTypeChanged()));
connect(mNotify, SIGNAL(feedChanged(QString,int)), this, SLOT(feedChanged(QString,int)));
connect(mNotify, SIGNAL(msgChanged(QString,QString,int)), this, SLOT(msgChanged(QString,QString,int)));
ui->transformationTypeComboBox->addItem(FeedReaderStringDefs::transforationTypeString(RS_FEED_TRANSFORMATION_TYPE_NONE), RS_FEED_TRANSFORMATION_TYPE_NONE);
ui->transformationTypeComboBox->addItem(FeedReaderStringDefs::transforationTypeString(RS_FEED_TRANSFORMATION_TYPE_XPATH), RS_FEED_TRANSFORMATION_TYPE_XPATH);
ui->transformationTypeComboBox->addItem(FeedReaderStringDefs::transforationTypeString(RS_FEED_TRANSFORMATION_TYPE_XSLT), RS_FEED_TRANSFORMATION_TYPE_XSLT);
ui->xsltTextEdit->setPlaceholderText(tr("XSLT is used on focus lost or when Ctrl+Enter is pressed"));
// ui->documentTreeWidget->setItemDelegate(new PreviewItemDelegate(ui->documentTreeWidget));
ui->structureFrame->hide();
showStructureFrame();
/* Set initial size the splitter */
// QList<int> sizes;
// sizes << 300 << 300 << 150; // Qt calculates the right sizes
// ui->splitter->setSizes(sizes);
if (mFeedReader->addPreviewFeed(feedInfo, mFeedId)) {
setFeedInfo("");
} else {
setFeedInfo(tr("Cannot create preview"));
}
setXPathInfo("");
showXPathFrame(true);
setTransformationInfo("");
/* fill xpath/xslt expressions */
ui->transformationTypeComboBox->setCurrentIndex(ui->transformationTypeComboBox->findData(feedInfo.transformationType));
/* fill xpath expressions */
QListWidgetItem *item;
std::string xpath;
foreach(xpath, feedInfo.xpathsToUse){
@ -188,12 +196,15 @@ PreviewFeedDialog::PreviewFeedDialog(RsFeedReader *feedReader, FeedReaderNotify
ui->xpathRemoveListWidget->addItem(item);
}
ui->xsltTextEdit->setPlainText(QString::fromUtf8(feedInfo.xslt.c_str()));
updateMsgCount();
ui->xpathUseListWidget->installEventFilter(this);
ui->xpathUseListWidget->viewport()->installEventFilter(this);
ui->xpathRemoveListWidget->installEventFilter(this);
ui->xpathRemoveListWidget->viewport()->installEventFilter(this);
ui->xsltTextEdit->installEventFilter(this);
/* load settings */
processSettings(true);
@ -234,8 +245,6 @@ void PreviewFeedDialog::processSettings(bool load)
bool PreviewFeedDialog::eventFilter(QObject *obj, QEvent *event)
{
long todo_here;
if (event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
if (keyEvent) {
@ -247,16 +256,28 @@ bool PreviewFeedDialog::eventFilter(QObject *obj, QEvent *event)
QListWidgetItem *item = listWidget->currentItem();
if (item) {
delete(item);
processXPath();
processTransformation();
}
return true; // eat event
}
}
}
if ((keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return) && (keyEvent->modifiers() & Qt::ControlModifier)) {
/* Ctrl+Enter pressed */
if (obj == ui->xsltTextEdit) {
processTransformation();
return true; // eat event
}
}
}
}
if (event->type() == QEvent::Drop) {
processXPath();
processTransformation();
}
if (event->type() == QEvent::FocusOut) {
if (obj == ui->xsltTextEdit) {
processTransformation();
}
}
/* pass the event on to the parent class */
return QDialog::eventFilter(obj, event);
@ -338,27 +359,51 @@ void PreviewFeedDialog::msgChanged(const QString &feedId, const QString &msgId,
updateMsgCount();
}
void PreviewFeedDialog::showStructureFrame(bool show)
void PreviewFeedDialog::showStructureFrame()
{
ui->structureButton->setChecked(show);
ui->structureFrame->setVisible(show);
bool show = ui->structureButton->isChecked();
RsFeedTransformationType transformationType = (RsFeedTransformationType) ui->transformationTypeComboBox->itemData(ui->transformationTypeComboBox->currentIndex()).toInt();
if (show) {
fillStructureTree();
ui->structureTreeFrame->setVisible(show);
switch (transformationType) {
case RS_FEED_TRANSFORMATION_TYPE_NONE:
ui->msgTextOrg->hide();
ui->structureTreeWidgetOrg->hide();
ui->transformationFrame->hide();
ui->xpathFrame->hide();
ui->xsltFrame->hide();
break;
case RS_FEED_TRANSFORMATION_TYPE_XPATH:
ui->msgTextOrg->setVisible(show);
ui->structureTreeWidgetOrg->show();
ui->transformationFrame->setVisible(show);
ui->xpathFrame->show();
ui->xsltFrame->hide();
break;
case RS_FEED_TRANSFORMATION_TYPE_XSLT:
ui->msgTextOrg->setVisible(show);
ui->structureTreeWidgetOrg->show();
ui->transformationFrame->setVisible(show);
ui->xpathFrame->hide();
ui->xsltFrame->show();
break;
}
if (ui->msgTextOrg->isVisible()) {
QString msgTxt = RsHtml().formatText(ui->msgTextOrg->document(), QString::fromUtf8(mDescription.c_str()), RSHTML_FORMATTEXT_EMBED_LINKS);
ui->msgTextOrg->setHtml(msgTxt);
} else {
ui->msgTextOrg->clear();
}
fillStructureTree(false);
fillStructureTree(true);
}
void PreviewFeedDialog::showXPathFrame(bool show)
void PreviewFeedDialog::transformationTypeChanged()
{
ui->xpathFrame->setVisible(show);
if (show) {
ui->xpathPushButton->setToolTip(tr("Hide XPath expressions"));
ui->xpathPushButton->setIcon(QIcon(":images/show_toolbox_frame.png"));
} else {
ui->xpathPushButton->setToolTip(tr("Show XPath expressions"));
ui->xpathPushButton->setIcon(QIcon(":images/hide_toolbox_frame.png"));
}
showStructureFrame();
processTransformation();
}
void PreviewFeedDialog::xpathListCustomPopupMenu(QPoint /*point*/)
@ -396,7 +441,7 @@ void PreviewFeedDialog::xpathListCustomPopupMenu(QPoint /*point*/)
void PreviewFeedDialog::xpathCloseEditor(QWidget */*editor*/, QAbstractItemDelegate::EndEditHint /*hint*/)
{
processXPath();
processTransformation();
}
void PreviewFeedDialog::addXPath()
@ -468,7 +513,7 @@ void PreviewFeedDialog::removeXPath()
delete(item);
}
processXPath();
processTransformation();
}
int PreviewFeedDialog::getMsgPos()
@ -491,10 +536,10 @@ void PreviewFeedDialog::setFeedInfo(const QString &info)
ui->feedInfoLabel->setVisible(!info.isEmpty());
}
void PreviewFeedDialog::setXPathInfo(const QString &info)
void PreviewFeedDialog::setTransformationInfo(const QString &info)
{
ui->xpathInfoLabel->setText(info);
ui->xpathInfoLabel->setVisible(!info.isEmpty());
ui->transformationInfoLabel->setText(info);
ui->transformationInfoLabel->setVisible(!info.isEmpty());
}
void PreviewFeedDialog::fillFeedInfo(const FeedInfo &feedInfo)
@ -551,8 +596,9 @@ void PreviewFeedDialog::updateMsg()
if (mMsgId.empty() || !mFeedReader->getMsgInfo(mFeedId, mMsgId, msgInfo)) {
ui->msgTitle->clear();
ui->msgText->clear();
ui->msgTextOrg->clear();
mDescription.clear();
mDescriptionXPath.clear();
mDescriptionTransformed.clear();
return;
}
@ -561,8 +607,15 @@ void PreviewFeedDialog::updateMsg()
/* store description */
mDescription = msgInfo.description;
if (ui->msgTextOrg->isVisible()) {
QString msgTxt = RsHtml().formatText(ui->msgTextOrg->document(), QString::fromUtf8(mDescription.c_str()), RSHTML_FORMATTEXT_EMBED_LINKS);
ui->msgTextOrg->setHtml(msgTxt);
}
showStructureFrame();
/* process xpath */
processXPath();
processTransformation();
}
static void buildNodeText(HTMLWrapper &html, xmlNodePtr node, QString &text)
@ -699,44 +752,52 @@ static void examineChildElements(QTreeWidget *treeWidget, HTMLWrapper &html, QLi
// treeWidget->setItemWidget(item, 0, label);
}
void PreviewFeedDialog::fillStructureTree()
void PreviewFeedDialog::fillStructureTree(bool transform)
{
if (!ui->structureTreeWidget->isVisible()) {
return;
if (transform && ui->structureTreeWidget->isVisible()) {
if (mDescriptionTransformed.empty()) {
ui->structureTreeWidget->clear();
} else {
HTMLWrapper html;
if (html.readHTML(mDescriptionTransformed.c_str(), "")) {
xmlNodePtr root = html.getRootElement();
if (root) {
QList<xmlNodePtr> nodes;
nodes.push_back(root);
examineChildElements(ui->structureTreeWidget, html, nodes, ui->structureTreeWidget->invisibleRootItem());
ui->structureTreeWidget->resizeColumnToContents(0);
}
} else {
QTreeWidgetItem *item = new QTreeWidgetItem;
item->setText(0, tr("Error parsing document") + ": " + QString::fromUtf8(html.lastError().c_str()));
ui->structureTreeWidget->addTopLevelItem(item);
}
}
}
// if (ui->structureTreeWidget->topLevelItemCount() > 0) {
// return;
// }
if (mDescriptionXPath.empty()) {
ui->structureTreeWidget->clear();
return;
if (!transform && ui->structureTreeWidgetOrg->isVisible()) {
if (mDescription.empty()) {
ui->structureTreeWidgetOrg->clear();
} else {
HTMLWrapper html;
if (html.readHTML(mDescription.c_str(), "")) {
xmlNodePtr root = html.getRootElement();
if (root) {
QList<xmlNodePtr> nodes;
nodes.push_back(root);
examineChildElements(ui->structureTreeWidgetOrg, html, nodes, ui->structureTreeWidgetOrg->invisibleRootItem());
ui->structureTreeWidgetOrg->resizeColumnToContents(0);
}
} else {
QTreeWidgetItem *item = new QTreeWidgetItem;
item->setText(0, tr("Error parsing document") + ": " + QString::fromUtf8(html.lastError().c_str()));
ui->structureTreeWidgetOrg->addTopLevelItem(item);
}
}
}
bool useXPath = ui->useXPathCheckBox->isChecked();
HTMLWrapper html;
if (!html.readHTML(useXPath ? mDescriptionXPath.c_str() : mDescription.c_str(), "")) {
QTreeWidgetItem *item = new QTreeWidgetItem;
item->setText(0, tr("Error parsing document"));
ui->structureTreeWidget->addTopLevelItem(item);
return;
}
xmlNodePtr root = html.getRootElement();
if (!root) {
return;
}
QList<xmlNodePtr> nodes;
nodes.push_back(root);
examineChildElements(ui->structureTreeWidget, html, nodes, ui->structureTreeWidget->invisibleRootItem());
ui->structureTreeWidget->resizeColumnToContents(0);
}
void PreviewFeedDialog::getXPaths(std::list<std::string> &xpathsToUse, std::list<std::string> &xpathsToRemove)
RsFeedTransformationType PreviewFeedDialog::getData(std::list<std::string> &xpathsToUse, std::list<std::string> &xpathsToRemove, std::string &xslt)
{
xpathsToUse.clear();
xpathsToRemove.clear();
@ -751,24 +812,40 @@ void PreviewFeedDialog::getXPaths(std::list<std::string> &xpathsToUse, std::list
for (row = 0; row < rowCount; ++row) {
xpathsToRemove.push_back(ui->xpathRemoveListWidget->item(row)->text().toUtf8().constData());
}
xslt = ui->xsltTextEdit->toPlainText().toUtf8().constData();
return (RsFeedTransformationType) ui->transformationTypeComboBox->itemData(ui->transformationTypeComboBox->currentIndex()).toInt();
}
void PreviewFeedDialog::processXPath()
void PreviewFeedDialog::processTransformation()
{
std::list<std::string> xpathsToUse;
std::list<std::string> xpathsToRemove;
std::string xslt;
getXPaths(xpathsToUse, xpathsToRemove);
RsFeedTransformationType transformationType = getData(xpathsToUse, xpathsToRemove, xslt);
mDescriptionXPath = mDescription;
mDescriptionTransformed = mDescription;
std::string errorString;
RsFeedReaderErrorState result = mFeedReader->processXPath(xpathsToUse, xpathsToRemove, mDescriptionXPath, errorString);
setXPathInfo(FeedReaderStringDefs::errorString(result, errorString));
RsFeedReaderErrorState result = RS_FEED_ERRORSTATE_OK;
switch (transformationType) {
case RS_FEED_TRANSFORMATION_TYPE_NONE:
break;
case RS_FEED_TRANSFORMATION_TYPE_XPATH:
result = mFeedReader->processXPath(xpathsToUse, xpathsToRemove, mDescriptionTransformed, errorString);
break;
case RS_FEED_TRANSFORMATION_TYPE_XSLT:
result = mFeedReader->processXslt(xslt, mDescriptionTransformed, errorString);
break;
}
setTransformationInfo(FeedReaderStringDefs::errorString(result, errorString));
/* fill message */
QString msgTxt = RsHtml().formatText(ui->msgText->document(), QString::fromUtf8(mDescriptionXPath.c_str()), RSHTML_FORMATTEXT_EMBED_LINKS);
QString msgTxt = RsHtml().formatText(ui->msgText->document(), QString::fromUtf8(mDescriptionTransformed.c_str()), RSHTML_FORMATTEXT_EMBED_LINKS);
ui->msgText->setHtml(msgTxt);
/* fill structure */
fillStructureTree();
fillStructureTree(true);
}

View file

@ -25,6 +25,8 @@
#include <QDialog>
#include <QItemDelegate>
#include "interface/rsFeedReader.h"
namespace Ui {
class PreviewFeedDialog;
}
@ -54,12 +56,12 @@ class FeedInfo;
class PreviewFeedDialog : public QDialog
{
Q_OBJECT
public:
PreviewFeedDialog(RsFeedReader *feedReader, FeedReaderNotify *notify, const FeedInfo &feedInfo, QWidget *parent = 0);
~PreviewFeedDialog();
void getXPaths(std::list<std::string> &xpathsToUse, std::list<std::string> &xpathsToRemove);
RsFeedTransformationType getData(std::list<std::string> &xpathsToUse, std::list<std::string> &xpathsToRemove, std::string &xslt);
protected:
bool eventFilter(QObject *obj, QEvent *ev);
@ -67,14 +69,13 @@ protected:
private slots:
void previousMsg();
void nextMsg();
void showStructureFrame(bool show = false);
void showXPathFrame(bool show);
void showStructureFrame();
void xpathListCustomPopupMenu(QPoint point);
void xpathCloseEditor(QWidget *editor, QAbstractItemDelegate::EndEditHint hint);
void addXPath();
void editXPath();
void removeXPath();
void fillStructureTree();
void transformationTypeChanged();
/* FeedReaderNotify */
void feedChanged(const QString &feedId, int type);
@ -84,11 +85,12 @@ private:
void processSettings(bool load);
int getMsgPos();
void setFeedInfo(const QString &info);
void setXPathInfo(const QString &info);
void setTransformationInfo(const QString &info);
void fillFeedInfo(const FeedInfo &feedInfo);
void updateMsgCount();
void updateMsg();
void processXPath();
void fillStructureTree(bool transform);
void processTransformation();
RsFeedReader *mFeedReader;
FeedReaderNotify *mNotify;
@ -96,7 +98,7 @@ private:
std::string mMsgId;
std::list<std::string> mMsgIds;
std::string mDescription;
std::string mDescriptionXPath;
std::string mDescriptionTransformed;
Ui::PreviewFeedDialog *ui;
};

File diff suppressed because it is too large Load diff