mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-06-17 19:09:29 -04:00
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:
parent
919fb3f62d
commit
ef49000b9a
28 changed files with 1549 additions and 849 deletions
|
@ -229,14 +229,11 @@ static int vasprintf(char **sptr, const char *fmt, va_list argv)
|
||||||
//}
|
//}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int rs_sprintf(std::string &str, const char *fmt, ...)
|
int rs_sprintf_args(std::string &str, const char *fmt, va_list ap)
|
||||||
{
|
{
|
||||||
char *buffer = NULL;
|
char *buffer = NULL;
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
int retval = vasprintf(&buffer, fmt, (va_list) ap);
|
||||||
int retval = vasprintf(&buffer, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
if (retval >= 0) {
|
if (retval >= 0) {
|
||||||
if (buffer) {
|
if (buffer) {
|
||||||
|
@ -252,15 +249,23 @@ int rs_sprintf(std::string &str, const char *fmt, ...)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rs_sprintf_append(std::string &str, const char *fmt, ...)
|
int rs_sprintf(std::string &str, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
char *buffer = NULL;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
int retval = vasprintf(&buffer, fmt, ap);
|
int retval = rs_sprintf_args(str, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rs_sprintf_append_args(std::string &str, const char *fmt, va_list ap)
|
||||||
|
{
|
||||||
|
char *buffer = NULL;
|
||||||
|
|
||||||
|
int retval = vasprintf(&buffer, fmt, (va_list) ap);
|
||||||
|
|
||||||
if (retval >= 0) {
|
if (retval >= 0) {
|
||||||
if (buffer) {
|
if (buffer) {
|
||||||
str.append(buffer);
|
str.append(buffer);
|
||||||
|
@ -271,6 +276,17 @@ int rs_sprintf_append(std::string &str, const char *fmt, ...)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int rs_sprintf_append(std::string &str, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
int retval = rs_sprintf_append_args(str, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
void stringToUpperCase(const std::string& s, std::string &upper)
|
void stringToUpperCase(const std::string& s, std::string &upper)
|
||||||
{
|
{
|
||||||
upper = s ;
|
upper = s ;
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
* Boston, MA 02110-1301, USA.
|
* Boston, MA 02110-1301, USA.
|
||||||
****************************************************************/
|
****************************************************************/
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@
|
||||||
#define RSSTRING_H_
|
#define RSSTRING_H_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
namespace librs { namespace util {
|
namespace librs { namespace util {
|
||||||
|
|
||||||
|
@ -39,7 +40,9 @@ bool ConvertUtf16ToUtf8(const std::wstring& source, std::string& dest);
|
||||||
#define UINT64FMT "%llu"
|
#define UINT64FMT "%llu"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int rs_sprintf_args(std::string &str, const char *fmt, va_list ap);
|
||||||
int rs_sprintf(std::string &str, const char *fmt, ...);
|
int rs_sprintf(std::string &str, const char *fmt, ...);
|
||||||
|
int rs_sprintf_append_args(std::string &str, const char *fmt, va_list ap);
|
||||||
int rs_sprintf_append(std::string &str, const char *fmt, ...);
|
int rs_sprintf_append(std::string &str, const char *fmt, ...);
|
||||||
|
|
||||||
void stringToUpperCase(const std::string& s, std::string &upper);
|
void stringToUpperCase(const std::string& s, std::string &upper);
|
||||||
|
|
|
@ -51,8 +51,8 @@ FORMS = gui/FeedReaderDialog.ui \
|
||||||
TARGET = FeedReader
|
TARGET = FeedReader
|
||||||
|
|
||||||
RESOURCES = gui/FeedReader_images.qrc \
|
RESOURCES = gui/FeedReader_images.qrc \
|
||||||
lang/FeedReader_lang.qrc
|
lang/FeedReader_lang.qrc
|
||||||
|
|
||||||
TRANSLATIONS += \
|
TRANSLATIONS += \
|
||||||
lang/FeedReader_cs.ts \
|
lang/FeedReader_cs.ts \
|
||||||
lang/FeedReader_da.ts \
|
lang/FeedReader_da.ts \
|
||||||
|
@ -76,17 +76,17 @@ linux-* {
|
||||||
|
|
||||||
INCLUDEPATH += $${LIBXML2_DIR}
|
INCLUDEPATH += $${LIBXML2_DIR}
|
||||||
|
|
||||||
LIBS += -lcurl -lxml2
|
LIBS += -lcurl -lxml2 -lxslt
|
||||||
}
|
}
|
||||||
|
|
||||||
win32 {
|
win32 {
|
||||||
DEFINES += CURL_STATICLIB LIBXML_STATIC
|
DEFINES += CURL_STATICLIB LIBXML_STATIC LIBXSLT_STATIC LIBEXSLT_STATIC
|
||||||
|
|
||||||
CURL_DIR = ../../../curl-7.26.0
|
CURL_DIR = ../../../curl-7.26.0
|
||||||
LIBXML2_DIR = ../../../libxml2-2.8.0
|
LIBXML2_DIR = ../../../libxml2-2.8.0
|
||||||
LIBICONV_DIR = ../../../libiconv-1.14
|
LIBXSLT_DIR = ../../../libxslt-1.1.28
|
||||||
|
|
||||||
INCLUDEPATH += $${CURL_DIR}/include $${LIBXML2_DIR}/include $${LIBICONV_DIR}/include
|
INCLUDEPATH += $${CURL_DIR}/include $${LIBXML2_DIR}/include $${LIBXSLT_DIR} $${LIBICONV_DIR}/include
|
||||||
|
|
||||||
LIBS += -lcurl -lxml2 -lws2_32 -lwldap32
|
LIBS += -lcurl -lxml2 -lxslt -lws2_32 -lwldap32
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,6 @@ AddFeedDialog::AddFeedDialog(RsFeedReader *feedReader, FeedReaderNotify *notify,
|
||||||
|
|
||||||
/* currently only for loacl feeds */
|
/* currently only for loacl feeds */
|
||||||
connect(ui->saveCompletePageCheckBox, SIGNAL(toggled(bool)), this, SLOT(denyForumToggled()));
|
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->urlLineEdit, SIGNAL(textChanged(QString)), this, SLOT(validate()));
|
||||||
connect(ui->nameLineEdit, 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 */
|
/* not yet supported */
|
||||||
ui->authenticationGroupBox->setEnabled(false);
|
ui->authenticationGroupBox->setEnabled(false);
|
||||||
|
|
||||||
|
mTransformationType = RS_FEED_TRANSFORMATION_TYPE_NONE;
|
||||||
|
ui->transformationTypeLabel->setText(FeedReaderStringDefs::transforationTypeString(mTransformationType));
|
||||||
|
|
||||||
/* fill own forums */
|
/* fill own forums */
|
||||||
std::list<ForumInfo> forumList;
|
std::list<ForumInfo> forumList;
|
||||||
if (rsForums->getForumList(forumList)) {
|
if (rsForums->getForumList(forumList)) {
|
||||||
|
@ -163,7 +165,7 @@ void AddFeedDialog::typeForumToggled()
|
||||||
|
|
||||||
void AddFeedDialog::denyForumToggled()
|
void AddFeedDialog::denyForumToggled()
|
||||||
{
|
{
|
||||||
if (ui->saveCompletePageCheckBox->isChecked() || ui->embedImagesCheckBox->isChecked()) {
|
if (ui->saveCompletePageCheckBox->isChecked()) {
|
||||||
ui->typeForumRadio->setEnabled(false);
|
ui->typeForumRadio->setEnabled(false);
|
||||||
ui->typeLocalRadio->setChecked(true);
|
ui->typeLocalRadio->setChecked(true);
|
||||||
} else {
|
} else {
|
||||||
|
@ -230,7 +232,6 @@ bool AddFeedDialog::fillFeed(const std::string &feedId)
|
||||||
if (feedInfo.flag.forum) {
|
if (feedInfo.flag.forum) {
|
||||||
ui->typeForumRadio->setChecked(true);
|
ui->typeForumRadio->setChecked(true);
|
||||||
ui->saveCompletePageCheckBox->setEnabled(false);
|
ui->saveCompletePageCheckBox->setEnabled(false);
|
||||||
ui->embedImagesCheckBox->setEnabled(false);
|
|
||||||
|
|
||||||
if (feedInfo.forumId.empty()) {
|
if (feedInfo.forumId.empty()) {
|
||||||
ui->forumNameLabel->setText(tr("Not yet created"));
|
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->useStandardStorageTimeCheckBox->setChecked(feedInfo.flag.standardStorageTime);
|
||||||
ui->storageTimeSpinBox->setValue(feedInfo.storageTime / (60 * 60 *24));
|
ui->storageTimeSpinBox->setValue(feedInfo.storageTime / (60 * 60 *24));
|
||||||
|
|
||||||
|
mTransformationType = feedInfo.transformationType;
|
||||||
mXPathsToUse = feedInfo.xpathsToUse;
|
mXPathsToUse = feedInfo.xpathsToUse;
|
||||||
mXPathsToRemove = feedInfo.xpathsToRemove;
|
mXPathsToRemove = feedInfo.xpathsToRemove;
|
||||||
|
mXslt = feedInfo.xslt;
|
||||||
|
|
||||||
|
ui->transformationTypeLabel->setText(FeedReaderStringDefs::transforationTypeString(mTransformationType));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -306,8 +311,10 @@ void AddFeedDialog::getFeedInfo(FeedInfo &feedInfo)
|
||||||
feedInfo.flag.standardStorageTime = ui->useStandardStorageTimeCheckBox->isChecked();
|
feedInfo.flag.standardStorageTime = ui->useStandardStorageTimeCheckBox->isChecked();
|
||||||
feedInfo.storageTime = ui->storageTimeSpinBox->value() * 60 *60 * 24;
|
feedInfo.storageTime = ui->storageTimeSpinBox->value() * 60 *60 * 24;
|
||||||
|
|
||||||
|
feedInfo.transformationType = mTransformationType;
|
||||||
feedInfo.xpathsToUse = mXPathsToUse;
|
feedInfo.xpathsToUse = mXPathsToUse;
|
||||||
feedInfo.xpathsToRemove = mXPathsToRemove;
|
feedInfo.xpathsToRemove = mXPathsToRemove;
|
||||||
|
feedInfo.xslt = mXslt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddFeedDialog::createFeed()
|
void AddFeedDialog::createFeed()
|
||||||
|
@ -345,6 +352,7 @@ void AddFeedDialog::preview()
|
||||||
|
|
||||||
PreviewFeedDialog dialog(mFeedReader, mNotify, feedInfo, this);
|
PreviewFeedDialog dialog(mFeedReader, mNotify, feedInfo, this);
|
||||||
if (dialog.exec() == QDialog::Accepted) {
|
if (dialog.exec() == QDialog::Accepted) {
|
||||||
dialog.getXPaths(mXPathsToUse, mXPathsToRemove);
|
mTransformationType = dialog.getData(mXPathsToUse, mXPathsToRemove, mXslt);
|
||||||
|
ui->transformationTypeLabel->setText(FeedReaderStringDefs::transforationTypeString(mTransformationType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,8 +63,10 @@ private:
|
||||||
std::string mFeedId;
|
std::string mFeedId;
|
||||||
std::string mParentId;
|
std::string mParentId;
|
||||||
|
|
||||||
|
RsFeedTransformationType mTransformationType;
|
||||||
std::list<std::string> mXPathsToUse;
|
std::list<std::string> mXPathsToUse;
|
||||||
std::list<std::string> mXPathsToRemove;
|
std::list<std::string> mXPathsToRemove;
|
||||||
|
std::string mXslt;
|
||||||
|
|
||||||
Ui::AddFeedDialog *ui;
|
Ui::AddFeedDialog *ui;
|
||||||
};
|
};
|
||||||
|
|
|
@ -21,7 +21,16 @@
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</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>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
|
@ -36,6 +45,61 @@
|
||||||
<enum>QFrame::Raised</enum>
|
<enum>QFrame::Raised</enum>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_7">
|
<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">
|
<item row="7" column="0">
|
||||||
<widget class="QGroupBox" name="authenticationGroupBox">
|
<widget class="QGroupBox" name="authenticationGroupBox">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
|
@ -76,63 +140,6 @@
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</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">
|
<item row="7" column="1">
|
||||||
<widget class="QGroupBox" name="storageTimeGroupBox">
|
<widget class="QGroupBox" name="storageTimeGroupBox">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
|
@ -209,47 +216,47 @@
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="11" column="0" colspan="2">
|
<item row="8" column="0">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<widget class="QGroupBox" name="updateInteralGroupBox">
|
||||||
<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">
|
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Type</string>
|
<string>Update interval</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
<layout class="QGridLayout" name="gridLayout_5">
|
||||||
<property name="margin">
|
<item row="0" column="0" colspan="2">
|
||||||
<number>6</number>
|
<widget class="QCheckBox" name="useStandardUpdateInterval">
|
||||||
</property>
|
<property name="text">
|
||||||
<item>
|
<string>Use standard update interval</string>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
</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>
|
<item>
|
||||||
<widget class="QRadioButton" name="typeForumRadio">
|
<widget class="QLabel" name="lastUpdateLabel">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Forum</string>
|
<string>Last update</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QComboBox" name="forumComboBox"/>
|
<widget class="QLabel" name="lastUpdate">
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="forumNameLabel">
|
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
|
@ -257,78 +264,25 @@
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string notr="true">Forum name</string>
|
<string>Never</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</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>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="1">
|
<item row="11" column="0" colspan="2">
|
||||||
<widget class="QGroupBox" name="flagGroupBox">
|
<layout class="QHBoxLayout" name="buttonLayout">
|
||||||
<property name="title">
|
<item>
|
||||||
<string>Misc</string>
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
</property>
|
<property name="standardButtons">
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
<item>
|
</property>
|
||||||
<widget class="QCheckBox" name="activatedCheckBox">
|
</widget>
|
||||||
<property name="text">
|
</item>
|
||||||
<string>Activated</string>
|
</layout>
|
||||||
</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>
|
</item>
|
||||||
<item row="1" column="0" colspan="2">
|
<item row="1" column="0" colspan="2">
|
||||||
<layout class="QVBoxLayout" name="descriptionLayout">
|
<layout class="QVBoxLayout" name="descriptionLayout">
|
||||||
|
@ -368,6 +322,83 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</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 && 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>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -67,7 +67,7 @@ FeedReaderFeedItem::FeedReaderFeedItem(RsFeedReader *feedReader, FeedReaderNotif
|
||||||
|
|
||||||
ui->titleLabel->setText(QString::fromUtf8(feedInfo.name.c_str()));
|
ui->titleLabel->setText(QString::fromUtf8(feedInfo.name.c_str()));
|
||||||
ui->msgTitleLabel->setText(QString::fromUtf8(msgInfo.title.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));
|
ui->dateTimeLabel->setText(DateTime::formatLongDateTime(msgInfo.pubDate));
|
||||||
|
|
||||||
|
|
|
@ -219,7 +219,16 @@ void FeedReaderMessageWidget::setFeedId(const std::string &feedId)
|
||||||
mFeedInfo = FeedInfo();
|
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();
|
updateMsgs();
|
||||||
updateCurrentMessage();
|
updateCurrentMessage();
|
||||||
|
@ -307,6 +316,11 @@ void FeedReaderMessageWidget::msgTreeCustomPopupMenu(QPoint /*point*/)
|
||||||
action = contextMnu.addAction(QIcon(""), tr("Remove"), this, SLOT(removeMsg()));
|
action = contextMnu.addAction(QIcon(""), tr("Remove"), this, SLOT(removeMsg()));
|
||||||
action->setEnabled(!selectedItems.empty());
|
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());
|
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) {
|
if (type == NOTIFY_TYPE_ADD) {
|
||||||
QTreeWidgetItem *item = new RSTreeWidgetItem(mMsgCompareRole);
|
QTreeWidgetItem *item = new RSTreeWidgetItem(mMsgCompareRole);
|
||||||
updateMsgItem(item, msgInfo);
|
updateMsgItem(item, msgInfo);
|
||||||
|
@ -591,7 +611,7 @@ void FeedReaderMessageWidget::updateCurrentMessage()
|
||||||
setMsgAsReadUnread(row, setToReadOnActive);
|
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->msgText->setHtml(msgTxt);
|
||||||
ui->msgTitle->setText(QString::fromUtf8(msgInfo.title.c_str()));
|
ui->msgTitle->setText(QString::fromUtf8(msgInfo.title.c_str()));
|
||||||
|
@ -744,6 +764,20 @@ void FeedReaderMessageWidget::removeMsg()
|
||||||
mFeedReader->removeMsgs(mFeedId, msgIds);
|
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()
|
void FeedReaderMessageWidget::processFeed()
|
||||||
{
|
{
|
||||||
if (mFeedId.empty()) {
|
if (mFeedId.empty()) {
|
||||||
|
|
|
@ -52,6 +52,7 @@ private slots:
|
||||||
void processFeed();
|
void processFeed();
|
||||||
void openLinkMsg();
|
void openLinkMsg();
|
||||||
void copyLinkMsg();
|
void copyLinkMsg();
|
||||||
|
void retransformMsg();
|
||||||
|
|
||||||
/* FeedReaderNotify */
|
/* FeedReaderNotify */
|
||||||
void feedChanged(const QString &feedId, int type);
|
void feedChanged(const QString &feedId, int type);
|
||||||
|
|
|
@ -17,7 +17,16 @@
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</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>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
|
@ -36,7 +45,16 @@
|
||||||
<enum>QFrame::Sunken</enum>
|
<enum>QFrame::Sunken</enum>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
<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>
|
<number>2</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
|
@ -138,7 +156,7 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="3" column="0">
|
||||||
<widget class="QTreeWidget" name="msgTreeWidget">
|
<widget class="RSTreeWidget" name="msgTreeWidget">
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
<pointsize>9</pointsize>
|
<pointsize>9</pointsize>
|
||||||
|
@ -278,6 +296,11 @@
|
||||||
<extends>QLineEdit</extends>
|
<extends>QLineEdit</extends>
|
||||||
<header location="global">gui/common/LineEditClear.h</header>
|
<header location="global">gui/common/LineEditClear.h</header>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>RSTreeWidget</class>
|
||||||
|
<extends>QTreeWidget</extends>
|
||||||
|
<header>gui/common/RSTreeWidget.h</header>
|
||||||
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="FeedReader_images.qrc"/>
|
<include location="FeedReader_images.qrc"/>
|
||||||
|
|
|
@ -71,7 +71,7 @@ QString FeedReaderStringDefs::workState(FeedInfo::WorkState state)
|
||||||
return QApplication::translate("FeedReaderStringDefs", "Processing");
|
return QApplication::translate("FeedReaderStringDefs", "Processing");
|
||||||
}
|
}
|
||||||
|
|
||||||
return "";
|
return QApplication::translate("FeedReaderStringDefs", "Unknown");
|
||||||
}
|
}
|
||||||
|
|
||||||
QString FeedReaderStringDefs::errorString(const FeedInfo &feedInfo)
|
QString FeedReaderStringDefs::errorString(const FeedInfo &feedInfo)
|
||||||
|
@ -135,6 +135,15 @@ QString FeedReaderStringDefs::errorString(RsFeedReaderErrorState errorState, con
|
||||||
case RS_FEED_ERRORSTATE_PROCESS_XPATH_NO_RESULT:
|
case RS_FEED_ERRORSTATE_PROCESS_XPATH_NO_RESULT:
|
||||||
errorText = QApplication::translate("FeedReaderStringDefs", "Empty XPath result");
|
errorText = QApplication::translate("FeedReaderStringDefs", "Empty XPath result");
|
||||||
break;
|
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:
|
default:
|
||||||
errorText = QApplication::translate("FeedReaderStringDefs", "Unknown error");
|
errorText = QApplication::translate("FeedReaderStringDefs", "Unknown error");
|
||||||
|
@ -146,3 +155,17 @@ QString FeedReaderStringDefs::errorString(RsFeedReaderErrorState errorState, con
|
||||||
|
|
||||||
return errorText;
|
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");
|
||||||
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ public:
|
||||||
static QString workState(FeedInfo::WorkState state);
|
static QString workState(FeedInfo::WorkState state);
|
||||||
static QString errorString(const FeedInfo &feedInfo);
|
static QString errorString(const FeedInfo &feedInfo);
|
||||||
static QString errorString(RsFeedReaderErrorState errorState, const std::string &errorString);
|
static QString errorString(RsFeedReaderErrorState errorState, const std::string &errorString);
|
||||||
|
static QString transforationTypeString(RsFeedTransformationType transformationType);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
#include "util/HandleRichText.h"
|
#include "util/HandleRichText.h"
|
||||||
#include "gui/settings/rsharesettings.h"
|
#include "gui/settings/rsharesettings.h"
|
||||||
|
|
||||||
#include "interface/rsFeedReader.h"
|
|
||||||
#include "retroshare/rsiface.h"
|
#include "retroshare/rsiface.h"
|
||||||
#include "util/HTMLWrapper.h"
|
#include "util/HTMLWrapper.h"
|
||||||
|
|
||||||
|
@ -146,35 +145,44 @@ PreviewFeedDialog::PreviewFeedDialog(RsFeedReader *feedReader, FeedReaderNotify
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
ui->feedNameLabel->clear();
|
ui->feedNameLabel->clear();
|
||||||
ui->useXPathCheckBox->setChecked(true);
|
|
||||||
|
|
||||||
/* connect signals */
|
/* connect signals */
|
||||||
connect(ui->previousPushButton, SIGNAL(clicked()), this, SLOT(previousMsg()));
|
connect(ui->previousPushButton, SIGNAL(clicked()), this, SLOT(previousMsg()));
|
||||||
connect(ui->nextPushButton, SIGNAL(clicked()), this, SLOT(nextMsg()));
|
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()));
|
||||||
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->xpathUseListWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(xpathListCustomPopupMenu(QPoint)));
|
connect(ui->xpathUseListWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(xpathListCustomPopupMenu(QPoint)));
|
||||||
connect(ui->xpathRemoveListWidget, 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->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->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(feedChanged(QString,int)), this, SLOT(feedChanged(QString,int)));
|
||||||
connect(mNotify, SIGNAL(msgChanged(QString,QString,int)), this, SLOT(msgChanged(QString,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->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)) {
|
if (mFeedReader->addPreviewFeed(feedInfo, mFeedId)) {
|
||||||
setFeedInfo("");
|
setFeedInfo("");
|
||||||
} else {
|
} else {
|
||||||
setFeedInfo(tr("Cannot create preview"));
|
setFeedInfo(tr("Cannot create preview"));
|
||||||
}
|
}
|
||||||
setXPathInfo("");
|
setTransformationInfo("");
|
||||||
showXPathFrame(true);
|
|
||||||
|
/* fill xpath/xslt expressions */
|
||||||
|
ui->transformationTypeComboBox->setCurrentIndex(ui->transformationTypeComboBox->findData(feedInfo.transformationType));
|
||||||
|
|
||||||
/* fill xpath expressions */
|
|
||||||
QListWidgetItem *item;
|
QListWidgetItem *item;
|
||||||
std::string xpath;
|
std::string xpath;
|
||||||
foreach(xpath, feedInfo.xpathsToUse){
|
foreach(xpath, feedInfo.xpathsToUse){
|
||||||
|
@ -188,12 +196,15 @@ PreviewFeedDialog::PreviewFeedDialog(RsFeedReader *feedReader, FeedReaderNotify
|
||||||
ui->xpathRemoveListWidget->addItem(item);
|
ui->xpathRemoveListWidget->addItem(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ui->xsltTextEdit->setPlainText(QString::fromUtf8(feedInfo.xslt.c_str()));
|
||||||
|
|
||||||
updateMsgCount();
|
updateMsgCount();
|
||||||
|
|
||||||
ui->xpathUseListWidget->installEventFilter(this);
|
ui->xpathUseListWidget->installEventFilter(this);
|
||||||
ui->xpathUseListWidget->viewport()->installEventFilter(this);
|
ui->xpathUseListWidget->viewport()->installEventFilter(this);
|
||||||
ui->xpathRemoveListWidget->installEventFilter(this);
|
ui->xpathRemoveListWidget->installEventFilter(this);
|
||||||
ui->xpathRemoveListWidget->viewport()->installEventFilter(this);
|
ui->xpathRemoveListWidget->viewport()->installEventFilter(this);
|
||||||
|
ui->xsltTextEdit->installEventFilter(this);
|
||||||
|
|
||||||
/* load settings */
|
/* load settings */
|
||||||
processSettings(true);
|
processSettings(true);
|
||||||
|
@ -234,8 +245,6 @@ void PreviewFeedDialog::processSettings(bool load)
|
||||||
|
|
||||||
bool PreviewFeedDialog::eventFilter(QObject *obj, QEvent *event)
|
bool PreviewFeedDialog::eventFilter(QObject *obj, QEvent *event)
|
||||||
{
|
{
|
||||||
long todo_here;
|
|
||||||
|
|
||||||
if (event->type() == QEvent::KeyPress) {
|
if (event->type() == QEvent::KeyPress) {
|
||||||
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
|
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
|
||||||
if (keyEvent) {
|
if (keyEvent) {
|
||||||
|
@ -247,16 +256,28 @@ bool PreviewFeedDialog::eventFilter(QObject *obj, QEvent *event)
|
||||||
QListWidgetItem *item = listWidget->currentItem();
|
QListWidgetItem *item = listWidget->currentItem();
|
||||||
if (item) {
|
if (item) {
|
||||||
delete(item);
|
delete(item);
|
||||||
processXPath();
|
processTransformation();
|
||||||
}
|
}
|
||||||
return true; // eat event
|
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) {
|
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 */
|
/* pass the event on to the parent class */
|
||||||
return QDialog::eventFilter(obj, event);
|
return QDialog::eventFilter(obj, event);
|
||||||
|
@ -338,27 +359,51 @@ void PreviewFeedDialog::msgChanged(const QString &feedId, const QString &msgId,
|
||||||
updateMsgCount();
|
updateMsgCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreviewFeedDialog::showStructureFrame(bool show)
|
void PreviewFeedDialog::showStructureFrame()
|
||||||
{
|
{
|
||||||
ui->structureButton->setChecked(show);
|
bool show = ui->structureButton->isChecked();
|
||||||
ui->structureFrame->setVisible(show);
|
RsFeedTransformationType transformationType = (RsFeedTransformationType) ui->transformationTypeComboBox->itemData(ui->transformationTypeComboBox->currentIndex()).toInt();
|
||||||
|
|
||||||
if (show) {
|
ui->structureTreeFrame->setVisible(show);
|
||||||
fillStructureTree();
|
|
||||||
|
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);
|
showStructureFrame();
|
||||||
|
processTransformation();
|
||||||
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"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreviewFeedDialog::xpathListCustomPopupMenu(QPoint /*point*/)
|
void PreviewFeedDialog::xpathListCustomPopupMenu(QPoint /*point*/)
|
||||||
|
@ -396,7 +441,7 @@ void PreviewFeedDialog::xpathListCustomPopupMenu(QPoint /*point*/)
|
||||||
|
|
||||||
void PreviewFeedDialog::xpathCloseEditor(QWidget */*editor*/, QAbstractItemDelegate::EndEditHint /*hint*/)
|
void PreviewFeedDialog::xpathCloseEditor(QWidget */*editor*/, QAbstractItemDelegate::EndEditHint /*hint*/)
|
||||||
{
|
{
|
||||||
processXPath();
|
processTransformation();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreviewFeedDialog::addXPath()
|
void PreviewFeedDialog::addXPath()
|
||||||
|
@ -468,7 +513,7 @@ void PreviewFeedDialog::removeXPath()
|
||||||
delete(item);
|
delete(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
processXPath();
|
processTransformation();
|
||||||
}
|
}
|
||||||
|
|
||||||
int PreviewFeedDialog::getMsgPos()
|
int PreviewFeedDialog::getMsgPos()
|
||||||
|
@ -491,10 +536,10 @@ void PreviewFeedDialog::setFeedInfo(const QString &info)
|
||||||
ui->feedInfoLabel->setVisible(!info.isEmpty());
|
ui->feedInfoLabel->setVisible(!info.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreviewFeedDialog::setXPathInfo(const QString &info)
|
void PreviewFeedDialog::setTransformationInfo(const QString &info)
|
||||||
{
|
{
|
||||||
ui->xpathInfoLabel->setText(info);
|
ui->transformationInfoLabel->setText(info);
|
||||||
ui->xpathInfoLabel->setVisible(!info.isEmpty());
|
ui->transformationInfoLabel->setVisible(!info.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreviewFeedDialog::fillFeedInfo(const FeedInfo &feedInfo)
|
void PreviewFeedDialog::fillFeedInfo(const FeedInfo &feedInfo)
|
||||||
|
@ -551,8 +596,9 @@ void PreviewFeedDialog::updateMsg()
|
||||||
if (mMsgId.empty() || !mFeedReader->getMsgInfo(mFeedId, mMsgId, msgInfo)) {
|
if (mMsgId.empty() || !mFeedReader->getMsgInfo(mFeedId, mMsgId, msgInfo)) {
|
||||||
ui->msgTitle->clear();
|
ui->msgTitle->clear();
|
||||||
ui->msgText->clear();
|
ui->msgText->clear();
|
||||||
|
ui->msgTextOrg->clear();
|
||||||
mDescription.clear();
|
mDescription.clear();
|
||||||
mDescriptionXPath.clear();
|
mDescriptionTransformed.clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -561,8 +607,15 @@ void PreviewFeedDialog::updateMsg()
|
||||||
/* store description */
|
/* store description */
|
||||||
mDescription = msgInfo.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 */
|
/* process xpath */
|
||||||
processXPath();
|
processTransformation();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void buildNodeText(HTMLWrapper &html, xmlNodePtr node, QString &text)
|
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);
|
// treeWidget->setItemWidget(item, 0, label);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreviewFeedDialog::fillStructureTree()
|
void PreviewFeedDialog::fillStructureTree(bool transform)
|
||||||
{
|
{
|
||||||
if (!ui->structureTreeWidget->isVisible()) {
|
if (transform && ui->structureTreeWidget->isVisible()) {
|
||||||
return;
|
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) {
|
if (!transform && ui->structureTreeWidgetOrg->isVisible()) {
|
||||||
// return;
|
if (mDescription.empty()) {
|
||||||
// }
|
ui->structureTreeWidgetOrg->clear();
|
||||||
|
} else {
|
||||||
if (mDescriptionXPath.empty()) {
|
HTMLWrapper html;
|
||||||
ui->structureTreeWidget->clear();
|
if (html.readHTML(mDescription.c_str(), "")) {
|
||||||
return;
|
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();
|
xpathsToUse.clear();
|
||||||
xpathsToRemove.clear();
|
xpathsToRemove.clear();
|
||||||
|
@ -751,24 +812,40 @@ void PreviewFeedDialog::getXPaths(std::list<std::string> &xpathsToUse, std::list
|
||||||
for (row = 0; row < rowCount; ++row) {
|
for (row = 0; row < rowCount; ++row) {
|
||||||
xpathsToRemove.push_back(ui->xpathRemoveListWidget->item(row)->text().toUtf8().constData());
|
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> xpathsToUse;
|
||||||
std::list<std::string> xpathsToRemove;
|
std::list<std::string> xpathsToRemove;
|
||||||
|
std::string xslt;
|
||||||
|
|
||||||
getXPaths(xpathsToUse, xpathsToRemove);
|
RsFeedTransformationType transformationType = getData(xpathsToUse, xpathsToRemove, xslt);
|
||||||
|
|
||||||
mDescriptionXPath = mDescription;
|
mDescriptionTransformed = mDescription;
|
||||||
std::string errorString;
|
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 */
|
/* 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);
|
ui->msgText->setHtml(msgTxt);
|
||||||
|
|
||||||
/* fill structure */
|
/* fill structure */
|
||||||
fillStructureTree();
|
fillStructureTree(true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QItemDelegate>
|
#include <QItemDelegate>
|
||||||
|
|
||||||
|
#include "interface/rsFeedReader.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class PreviewFeedDialog;
|
class PreviewFeedDialog;
|
||||||
}
|
}
|
||||||
|
@ -54,12 +56,12 @@ class FeedInfo;
|
||||||
class PreviewFeedDialog : public QDialog
|
class PreviewFeedDialog : public QDialog
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PreviewFeedDialog(RsFeedReader *feedReader, FeedReaderNotify *notify, const FeedInfo &feedInfo, QWidget *parent = 0);
|
PreviewFeedDialog(RsFeedReader *feedReader, FeedReaderNotify *notify, const FeedInfo &feedInfo, QWidget *parent = 0);
|
||||||
~PreviewFeedDialog();
|
~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:
|
protected:
|
||||||
bool eventFilter(QObject *obj, QEvent *ev);
|
bool eventFilter(QObject *obj, QEvent *ev);
|
||||||
|
@ -67,14 +69,13 @@ protected:
|
||||||
private slots:
|
private slots:
|
||||||
void previousMsg();
|
void previousMsg();
|
||||||
void nextMsg();
|
void nextMsg();
|
||||||
void showStructureFrame(bool show = false);
|
void showStructureFrame();
|
||||||
void showXPathFrame(bool show);
|
|
||||||
void xpathListCustomPopupMenu(QPoint point);
|
void xpathListCustomPopupMenu(QPoint point);
|
||||||
void xpathCloseEditor(QWidget *editor, QAbstractItemDelegate::EndEditHint hint);
|
void xpathCloseEditor(QWidget *editor, QAbstractItemDelegate::EndEditHint hint);
|
||||||
void addXPath();
|
void addXPath();
|
||||||
void editXPath();
|
void editXPath();
|
||||||
void removeXPath();
|
void removeXPath();
|
||||||
void fillStructureTree();
|
void transformationTypeChanged();
|
||||||
|
|
||||||
/* FeedReaderNotify */
|
/* FeedReaderNotify */
|
||||||
void feedChanged(const QString &feedId, int type);
|
void feedChanged(const QString &feedId, int type);
|
||||||
|
@ -84,11 +85,12 @@ private:
|
||||||
void processSettings(bool load);
|
void processSettings(bool load);
|
||||||
int getMsgPos();
|
int getMsgPos();
|
||||||
void setFeedInfo(const QString &info);
|
void setFeedInfo(const QString &info);
|
||||||
void setXPathInfo(const QString &info);
|
void setTransformationInfo(const QString &info);
|
||||||
void fillFeedInfo(const FeedInfo &feedInfo);
|
void fillFeedInfo(const FeedInfo &feedInfo);
|
||||||
void updateMsgCount();
|
void updateMsgCount();
|
||||||
void updateMsg();
|
void updateMsg();
|
||||||
void processXPath();
|
void fillStructureTree(bool transform);
|
||||||
|
void processTransformation();
|
||||||
|
|
||||||
RsFeedReader *mFeedReader;
|
RsFeedReader *mFeedReader;
|
||||||
FeedReaderNotify *mNotify;
|
FeedReaderNotify *mNotify;
|
||||||
|
@ -96,7 +98,7 @@ private:
|
||||||
std::string mMsgId;
|
std::string mMsgId;
|
||||||
std::list<std::string> mMsgIds;
|
std::list<std::string> mMsgIds;
|
||||||
std::string mDescription;
|
std::string mDescription;
|
||||||
std::string mDescriptionXPath;
|
std::string mDescriptionTransformed;
|
||||||
|
|
||||||
Ui::PreviewFeedDialog *ui;
|
Ui::PreviewFeedDialog *ui;
|
||||||
};
|
};
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -26,6 +26,9 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
|
class RsFeedReader;
|
||||||
|
extern RsFeedReader *rsFeedReader;
|
||||||
|
|
||||||
enum RsFeedReaderErrorState {
|
enum RsFeedReaderErrorState {
|
||||||
RS_FEED_ERRORSTATE_OK = 0,
|
RS_FEED_ERRORSTATE_OK = 0,
|
||||||
|
|
||||||
|
@ -47,13 +50,12 @@ enum RsFeedReaderErrorState {
|
||||||
RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR = 150,
|
RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR = 150,
|
||||||
RS_FEED_ERRORSTATE_PROCESS_XPATH_INTERNAL_ERROR = 151,
|
RS_FEED_ERRORSTATE_PROCESS_XPATH_INTERNAL_ERROR = 151,
|
||||||
RS_FEED_ERRORSTATE_PROCESS_XPATH_WRONG_EXPRESSION = 152,
|
RS_FEED_ERRORSTATE_PROCESS_XPATH_WRONG_EXPRESSION = 152,
|
||||||
RS_FEED_ERRORSTATE_PROCESS_XPATH_NO_RESULT = 153
|
RS_FEED_ERRORSTATE_PROCESS_XPATH_NO_RESULT = 153,
|
||||||
|
RS_FEED_ERRORSTATE_PROCESS_XSLT_FORMAT_ERROR = 154,
|
||||||
|
RS_FEED_ERRORSTATE_PROCESS_XSLT_TRANSFORM_ERROR = 155,
|
||||||
|
RS_FEED_ERRORSTATE_PROCESS_XSLT_NO_RESULT = 156
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class RsFeedReader;
|
|
||||||
extern RsFeedReader *rsFeedReader;
|
|
||||||
|
|
||||||
enum RsFeedAddResult
|
enum RsFeedAddResult
|
||||||
{
|
{
|
||||||
RS_FEED_ADD_RESULT_SUCCESS,
|
RS_FEED_ADD_RESULT_SUCCESS,
|
||||||
|
@ -64,6 +66,13 @@ enum RsFeedAddResult
|
||||||
RS_FEED_ADD_RESULT_FEED_IS_NO_FOLDER
|
RS_FEED_ADD_RESULT_FEED_IS_NO_FOLDER
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum RsFeedTransformationType
|
||||||
|
{
|
||||||
|
RS_FEED_TRANSFORMATION_TYPE_NONE = 0,
|
||||||
|
RS_FEED_TRANSFORMATION_TYPE_XPATH = 1,
|
||||||
|
RS_FEED_TRANSFORMATION_TYPE_XSLT = 2
|
||||||
|
};
|
||||||
|
|
||||||
class FeedInfo
|
class FeedInfo
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -96,28 +105,31 @@ public:
|
||||||
flag.embedImages = false;
|
flag.embedImages = false;
|
||||||
flag.saveCompletePage = false;
|
flag.saveCompletePage = false;
|
||||||
flag.preview = false;
|
flag.preview = false;
|
||||||
|
transformationType = RS_FEED_TRANSFORMATION_TYPE_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string feedId;
|
std::string feedId;
|
||||||
std::string parentId;
|
std::string parentId;
|
||||||
std::string url;
|
std::string url;
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string description;
|
std::string description;
|
||||||
std::string icon;
|
std::string icon;
|
||||||
std::string user;
|
std::string user;
|
||||||
std::string password;
|
std::string password;
|
||||||
std::string proxyAddress;
|
std::string proxyAddress;
|
||||||
uint16_t proxyPort;
|
uint16_t proxyPort;
|
||||||
uint32_t updateInterval;
|
uint32_t updateInterval;
|
||||||
time_t lastUpdate;
|
time_t lastUpdate;
|
||||||
uint32_t storageTime;
|
uint32_t storageTime;
|
||||||
std::string forumId;
|
std::string forumId;
|
||||||
WorkState workstate;
|
WorkState workstate;
|
||||||
RsFeedReaderErrorState errorState;
|
RsFeedReaderErrorState errorState;
|
||||||
std::string errorString;
|
std::string errorString;
|
||||||
|
|
||||||
std::list<std::string> xpathsToUse;
|
RsFeedTransformationType transformationType;
|
||||||
std::list<std::string> xpathsToRemove;
|
std::list<std::string> xpathsToUse;
|
||||||
|
std::list<std::string> xpathsToRemove;
|
||||||
|
std::string xslt;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
bool folder : 1;
|
bool folder : 1;
|
||||||
|
@ -152,6 +164,7 @@ public:
|
||||||
std::string link;
|
std::string link;
|
||||||
std::string author;
|
std::string author;
|
||||||
std::string description;
|
std::string description;
|
||||||
|
std::string descriptionTransformed;
|
||||||
time_t pubDate;
|
time_t pubDate;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
@ -202,8 +215,10 @@ public:
|
||||||
virtual bool getFeedMsgIdList(const std::string &feedId, std::list<std::string> &msgIds) = 0;
|
virtual bool getFeedMsgIdList(const std::string &feedId, std::list<std::string> &msgIds) = 0;
|
||||||
virtual bool processFeed(const std::string &feedId) = 0;
|
virtual bool processFeed(const std::string &feedId) = 0;
|
||||||
virtual bool setMessageRead(const std::string &feedId, const std::string &msgId, bool read) = 0;
|
virtual bool setMessageRead(const std::string &feedId, const std::string &msgId, bool read) = 0;
|
||||||
|
virtual bool retransformMsg(const std::string &feedId, const std::string &msgId) = 0;
|
||||||
|
|
||||||
virtual RsFeedReaderErrorState processXPath(const std::list<std::string> &xpathsToUse, const std::list<std::string> &xpathsToRemove, std::string &description, std::string &errorString) = 0;
|
virtual RsFeedReaderErrorState processXPath(const std::list<std::string> &xpathsToUse, const std::list<std::string> &xpathsToRemove, std::string &description, std::string &errorString) = 0;
|
||||||
|
virtual RsFeedReaderErrorState processXslt(const std::string &xslt, std::string &description, std::string &errorString) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -88,8 +88,10 @@ static void feedToInfo(const RsFeedReaderFeed *feed, FeedInfo &info)
|
||||||
info.errorState = feed->errorState;
|
info.errorState = feed->errorState;
|
||||||
info.errorString = feed->errorString;
|
info.errorString = feed->errorString;
|
||||||
|
|
||||||
|
info.transformationType = feed->transformationType;
|
||||||
info.xpathsToUse = feed->xpathsToUse.ids;
|
info.xpathsToUse = feed->xpathsToUse.ids;
|
||||||
info.xpathsToRemove = feed->xpathsToRemove.ids;
|
info.xpathsToRemove = feed->xpathsToRemove.ids;
|
||||||
|
info.xslt = feed->xslt;
|
||||||
|
|
||||||
info.flag.folder = (feed->flag & RS_FEED_FLAG_FOLDER);
|
info.flag.folder = (feed->flag & RS_FEED_FLAG_FOLDER);
|
||||||
info.flag.infoFromFeed = (feed->flag & RS_FEED_FLAG_INFO_FROM_FEED);
|
info.flag.infoFromFeed = (feed->flag & RS_FEED_FLAG_INFO_FROM_FEED);
|
||||||
|
@ -144,8 +146,10 @@ static void infoToFeed(const FeedInfo &info, RsFeedReaderFeed *feed, bool add)
|
||||||
feed->forumId = info.forumId;
|
feed->forumId = info.forumId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
feed->transformationType = info.transformationType;
|
||||||
feed->xpathsToUse.ids = info.xpathsToUse;
|
feed->xpathsToUse.ids = info.xpathsToUse;
|
||||||
feed->xpathsToRemove.ids = info.xpathsToRemove;
|
feed->xpathsToRemove.ids = info.xpathsToRemove;
|
||||||
|
feed->xslt = info.xslt;
|
||||||
|
|
||||||
// feed->preview = info.flag.preview;
|
// feed->preview = info.flag.preview;
|
||||||
|
|
||||||
|
@ -200,6 +204,7 @@ static void feedMsgToInfo(const RsFeedReaderMsg *msg, FeedMsgInfo &info)
|
||||||
info.link = msg->link;
|
info.link = msg->link;
|
||||||
info.author = msg->author;
|
info.author = msg->author;
|
||||||
info.description = msg->description;
|
info.description = msg->description;
|
||||||
|
info.descriptionTransformed = msg->descriptionTransformed;
|
||||||
info.pubDate = msg->pubDate;
|
info.pubDate = msg->pubDate;
|
||||||
|
|
||||||
info.flag.isnew = (msg->flag & RS_FEEDMSG_FLAG_NEW);
|
info.flag.isnew = (msg->flag & RS_FEEDMSG_FLAG_NEW);
|
||||||
|
@ -491,6 +496,7 @@ RsFeedAddResult p3FeedReader::setFeed(const std::string &feedId, const FeedInfo
|
||||||
forumId = fi->forumId;
|
forumId = fi->forumId;
|
||||||
librs::util::ConvertUtf8ToUtf16(fi->name, forumInfo.forumName);
|
librs::util::ConvertUtf8ToUtf16(fi->name, forumInfo.forumName);
|
||||||
librs::util::ConvertUtf8ToUtf16(fi->description, forumInfo.forumDesc);
|
librs::util::ConvertUtf8ToUtf16(fi->description, forumInfo.forumDesc);
|
||||||
|
forumInfo.forumName.insert(0, FEEDREADER_FORUM_PREFIX);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -759,8 +765,11 @@ bool p3FeedReader::removeMsg(const std::string &feedId, const std::string &msgId
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
msgIt->second->flag |= RS_FEEDMSG_FLAG_DELETED | RS_FEEDMSG_FLAG_READ;
|
RsFeedReaderMsg *mi = msgIt->second;
|
||||||
msgIt->second->flag &= ~RS_FEEDMSG_FLAG_NEW;
|
mi->flag |= RS_FEEDMSG_FLAG_DELETED | RS_FEEDMSG_FLAG_READ;
|
||||||
|
mi->flag &= ~RS_FEEDMSG_FLAG_NEW;
|
||||||
|
mi->description.clear();
|
||||||
|
mi->descriptionTransformed.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changed) {
|
if (changed) {
|
||||||
|
@ -805,8 +814,11 @@ bool p3FeedReader::removeMsgs(const std::string &feedId, const std::list<std::st
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
msgIt->second->flag |= RS_FEEDMSG_FLAG_DELETED | RS_FEEDMSG_FLAG_READ;
|
RsFeedReaderMsg *mi = msgIt->second;
|
||||||
msgIt->second->flag &= ~RS_FEEDMSG_FLAG_NEW;
|
mi->flag |= RS_FEEDMSG_FLAG_DELETED | RS_FEEDMSG_FLAG_READ;
|
||||||
|
mi->flag &= ~RS_FEEDMSG_FLAG_NEW;
|
||||||
|
mi->description.clear();
|
||||||
|
mi->descriptionTransformed.clear();
|
||||||
|
|
||||||
removedMsgs.push_back(*idIt);
|
removedMsgs.push_back(*idIt);
|
||||||
}
|
}
|
||||||
|
@ -1121,11 +1133,74 @@ bool p3FeedReader::setMessageRead(const std::string &feedId, const std::string &
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool p3FeedReader::retransformMsg(const std::string &feedId, const std::string &msgId)
|
||||||
|
{
|
||||||
|
bool msgChanged = false;
|
||||||
|
bool feedChanged = false;
|
||||||
|
|
||||||
|
{
|
||||||
|
RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/
|
||||||
|
|
||||||
|
std::map<std::string, RsFeedReaderFeed*>::iterator feedIt = mFeeds.find(feedId);
|
||||||
|
if (feedIt == mFeeds.end()) {
|
||||||
|
#ifdef FEEDREADER_DEBUG
|
||||||
|
std::cerr << "p3FeedReader::setMessageRead - feed " << feedId << " not found" << std::endl;
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
RsFeedReaderFeed *fi = feedIt->second;
|
||||||
|
|
||||||
|
std::map<std::string, RsFeedReaderMsg*>::iterator msgIt;
|
||||||
|
msgIt = fi->msgs.find(msgId);
|
||||||
|
if (msgIt == fi->msgs.end()) {
|
||||||
|
#ifdef FEEDREADER_DEBUG
|
||||||
|
std::cerr << "p3FeedReader::setMessageRead - msg " << msgId << " not found" << std::endl;
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
RsFeedReaderMsg *mi = msgIt->second;
|
||||||
|
|
||||||
|
std::string errorString;
|
||||||
|
std::string descriptionTransformed = mi->descriptionTransformed;
|
||||||
|
if (p3FeedReaderThread::processTransformation(*fi, mi, errorString) == RS_FEED_ERRORSTATE_OK) {
|
||||||
|
if (mi->descriptionTransformed != descriptionTransformed) {
|
||||||
|
msgChanged = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!errorString.empty()) {
|
||||||
|
fi->errorString = errorString;
|
||||||
|
feedChanged = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (feedChanged || msgChanged) {
|
||||||
|
IndicateConfigChanged();
|
||||||
|
if (mNotify) {
|
||||||
|
if (feedChanged) {
|
||||||
|
mNotify->notifyFeedChanged(feedId, NOTIFY_TYPE_MOD);
|
||||||
|
}
|
||||||
|
if (msgChanged) {
|
||||||
|
mNotify->notifyMsgChanged(feedId, msgId, NOTIFY_TYPE_MOD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
RsFeedReaderErrorState p3FeedReader::processXPath(const std::list<std::string> &xpathsToUse, const std::list<std::string> &xpathsToRemove, std::string &description, std::string &errorString)
|
RsFeedReaderErrorState p3FeedReader::processXPath(const std::list<std::string> &xpathsToUse, const std::list<std::string> &xpathsToRemove, std::string &description, std::string &errorString)
|
||||||
{
|
{
|
||||||
return p3FeedReaderThread::processXPath(xpathsToUse, xpathsToRemove, description, errorString);
|
return p3FeedReaderThread::processXPath(xpathsToUse, xpathsToRemove, description, errorString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RsFeedReaderErrorState p3FeedReader::processXslt(const std::string &xslt, std::string &description, std::string &errorString)
|
||||||
|
{
|
||||||
|
return p3FeedReaderThread::processXslt(xslt, description, errorString);
|
||||||
|
}
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
/****************************** p3Service **********************************/
|
/****************************** p3Service **********************************/
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
@ -1776,7 +1851,8 @@ void p3FeedReader::onProcessSuccess_addMsgs(const std::string &feedId, std::list
|
||||||
if (forum) {
|
if (forum) {
|
||||||
miNew->flag = RS_FEEDMSG_FLAG_DELETED;
|
miNew->flag = RS_FEEDMSG_FLAG_DELETED;
|
||||||
forumMsgs.push_back(*miNew);
|
forumMsgs.push_back(*miNew);
|
||||||
// miNew->description.clear();
|
miNew->description.clear();
|
||||||
|
miNew->descriptionTransformed.clear();
|
||||||
} else {
|
} else {
|
||||||
miNew->flag = RS_FEEDMSG_FLAG_NEW;
|
miNew->flag = RS_FEEDMSG_FLAG_NEW;
|
||||||
addedMsgs.push_back(miNew->msgId);
|
addedMsgs.push_back(miNew->msgId);
|
||||||
|
@ -1816,7 +1892,7 @@ void p3FeedReader::onProcessSuccess_addMsgs(const std::string &feedId, std::list
|
||||||
forumMsgInfo.forumId = forumId;
|
forumMsgInfo.forumId = forumId;
|
||||||
librs::util::ConvertUtf8ToUtf16(mi.title, forumMsgInfo.title);
|
librs::util::ConvertUtf8ToUtf16(mi.title, forumMsgInfo.title);
|
||||||
|
|
||||||
std::string description = mi.description;
|
std::string description = mi.descriptionTransformed.empty() ? mi.description : mi.descriptionTransformed;
|
||||||
/* add link */
|
/* add link */
|
||||||
if (!mi.link.empty()) {
|
if (!mi.link.empty()) {
|
||||||
description += "<br><a href=\"" + mi.link + "\">" + mi.link + "</a>";
|
description += "<br><a href=\"" + mi.link + "\">" + mi.link + "</a>";
|
||||||
|
|
|
@ -62,8 +62,10 @@ public:
|
||||||
virtual bool getFeedMsgIdList(const std::string &feedId, std::list<std::string> &msgIds);
|
virtual bool getFeedMsgIdList(const std::string &feedId, std::list<std::string> &msgIds);
|
||||||
virtual bool processFeed(const std::string &feedId);
|
virtual bool processFeed(const std::string &feedId);
|
||||||
virtual bool setMessageRead(const std::string &feedId, const std::string &msgId, bool read);
|
virtual bool setMessageRead(const std::string &feedId, const std::string &msgId, bool read);
|
||||||
|
virtual bool retransformMsg(const std::string &feedId, const std::string &msgId);
|
||||||
|
|
||||||
virtual RsFeedReaderErrorState processXPath(const std::list<std::string> &xpathsToUse, const std::list<std::string> &xpathsToRemove, std::string &description, std::string &errorString);
|
virtual RsFeedReaderErrorState processXPath(const std::list<std::string> &xpathsToUse, const std::list<std::string> &xpathsToRemove, std::string &description, std::string &errorString);
|
||||||
|
virtual RsFeedReaderErrorState processXslt(const std::string &xslt, std::string &description, std::string &errorString);
|
||||||
|
|
||||||
/****************** p3Service STUFF ******************/
|
/****************** p3Service STUFF ******************/
|
||||||
virtual int tick();
|
virtual int tick();
|
||||||
|
|
|
@ -117,6 +117,10 @@ void p3FeedReaderThread::run()
|
||||||
delete (*it1);
|
delete (*it1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
result = processTransformation(feed, mi, errorString);
|
||||||
|
if (result != RS_FEED_ERRORSTATE_OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -258,14 +262,14 @@ static bool getFavicon(CURLWrapper &CURL, const std::string &url, std::string &i
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
RsFeedReaderErrorState p3FeedReaderThread::download(const RsFeedReaderFeed &feed, std::string &content, std::string &icon, std::string &error)
|
RsFeedReaderErrorState p3FeedReaderThread::download(const RsFeedReaderFeed &feed, std::string &content, std::string &icon, std::string &errorString)
|
||||||
{
|
{
|
||||||
#ifdef FEEDREADER_DEBUG
|
#ifdef FEEDREADER_DEBUG
|
||||||
std::cerr << "p3FeedReaderThread::download - feed " << feed.feedId << " (" << feed.name << ")" << std::endl;
|
std::cerr << "p3FeedReaderThread::download - feed " << feed.feedId << " (" << feed.name << ")" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
content.clear();
|
content.clear();
|
||||||
error.clear();
|
errorString.clear();
|
||||||
|
|
||||||
RsFeedReaderErrorState result;
|
RsFeedReaderErrorState result;
|
||||||
|
|
||||||
|
@ -291,7 +295,7 @@ RsFeedReaderErrorState p3FeedReaderThread::download(const RsFeedReaderFeed &feed
|
||||||
result = RS_FEED_ERRORSTATE_OK;
|
result = RS_FEED_ERRORSTATE_OK;
|
||||||
} else {
|
} else {
|
||||||
result = RS_FEED_ERRORSTATE_DOWNLOAD_UNKNOWN_CONTENT_TYPE;
|
result = RS_FEED_ERRORSTATE_DOWNLOAD_UNKNOWN_CONTENT_TYPE;
|
||||||
error = contentType;
|
errorString = contentType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -300,17 +304,17 @@ RsFeedReaderErrorState p3FeedReaderThread::download(const RsFeedReaderFeed &feed
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
result = RS_FEED_ERRORSTATE_DOWNLOAD_UNKOWN_RESPONSE_CODE;
|
result = RS_FEED_ERRORSTATE_DOWNLOAD_UNKOWN_RESPONSE_CODE;
|
||||||
rs_sprintf(error, "%ld", responseCode);
|
rs_sprintf(errorString, "%ld", responseCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
getFavicon(CURL, feed.url, icon);
|
getFavicon(CURL, feed.url, icon);
|
||||||
} else {
|
} else {
|
||||||
result = RS_FEED_ERRORSTATE_DOWNLOAD_ERROR;
|
result = RS_FEED_ERRORSTATE_DOWNLOAD_ERROR;
|
||||||
error = curl_easy_strerror(code);
|
errorString = curl_easy_strerror(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FEEDREADER_DEBUG
|
#ifdef FEEDREADER_DEBUG
|
||||||
std::cerr << "p3FeedReaderThread::download - feed " << feed.feedId << " (" << feed.name << "), result " << result << ", error = " << error << std::endl;
|
std::cerr << "p3FeedReaderThread::download - feed " << feed.feedId << " (" << feed.name << "), result " << result << ", error = " << errorString << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -805,7 +809,7 @@ static time_t parseISO8601Date(const std::string &pubDate)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
RsFeedReaderErrorState p3FeedReaderThread::process(const RsFeedReaderFeed &feed, std::list<RsFeedReaderMsg*> &entries, std::string &error)
|
RsFeedReaderErrorState p3FeedReaderThread::process(const RsFeedReaderFeed &feed, std::list<RsFeedReaderMsg*> &entries, std::string &errorString)
|
||||||
{
|
{
|
||||||
#ifdef FEEDREADER_DEBUG
|
#ifdef FEEDREADER_DEBUG
|
||||||
std::cerr << "p3FeedReaderThread::process - feed " << feed.feedId << " (" << feed.name << ")" << std::endl;
|
std::cerr << "p3FeedReaderThread::process - feed " << feed.feedId << " (" << feed.name << ")" << std::endl;
|
||||||
|
@ -826,7 +830,7 @@ RsFeedReaderErrorState p3FeedReaderThread::process(const RsFeedReaderFeed &feed,
|
||||||
feedFormat = FORMAT_ATOM;
|
feedFormat = FORMAT_ATOM;
|
||||||
} else {
|
} else {
|
||||||
result = RS_FEED_ERRORSTATE_PROCESS_UNKNOWN_FORMAT;
|
result = RS_FEED_ERRORSTATE_PROCESS_UNKNOWN_FORMAT;
|
||||||
error = "Only RSS, RDF or ATOM supported";
|
errorString = "Only RSS, RDF or ATOM supported";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == RS_FEED_ERRORSTATE_OK) {
|
if (result == RS_FEED_ERRORSTATE_OK) {
|
||||||
|
@ -962,19 +966,23 @@ RsFeedReaderErrorState p3FeedReaderThread::process(const RsFeedReaderFeed &feed,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
result = RS_FEED_ERRORSTATE_PROCESS_UNKNOWN_FORMAT;
|
result = RS_FEED_ERRORSTATE_PROCESS_UNKNOWN_FORMAT;
|
||||||
error = "Channel not found";
|
errorString = "Channel not found";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
result = RS_FEED_ERRORSTATE_PROCESS_UNKNOWN_FORMAT;
|
result = RS_FEED_ERRORSTATE_PROCESS_UNKNOWN_FORMAT;
|
||||||
error = "Can't read document";
|
errorString = "Can't read document";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
result = RS_FEED_ERRORSTATE_PROCESS_INTERNAL_ERROR;
|
result = RS_FEED_ERRORSTATE_PROCESS_INTERNAL_ERROR;
|
||||||
|
errorString = xml.lastError();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FEEDREADER_DEBUG
|
#ifdef FEEDREADER_DEBUG
|
||||||
std::cerr << "p3FeedReaderThread::process - feed " << feed.feedId << " (" << feed.name << "), result " << result << ", error = " << error << std::endl;
|
std::cerr << "p3FeedReaderThread::process - feed " << feed.feedId << " (" << feed.name << "), result " << result << ", error = " << errorString << std::endl;
|
||||||
|
if (result == RS_FEED_ERRORSTATE_PROCESS_INTERNAL_ERROR) {
|
||||||
|
std::cerr << " Error: " << errorString << std::endl;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -1059,7 +1067,7 @@ RsFeedReaderErrorState p3FeedReaderThread::processMsg(const RsFeedReaderFeed &fe
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check if string contains xml chars (very simple test) */
|
/* check if string contains xml chars (very simple test) */
|
||||||
if (msg->description.find('<') == std::string::npos) {
|
if (msg->description.find('<') == std::string::npos && feed.transformationType == RS_FEED_TRANSFORMATION_TYPE_NONE) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1164,10 +1172,6 @@ RsFeedReaderErrorState p3FeedReaderThread::processMsg(const RsFeedReaderFeed &fe
|
||||||
}
|
}
|
||||||
nodesToDelete.clear();
|
nodesToDelete.clear();
|
||||||
|
|
||||||
if (isRunning() && !feed.preview) {
|
|
||||||
result = processXPath(feed.xpathsToUse.ids, feed.xpathsToRemove.ids, html, errorString);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isRunning() && result == RS_FEED_ERRORSTATE_OK) {
|
if (isRunning() && result == RS_FEED_ERRORSTATE_OK) {
|
||||||
unsigned int xpathCount;
|
unsigned int xpathCount;
|
||||||
unsigned int xpathIndex;
|
unsigned int xpathIndex;
|
||||||
|
@ -1241,8 +1245,10 @@ RsFeedReaderErrorState p3FeedReaderThread::processMsg(const RsFeedReaderFeed &fe
|
||||||
if (result == RS_FEED_ERRORSTATE_OK) {
|
if (result == RS_FEED_ERRORSTATE_OK) {
|
||||||
if (isRunning()) {
|
if (isRunning()) {
|
||||||
if (!html.saveHTML(msg->description)) {
|
if (!html.saveHTML(msg->description)) {
|
||||||
|
errorString = html.lastError();
|
||||||
#ifdef FEEDREADER_DEBUG
|
#ifdef FEEDREADER_DEBUG
|
||||||
std::cerr << "p3FeedReaderThread::processHTML - feed " << feed.feedId << " (" << feed.name << ") cannot dump html" << std::endl;
|
std::cerr << "p3FeedReaderThread::processHTML - feed " << feed.feedId << " (" << feed.name << ") cannot dump html" << std::endl;
|
||||||
|
std::cerr << " Error: " << errorString << std::endl;
|
||||||
#endif
|
#endif
|
||||||
result = RS_FEED_ERRORSTATE_PROCESS_INTERNAL_ERROR;
|
result = RS_FEED_ERRORSTATE_PROCESS_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -1255,8 +1261,10 @@ RsFeedReaderErrorState p3FeedReaderThread::processMsg(const RsFeedReaderFeed &fe
|
||||||
result = RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR;
|
result = RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
errorString = html.lastError();
|
||||||
#ifdef FEEDREADER_DEBUG
|
#ifdef FEEDREADER_DEBUG
|
||||||
std::cerr << "p3FeedReaderThread::processHTML - feed " << feed.feedId << " (" << feed.name << ") cannot read html" << std::endl;
|
std::cerr << "p3FeedReaderThread::processHTML - feed " << feed.feedId << " (" << feed.name << ") cannot read html" << std::endl;
|
||||||
|
std::cerr << " Error: " << errorString << std::endl;
|
||||||
#endif
|
#endif
|
||||||
result = RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR;
|
result = RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -1265,6 +1273,30 @@ RsFeedReaderErrorState p3FeedReaderThread::processMsg(const RsFeedReaderFeed &fe
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RsFeedReaderErrorState p3FeedReaderThread::processTransformation(const RsFeedReaderFeed &feed, RsFeedReaderMsg *msg, std::string &errorString)
|
||||||
|
{
|
||||||
|
RsFeedReaderErrorState result = RS_FEED_ERRORSTATE_OK;
|
||||||
|
|
||||||
|
switch (feed.transformationType) {
|
||||||
|
case RS_FEED_TRANSFORMATION_TYPE_NONE:
|
||||||
|
break;
|
||||||
|
case RS_FEED_TRANSFORMATION_TYPE_XPATH:
|
||||||
|
msg->descriptionTransformed = msg->description;
|
||||||
|
result = processXPath(feed.xpathsToUse.ids, feed.xpathsToRemove.ids, msg->descriptionTransformed, errorString);
|
||||||
|
break;
|
||||||
|
case RS_FEED_TRANSFORMATION_TYPE_XSLT:
|
||||||
|
msg->descriptionTransformed = msg->description;
|
||||||
|
result = processXslt(feed.xslt, msg->descriptionTransformed, errorString);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg->descriptionTransformed == msg->description) {
|
||||||
|
msg->descriptionTransformed.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
RsFeedReaderErrorState p3FeedReaderThread::processXPath(const std::list<std::string> &xpathsToUse, const std::list<std::string> &xpathsToRemove, HTMLWrapper &html, std::string &errorString)
|
RsFeedReaderErrorState p3FeedReaderThread::processXPath(const std::list<std::string> &xpathsToUse, const std::list<std::string> &xpathsToRemove, HTMLWrapper &html, std::string &errorString)
|
||||||
{
|
{
|
||||||
long todo_fill_errorString;
|
long todo_fill_errorString;
|
||||||
|
@ -1376,8 +1408,6 @@ RsFeedReaderErrorState p3FeedReaderThread::processXPath(const std::list<std::str
|
||||||
|
|
||||||
RsFeedReaderErrorState result = RS_FEED_ERRORSTATE_OK;
|
RsFeedReaderErrorState result = RS_FEED_ERRORSTATE_OK;
|
||||||
|
|
||||||
long todo_fill_errorString;
|
|
||||||
|
|
||||||
/* process description */
|
/* process description */
|
||||||
long todo; // encoding
|
long todo; // encoding
|
||||||
HTMLWrapper html;
|
HTMLWrapper html;
|
||||||
|
@ -1388,8 +1418,10 @@ RsFeedReaderErrorState p3FeedReaderThread::processXPath(const std::list<std::str
|
||||||
|
|
||||||
if (result == RS_FEED_ERRORSTATE_OK) {
|
if (result == RS_FEED_ERRORSTATE_OK) {
|
||||||
if (!html.saveHTML(description)) {
|
if (!html.saveHTML(description)) {
|
||||||
|
errorString = html.lastError();
|
||||||
#ifdef FEEDREADER_DEBUG
|
#ifdef FEEDREADER_DEBUG
|
||||||
std::cerr << "p3FeedReaderThread::processXPath - cannot dump html" << std::endl;
|
std::cerr << "p3FeedReaderThread::processXPath - cannot dump html" << std::endl;
|
||||||
|
std::cerr << " Error: " << errorString << std::endl;
|
||||||
#endif
|
#endif
|
||||||
result = RS_FEED_ERRORSTATE_PROCESS_INTERNAL_ERROR;
|
result = RS_FEED_ERRORSTATE_PROCESS_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -1398,11 +1430,131 @@ RsFeedReaderErrorState p3FeedReaderThread::processXPath(const std::list<std::str
|
||||||
#ifdef FEEDREADER_DEBUG
|
#ifdef FEEDREADER_DEBUG
|
||||||
std::cerr << "p3FeedReaderThread::processXPath - no root element" << std::endl;
|
std::cerr << "p3FeedReaderThread::processXPath - no root element" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
errorString = "No root element found";
|
||||||
result = RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR;
|
result = RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
errorString = html.lastError();
|
||||||
#ifdef FEEDREADER_DEBUG
|
#ifdef FEEDREADER_DEBUG
|
||||||
std::cerr << "p3FeedReaderThread::processXPath - cannot read html" << std::endl;
|
std::cerr << "p3FeedReaderThread::processXPath - cannot read html" << std::endl;
|
||||||
|
std::cerr << " Error: " << errorString << std::endl;
|
||||||
|
#endif
|
||||||
|
result = RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
RsFeedReaderErrorState p3FeedReaderThread::processXslt(const std::string &xslt, HTMLWrapper &html, std::string &errorString)
|
||||||
|
{
|
||||||
|
XMLWrapper style;
|
||||||
|
if (!style.readXML(xslt.c_str())) {
|
||||||
|
errorString = style.lastError();
|
||||||
|
#ifdef FEEDREADER_DEBUG
|
||||||
|
std::cerr << "p3FeedReaderThread::processXslt - error loading style" << std::endl;
|
||||||
|
std::cerr << " Error: " << errorString << std::endl;
|
||||||
|
#endif
|
||||||
|
return RS_FEED_ERRORSTATE_PROCESS_XSLT_FORMAT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
XMLWrapper xmlResult;
|
||||||
|
if (!html.transform(style, xmlResult)) {
|
||||||
|
errorString = html.lastError();
|
||||||
|
#ifdef FEEDREADER_DEBUG
|
||||||
|
std::cerr << "p3FeedReaderThread::processXslt - error transform" << std::endl;
|
||||||
|
std::cerr << " Error: " << errorString << std::endl;
|
||||||
|
#endif
|
||||||
|
return RS_FEED_ERRORSTATE_PROCESS_XSLT_TRANSFORM_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
RsFeedReaderErrorState result = RS_FEED_ERRORSTATE_OK;
|
||||||
|
|
||||||
|
xmlNodePtr root = xmlResult.getRootElement();
|
||||||
|
if (root) {
|
||||||
|
if (xmlResult.nodeName(root) == "html") {
|
||||||
|
if (root->children && xmlResult.nodeName(root->children) == "body") {
|
||||||
|
root = root->children->children;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HTMLWrapper htmlNew;
|
||||||
|
if (htmlNew.createHTML()) {
|
||||||
|
xmlNodePtr body = htmlNew.getBody();
|
||||||
|
if (body) {
|
||||||
|
/* copy result nodes */
|
||||||
|
xmlNodePtr node;
|
||||||
|
for (node = root; node; node = node->next) {
|
||||||
|
xmlNodePtr newNode = xmlCopyNode(node, 1);
|
||||||
|
if (newNode) {
|
||||||
|
if (!xmlAddChild(body, newNode)) {
|
||||||
|
xmlFreeNode(newNode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = RS_FEED_ERRORSTATE_PROCESS_INTERNAL_ERROR;
|
||||||
|
#ifdef FEEDREADER_DEBUG
|
||||||
|
std::cerr << "p3FeedReaderThread::processXslt - node copy error" << std::endl;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == RS_FEED_ERRORSTATE_OK) {
|
||||||
|
html = htmlNew;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
#ifdef FEEDREADER_DEBUG
|
||||||
|
std::cerr << "p3FeedReaderThread::processXslt - no result" << std::endl;
|
||||||
|
#endif
|
||||||
|
result = RS_FEED_ERRORSTATE_PROCESS_XSLT_NO_RESULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
RsFeedReaderErrorState p3FeedReaderThread::processXslt(const std::string &xslt, std::string &description, std::string &errorString)
|
||||||
|
{
|
||||||
|
if (xslt.empty()) {
|
||||||
|
return RS_FEED_ERRORSTATE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
RsFeedReaderErrorState result = RS_FEED_ERRORSTATE_OK;
|
||||||
|
|
||||||
|
/* process description */
|
||||||
|
long todo; // encoding
|
||||||
|
HTMLWrapper html;
|
||||||
|
if (html.readHTML(description.c_str(), "")) {
|
||||||
|
xmlNodePtr root = html.getRootElement();
|
||||||
|
if (root) {
|
||||||
|
result = processXslt(xslt, html, errorString);
|
||||||
|
|
||||||
|
if (result == RS_FEED_ERRORSTATE_OK) {
|
||||||
|
if (!html.saveHTML(description)) {
|
||||||
|
errorString = html.lastError();
|
||||||
|
#ifdef FEEDREADER_DEBUG
|
||||||
|
std::cerr << "p3FeedReaderThread::processXslt - cannot dump html" << std::endl;
|
||||||
|
std::cerr << " Error: " << errorString << std::endl;
|
||||||
|
#endif
|
||||||
|
result = RS_FEED_ERRORSTATE_PROCESS_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
#ifdef FEEDREADER_DEBUG
|
||||||
|
std::cerr << "p3FeedReaderThread::processXslt - no root element" << std::endl;
|
||||||
|
#endif
|
||||||
|
errorString = "No root element found";
|
||||||
|
result = RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
errorString = html.lastError();
|
||||||
|
#ifdef FEEDREADER_DEBUG
|
||||||
|
std::cerr << "p3FeedReaderThread::processXslt - cannot read html" << std::endl;
|
||||||
|
std::cerr << " Error: " << errorString << std::endl;
|
||||||
#endif
|
#endif
|
||||||
result = RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR;
|
result = RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,11 +51,15 @@ public:
|
||||||
static RsFeedReaderErrorState processXPath(const std::list<std::string> &xpathsToUse, const std::list<std::string> &xpathsToRemove, std::string &description, std::string &errorString);
|
static RsFeedReaderErrorState processXPath(const std::list<std::string> &xpathsToUse, const std::list<std::string> &xpathsToRemove, std::string &description, std::string &errorString);
|
||||||
static RsFeedReaderErrorState processXPath(const std::list<std::string> &xpathsToUse, const std::list<std::string> &xpathsToRemove, HTMLWrapper &html, std::string &errorString);
|
static RsFeedReaderErrorState processXPath(const std::list<std::string> &xpathsToUse, const std::list<std::string> &xpathsToRemove, HTMLWrapper &html, std::string &errorString);
|
||||||
|
|
||||||
|
static RsFeedReaderErrorState processXslt(const std::string &xslt, std::string &description, std::string &errorString);
|
||||||
|
static RsFeedReaderErrorState processXslt(const std::string &xslt, HTMLWrapper &html, std::string &errorString);
|
||||||
|
|
||||||
|
static RsFeedReaderErrorState processTransformation(const RsFeedReaderFeed &feed, RsFeedReaderMsg *msg, std::string &errorString);
|
||||||
private:
|
private:
|
||||||
virtual void run();
|
virtual void run();
|
||||||
|
|
||||||
RsFeedReaderErrorState download(const RsFeedReaderFeed &feed, std::string &content, std::string &icon, std::string &error);
|
RsFeedReaderErrorState download(const RsFeedReaderFeed &feed, std::string &content, std::string &icon, std::string &errorString);
|
||||||
RsFeedReaderErrorState process(const RsFeedReaderFeed &feed, std::list<RsFeedReaderMsg*> &entries, std::string &error);
|
RsFeedReaderErrorState process(const RsFeedReaderFeed &feed, std::list<RsFeedReaderMsg*> &entries, std::string &errorString);
|
||||||
|
|
||||||
std::string getProxyForFeed(const RsFeedReaderFeed &feed);
|
std::string getProxyForFeed(const RsFeedReaderFeed &feed);
|
||||||
RsFeedReaderErrorState processMsg(const RsFeedReaderFeed &feed, RsFeedReaderMsg *msg, std::string &errorString);
|
RsFeedReaderErrorState processMsg(const RsFeedReaderFeed &feed, RsFeedReaderMsg *msg, std::string &errorString);
|
||||||
|
|
|
@ -51,8 +51,10 @@ void RsFeedReaderFeed::clear()
|
||||||
icon.clear();
|
icon.clear();
|
||||||
errorState = RS_FEED_ERRORSTATE_OK;
|
errorState = RS_FEED_ERRORSTATE_OK;
|
||||||
errorString.clear();
|
errorString.clear();
|
||||||
|
transformationType = RS_FEED_TRANSFORMATION_TYPE_NONE;
|
||||||
xpathsToUse.ids.clear();
|
xpathsToUse.ids.clear();
|
||||||
xpathsToRemove.ids.clear();
|
xpathsToRemove.ids.clear();
|
||||||
|
xslt.clear();
|
||||||
|
|
||||||
preview = false;
|
preview = false;
|
||||||
workstate = WAITING;
|
workstate = WAITING;
|
||||||
|
@ -85,8 +87,10 @@ uint32_t RsFeedReaderSerialiser::sizeFeed(RsFeedReaderFeed *item)
|
||||||
s += GetTlvStringSize(item->forumId);
|
s += GetTlvStringSize(item->forumId);
|
||||||
s += sizeof(uint32_t); /* errorstate */
|
s += sizeof(uint32_t); /* errorstate */
|
||||||
s += GetTlvStringSize(item->errorString);
|
s += GetTlvStringSize(item->errorString);
|
||||||
|
s += sizeof(uint32_t); /* transformationType */
|
||||||
s += item->xpathsToUse.TlvSize();
|
s += item->xpathsToUse.TlvSize();
|
||||||
s += item->xpathsToRemove.TlvSize();
|
s += item->xpathsToRemove.TlvSize();
|
||||||
|
s += GetTlvStringSize(item->xslt);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
@ -110,7 +114,7 @@ bool RsFeedReaderSerialiser::serialiseFeed(RsFeedReaderFeed *item, void *data, u
|
||||||
offset += 8;
|
offset += 8;
|
||||||
|
|
||||||
/* add values */
|
/* add values */
|
||||||
ok &= setRawUInt16(data, tlvsize, &offset, 0); /* version */
|
ok &= setRawUInt16(data, tlvsize, &offset, 1); /* version */
|
||||||
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_GENID, item->feedId);
|
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_GENID, item->feedId);
|
||||||
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->parentId);
|
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->parentId);
|
||||||
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_LINK, item->url);
|
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_LINK, item->url);
|
||||||
|
@ -128,8 +132,10 @@ bool RsFeedReaderSerialiser::serialiseFeed(RsFeedReaderFeed *item, void *data, u
|
||||||
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->forumId);
|
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->forumId);
|
||||||
ok &= setRawUInt32(data, tlvsize, &offset, item->errorState);
|
ok &= setRawUInt32(data, tlvsize, &offset, item->errorState);
|
||||||
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->errorString);
|
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->errorString);
|
||||||
|
ok &= setRawUInt32(data, tlvsize, &offset, item->transformationType);
|
||||||
ok &= item->xpathsToUse.SetTlv(data, tlvsize, &offset);
|
ok &= item->xpathsToUse.SetTlv(data, tlvsize, &offset);
|
||||||
ok &= item->xpathsToRemove.SetTlv(data, tlvsize, &offset);
|
ok &= item->xpathsToRemove.SetTlv(data, tlvsize, &offset);
|
||||||
|
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->xslt);
|
||||||
|
|
||||||
if (offset != tlvsize)
|
if (offset != tlvsize)
|
||||||
{
|
{
|
||||||
|
@ -192,9 +198,28 @@ RsFeedReaderFeed *RsFeedReaderSerialiser::deserialiseFeed(void *data, uint32_t *
|
||||||
ok &= getRawUInt32(data, rssize, &offset, &errorState);
|
ok &= getRawUInt32(data, rssize, &offset, &errorState);
|
||||||
item->errorState = (RsFeedReaderErrorState) errorState;
|
item->errorState = (RsFeedReaderErrorState) errorState;
|
||||||
ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_VALUE, item->errorString);
|
ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_VALUE, item->errorString);
|
||||||
|
if (version >= 1) {
|
||||||
|
uint32_t value = RS_FEED_TRANSFORMATION_TYPE_NONE;
|
||||||
|
ok &= getRawUInt32(data, rssize, &offset, &value);
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
item->transformationType = (RsFeedTransformationType) value;
|
||||||
|
}
|
||||||
|
}
|
||||||
ok &= item->xpathsToUse.GetTlv(data, rssize, &offset);
|
ok &= item->xpathsToUse.GetTlv(data, rssize, &offset);
|
||||||
ok &= item->xpathsToRemove.GetTlv(data, rssize, &offset);
|
ok &= item->xpathsToRemove.GetTlv(data, rssize, &offset);
|
||||||
|
if (version >= 1) {
|
||||||
|
ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_VALUE, item->xslt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version == 0)
|
||||||
|
{
|
||||||
|
if (!item->xpathsToUse.ids.empty() || !item->xpathsToRemove.ids.empty())
|
||||||
|
{
|
||||||
|
/* set transformation type */
|
||||||
|
item->transformationType = RS_FEED_TRANSFORMATION_TYPE_XPATH;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (offset != rssize)
|
if (offset != rssize)
|
||||||
{
|
{
|
||||||
/* error */
|
/* error */
|
||||||
|
@ -226,6 +251,7 @@ void RsFeedReaderMsg::clear()
|
||||||
link.clear();
|
link.clear();
|
||||||
author.clear();
|
author.clear();
|
||||||
description.clear();
|
description.clear();
|
||||||
|
descriptionTransformed.clear();
|
||||||
pubDate = 0;
|
pubDate = 0;
|
||||||
flag = 0;
|
flag = 0;
|
||||||
}
|
}
|
||||||
|
@ -245,6 +271,7 @@ uint32_t RsFeedReaderSerialiser::sizeMsg(RsFeedReaderMsg *item)
|
||||||
s += GetTlvStringSize(item->link);
|
s += GetTlvStringSize(item->link);
|
||||||
s += GetTlvStringSize(item->author);
|
s += GetTlvStringSize(item->author);
|
||||||
s += GetTlvStringSize(item->description);
|
s += GetTlvStringSize(item->description);
|
||||||
|
s += GetTlvStringSize(item->descriptionTransformed);
|
||||||
s += sizeof(time_t); /* pubDate */
|
s += sizeof(time_t); /* pubDate */
|
||||||
s += sizeof(uint32_t); /* flag */
|
s += sizeof(uint32_t); /* flag */
|
||||||
|
|
||||||
|
@ -270,13 +297,14 @@ bool RsFeedReaderSerialiser::serialiseMsg(RsFeedReaderMsg *item, void *data, uin
|
||||||
offset += 8;
|
offset += 8;
|
||||||
|
|
||||||
/* add values */
|
/* add values */
|
||||||
ok &= setRawUInt16(data, tlvsize, &offset, 0); /* version */
|
ok &= setRawUInt16(data, tlvsize, &offset, 1); /* version */
|
||||||
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_GENID, item->msgId);
|
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_GENID, item->msgId);
|
||||||
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->feedId);
|
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->feedId);
|
||||||
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_NAME, item->title);
|
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_NAME, item->title);
|
||||||
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_LINK, item->link);
|
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_LINK, item->link);
|
||||||
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->author);
|
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->author);
|
||||||
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_COMMENT, item->description);
|
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_COMMENT, item->description);
|
||||||
|
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_COMMENT, item->descriptionTransformed);
|
||||||
ok &= setRawUInt32(data, tlvsize, &offset, item->pubDate);
|
ok &= setRawUInt32(data, tlvsize, &offset, item->pubDate);
|
||||||
ok &= setRawUInt32(data, tlvsize, &offset, item->flag);
|
ok &= setRawUInt32(data, tlvsize, &offset, item->flag);
|
||||||
|
|
||||||
|
@ -328,6 +356,9 @@ RsFeedReaderMsg *RsFeedReaderSerialiser::deserialiseMsg(void *data, uint32_t *pk
|
||||||
ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_LINK, item->link);
|
ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_LINK, item->link);
|
||||||
ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_VALUE, item->author);
|
ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_VALUE, item->author);
|
||||||
ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_COMMENT, item->description);
|
ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_COMMENT, item->description);
|
||||||
|
if (version >= 1) {
|
||||||
|
ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_COMMENT, item->descriptionTransformed);
|
||||||
|
}
|
||||||
ok &= getRawUInt32(data, rssize, &offset, (uint32_t*) &(item->pubDate));
|
ok &= getRawUInt32(data, rssize, &offset, (uint32_t*) &(item->pubDate));
|
||||||
ok &= getRawUInt32(data, rssize, &offset, &(item->flag));
|
ok &= getRawUInt32(data, rssize, &offset, &(item->flag));
|
||||||
|
|
||||||
|
|
|
@ -65,26 +65,28 @@ public:
|
||||||
virtual void clear();
|
virtual void clear();
|
||||||
virtual std::ostream& print(std::ostream &out, uint16_t indent = 0);
|
virtual std::ostream& print(std::ostream &out, uint16_t indent = 0);
|
||||||
|
|
||||||
std::string feedId;
|
std::string feedId;
|
||||||
std::string parentId;
|
std::string parentId;
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string url;
|
std::string url;
|
||||||
std::string user;
|
std::string user;
|
||||||
std::string password;
|
std::string password;
|
||||||
std::string proxyAddress;
|
std::string proxyAddress;
|
||||||
uint16_t proxyPort;
|
uint16_t proxyPort;
|
||||||
uint32_t updateInterval;
|
uint32_t updateInterval;
|
||||||
time_t lastUpdate;
|
time_t lastUpdate;
|
||||||
uint32_t flag; // RS_FEED_FLAG_...
|
uint32_t flag; // RS_FEED_FLAG_...
|
||||||
std::string forumId;
|
std::string forumId;
|
||||||
uint32_t storageTime;
|
uint32_t storageTime;
|
||||||
std::string description;
|
std::string description;
|
||||||
std::string icon;
|
std::string icon;
|
||||||
RsFeedReaderErrorState errorState;
|
RsFeedReaderErrorState errorState;
|
||||||
std::string errorString;
|
std::string errorString;
|
||||||
|
|
||||||
RsTlvStringSet xpathsToUse;
|
RsFeedTransformationType transformationType;
|
||||||
RsTlvStringSet xpathsToRemove;
|
RsTlvStringSet xpathsToUse;
|
||||||
|
RsTlvStringSet xpathsToRemove;
|
||||||
|
std::string xslt;
|
||||||
|
|
||||||
/* Not Serialised */
|
/* Not Serialised */
|
||||||
bool preview;
|
bool preview;
|
||||||
|
@ -113,6 +115,7 @@ public:
|
||||||
std::string link;
|
std::string link;
|
||||||
std::string author;
|
std::string author;
|
||||||
std::string description;
|
std::string description;
|
||||||
|
std::string descriptionTransformed;
|
||||||
time_t pubDate;
|
time_t pubDate;
|
||||||
uint32_t flag; // RS_FEEDMSG_FLAG_...
|
uint32_t flag; // RS_FEEDMSG_FLAG_...
|
||||||
};
|
};
|
||||||
|
|
|
@ -32,7 +32,10 @@ bool HTMLWrapper::readHTML(const char *html, const char *url)
|
||||||
{
|
{
|
||||||
cleanup();
|
cleanup();
|
||||||
|
|
||||||
mDocument = htmlReadMemory(html, strlen(html), url, "", HTML_PARSE_NOERROR | HTML_PARSE_NOWARNING | HTML_PARSE_COMPACT | HTML_PARSE_NONET | HTML_PARSE_NOBLANKS);
|
handleError(true, mLastErrorString);
|
||||||
|
mDocument = htmlReadMemory(html, strlen(html), url, "", /*HTML_PARSE_NOERROR | HTML_PARSE_NOWARNING | */HTML_PARSE_COMPACT | HTML_PARSE_NONET | HTML_PARSE_NOBLANKS);
|
||||||
|
handleError(false, mLastErrorString);
|
||||||
|
|
||||||
if (mDocument) {
|
if (mDocument) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -48,7 +51,10 @@ bool HTMLWrapper::saveHTML(std::string &html)
|
||||||
|
|
||||||
xmlChar *newHtml = NULL;
|
xmlChar *newHtml = NULL;
|
||||||
int newHtmlSize = 0;
|
int newHtmlSize = 0;
|
||||||
|
handleError(true, mLastErrorString);
|
||||||
htmlDocDumpMemoryFormat(mDocument, &newHtml, &newHtmlSize, 0);
|
htmlDocDumpMemoryFormat(mDocument, &newHtml, &newHtmlSize, 0);
|
||||||
|
handleError(false, mLastErrorString);
|
||||||
|
|
||||||
if (newHtml) {
|
if (newHtml) {
|
||||||
convertToString(newHtml, html);
|
convertToString(newHtml, html);
|
||||||
xmlFree(newHtml);
|
xmlFree(newHtml);
|
||||||
|
|
|
@ -25,6 +25,14 @@
|
||||||
#include "XMLWrapper.h"
|
#include "XMLWrapper.h"
|
||||||
#include "XPathWrapper.h"
|
#include "XPathWrapper.h"
|
||||||
|
|
||||||
|
#include <util/rsstring.h>
|
||||||
|
#include <util/rsthreads.h>
|
||||||
|
#include <libxslt/transform.h>
|
||||||
|
#include <libxslt/xsltutils.h>
|
||||||
|
|
||||||
|
static RsMutex xmlMtx("XMLWrapper");
|
||||||
|
static std::string xmlErrorString;
|
||||||
|
|
||||||
XMLWrapper::XMLWrapper()
|
XMLWrapper::XMLWrapper()
|
||||||
{
|
{
|
||||||
mDocument = NULL;
|
mDocument = NULL;
|
||||||
|
@ -42,6 +50,35 @@ XMLWrapper::~XMLWrapper()
|
||||||
xmlCharEncCloseFunc(mCharEncodingHandler);
|
xmlCharEncCloseFunc(mCharEncodingHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void xmlErrorHandler(void */*context*/, const char *msg, ...)
|
||||||
|
{
|
||||||
|
va_list vl;
|
||||||
|
|
||||||
|
va_start(vl, msg);
|
||||||
|
rs_sprintf_append_args(xmlErrorString, msg, vl);
|
||||||
|
va_end(vl);
|
||||||
|
}
|
||||||
|
|
||||||
|
void XMLWrapper::handleError(bool init, std::string &errorString)
|
||||||
|
{
|
||||||
|
if (init) {
|
||||||
|
xmlMtx.lock();
|
||||||
|
xmlErrorString.clear();
|
||||||
|
errorString.clear();
|
||||||
|
|
||||||
|
xsltSetGenericErrorFunc(this, xmlErrorHandler);
|
||||||
|
xmlSetGenericErrorFunc(this, xmlErrorHandler);
|
||||||
|
} else {
|
||||||
|
xsltSetGenericErrorFunc(NULL, NULL);
|
||||||
|
xmlSetGenericErrorFunc(NULL, NULL);
|
||||||
|
|
||||||
|
errorString = xmlErrorString;
|
||||||
|
xmlErrorString.clear();
|
||||||
|
|
||||||
|
xmlMtx.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void XMLWrapper::trimString(std::string &string)
|
void XMLWrapper::trimString(std::string &string)
|
||||||
{
|
{
|
||||||
/* trim left */
|
/* trim left */
|
||||||
|
@ -59,7 +96,6 @@ void XMLWrapper::trimString(std::string &string)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
XMLWrapper &XMLWrapper::operator=(const XMLWrapper &xml)
|
XMLWrapper &XMLWrapper::operator=(const XMLWrapper &xml)
|
||||||
{
|
{
|
||||||
cleanup();
|
cleanup();
|
||||||
|
@ -80,6 +116,13 @@ void XMLWrapper::cleanup()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void XMLWrapper::attach(xmlDocPtr document)
|
||||||
|
{
|
||||||
|
cleanup();
|
||||||
|
|
||||||
|
mDocument = document;
|
||||||
|
}
|
||||||
|
|
||||||
bool XMLWrapper::convertToString(const xmlChar *xmlText, std::string &text)
|
bool XMLWrapper::convertToString(const xmlChar *xmlText, std::string &text)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
@ -138,7 +181,10 @@ bool XMLWrapper::readXML(const char *xml)
|
||||||
{
|
{
|
||||||
cleanup();
|
cleanup();
|
||||||
|
|
||||||
mDocument = xmlReadDoc(BAD_CAST xml, "", NULL, XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_COMPACT | XML_PARSE_NOENT | XML_PARSE_NOCDATA);
|
handleError(true, mLastErrorString);
|
||||||
|
mDocument = xmlReadDoc(BAD_CAST xml, "", NULL, /*XML_PARSE_NOERROR | XML_PARSE_NOWARNING | */XML_PARSE_COMPACT | XML_PARSE_NOENT | XML_PARSE_NOCDATA);
|
||||||
|
handleError(false, mLastErrorString);
|
||||||
|
|
||||||
if (mDocument) {
|
if (mDocument) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -358,3 +404,23 @@ XPathWrapper *XMLWrapper::createXPath()
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool XMLWrapper::transform(const XMLWrapper &style, XMLWrapper &result)
|
||||||
|
{
|
||||||
|
handleError(true, mLastErrorString);
|
||||||
|
|
||||||
|
xmlDocPtr resultDoc = NULL;
|
||||||
|
|
||||||
|
xsltStylesheetPtr stylesheet = xsltParseStylesheetDoc(style.getDocument());
|
||||||
|
if (stylesheet) {
|
||||||
|
resultDoc = xsltApplyStylesheet(stylesheet, getDocument(), NULL);
|
||||||
|
stylesheet->doc = NULL; // xsltFreeStylesheet is freeing doc
|
||||||
|
xsltFreeStylesheet(stylesheet);
|
||||||
|
}
|
||||||
|
|
||||||
|
result.attach(resultDoc);
|
||||||
|
|
||||||
|
handleError(false, mLastErrorString);
|
||||||
|
|
||||||
|
return resultDoc ? true : false;
|
||||||
|
}
|
||||||
|
|
|
@ -39,12 +39,16 @@ public:
|
||||||
XMLWrapper &operator=(const XMLWrapper &xml);
|
XMLWrapper &operator=(const XMLWrapper &xml);
|
||||||
|
|
||||||
void cleanup();
|
void cleanup();
|
||||||
|
std::string lastError() { return mLastErrorString; }
|
||||||
|
|
||||||
bool readXML(const char *xml);
|
bool readXML(const char *xml);
|
||||||
|
|
||||||
xmlDocPtr getDocument() const;
|
xmlDocPtr getDocument() const;
|
||||||
xmlNodePtr getRootElement() const;
|
xmlNodePtr getRootElement() const;
|
||||||
|
|
||||||
|
bool convertToString(const xmlChar *xmlText, std::string &text);
|
||||||
|
bool convertFromString(const char *text, xmlChar *&xmlText);
|
||||||
|
|
||||||
std::string nodeName(xmlNodePtr node);
|
std::string nodeName(xmlNodePtr node);
|
||||||
std::string attrName(xmlAttrPtr attr);
|
std::string attrName(xmlAttrPtr attr);
|
||||||
|
|
||||||
|
@ -62,12 +66,16 @@ public:
|
||||||
|
|
||||||
XPathWrapper *createXPath();
|
XPathWrapper *createXPath();
|
||||||
|
|
||||||
bool convertToString(const xmlChar *xmlText, std::string &text);
|
bool transform(const XMLWrapper &style, XMLWrapper &result);
|
||||||
bool convertFromString(const char *text, xmlChar *&xmlText);
|
|
||||||
|
protected:
|
||||||
|
void attach(xmlDocPtr document);
|
||||||
|
void handleError(bool init, std::string &errorString);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
xmlDocPtr mDocument;
|
xmlDocPtr mDocument;
|
||||||
xmlCharEncodingHandlerPtr mCharEncodingHandler;
|
xmlCharEncodingHandlerPtr mCharEncodingHandler;
|
||||||
|
std::string mLastErrorString;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
54
retroshare-gui/src/gui/common/RSPlainTextEdit.cpp
Normal file
54
retroshare-gui/src/gui/common/RSPlainTextEdit.cpp
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
/****************************************************************
|
||||||
|
*
|
||||||
|
* RetroShare is distributed under the following license:
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013, RetroShare Team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
****************************************************************/
|
||||||
|
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
|
#include "RSPlainTextEdit.h"
|
||||||
|
|
||||||
|
RSPlainTextEdit::RSPlainTextEdit(QWidget *parent)
|
||||||
|
: QPlainTextEdit(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void RSPlainTextEdit::setPlaceholderText(const QString &text)
|
||||||
|
{
|
||||||
|
mPlaceholderText = text;
|
||||||
|
viewport()->repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RSPlainTextEdit::paintEvent(QPaintEvent *event)
|
||||||
|
{
|
||||||
|
QPlainTextEdit::paintEvent(event);
|
||||||
|
|
||||||
|
if (mPlaceholderText.isEmpty() == false && toPlainText().isEmpty()) {
|
||||||
|
QWidget *vieportWidget = viewport();
|
||||||
|
QPainter painter(vieportWidget);
|
||||||
|
|
||||||
|
QPen pen = painter.pen();
|
||||||
|
QColor color = pen.color();
|
||||||
|
color.setAlpha(128);
|
||||||
|
pen.setColor(color);
|
||||||
|
painter.setPen(pen);
|
||||||
|
|
||||||
|
painter.drawText(QRect(QPoint(), vieportWidget->size()), Qt::AlignHCenter | Qt::AlignVCenter | Qt::TextWordWrap, mPlaceholderText);
|
||||||
|
}
|
||||||
|
}
|
44
retroshare-gui/src/gui/common/RSPlainTextEdit.h
Normal file
44
retroshare-gui/src/gui/common/RSPlainTextEdit.h
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
/****************************************************************
|
||||||
|
*
|
||||||
|
* RetroShare is distributed under the following license:
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013, RetroShare Team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
****************************************************************/
|
||||||
|
|
||||||
|
#ifndef RSPLAINTEXTEDIT_H
|
||||||
|
#define RSPLAINTEXTEDIT_H
|
||||||
|
|
||||||
|
#include <QPlainTextEdit>
|
||||||
|
|
||||||
|
class RSPlainTextEdit : public QPlainTextEdit
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
RSPlainTextEdit(QWidget *parent = 0);
|
||||||
|
|
||||||
|
void setPlaceholderText(const QString &text);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void paintEvent(QPaintEvent *event);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString mPlaceholderText;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // RSPLAINTEXTEDIT_H
|
|
@ -397,6 +397,7 @@ HEADERS += rshare.h \
|
||||||
gui/common/GroupDefs.h \
|
gui/common/GroupDefs.h \
|
||||||
gui/common/Emoticons.h \
|
gui/common/Emoticons.h \
|
||||||
gui/common/RSListWidgetItem.h \
|
gui/common/RSListWidgetItem.h \
|
||||||
|
gui/common/RSPlainTextEdit.h \
|
||||||
gui/common/RSTreeWidget.h \
|
gui/common/RSTreeWidget.h \
|
||||||
gui/common/RSTreeWidgetItem.h \
|
gui/common/RSTreeWidgetItem.h \
|
||||||
gui/common/RSTabWidget.h \
|
gui/common/RSTabWidget.h \
|
||||||
|
@ -665,6 +666,7 @@ SOURCES += main.cpp \
|
||||||
gui/common/GroupDefs.cpp \
|
gui/common/GroupDefs.cpp \
|
||||||
gui/common/Emoticons.cpp \
|
gui/common/Emoticons.cpp \
|
||||||
gui/common/RSListWidgetItem.cpp \
|
gui/common/RSListWidgetItem.cpp \
|
||||||
|
gui/common/RSPlainTextEdit.cpp \
|
||||||
gui/common/RSTreeWidget.cpp \
|
gui/common/RSTreeWidget.cpp \
|
||||||
gui/common/RSTreeWidgetItem.cpp \
|
gui/common/RSTreeWidgetItem.cpp \
|
||||||
gui/common/RSTabWidget.cpp \
|
gui/common/RSTabWidget.cpp \
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue