From ea2ac1ddd74c1d97f094a4e56f2c038b5fef6351 Mon Sep 17 00:00:00 2001 From: "Javier S. Pedro" Date: Tue, 2 Apr 2013 18:36:21 +0200 Subject: add some support for smilies --- board.cpp | 61 +++++++++++++++++++++++++++++++++++++++++++--- board.h | 8 +++--- fetchboardconfigaction.cpp | 56 ------------------------------------------ fetchboardconfigaction.h | 25 ------------------- fetchconfigaction.cpp | 56 ++++++++++++++++++++++++++++++++++++++++++ fetchconfigaction.h | 25 +++++++++++++++++++ fetchpostsaction.cpp | 3 ++- tapasboard.pro | 32 ++++++++++++------------ 8 files changed, 161 insertions(+), 105 deletions(-) delete mode 100644 fetchboardconfigaction.cpp delete mode 100644 fetchboardconfigaction.h create mode 100644 fetchconfigaction.cpp create mode 100644 fetchconfigaction.h diff --git a/board.cpp b/board.cpp index 4275047..acb2b01 100644 --- a/board.cpp +++ b/board.cpp @@ -1,4 +1,3 @@ -#include #include #include #include @@ -6,7 +5,7 @@ #include "global.h" #include "action.h" -#include "fetchboardconfigaction.h" +#include "fetchconfigaction.h" #include "fetchforumsaction.h" #include "xmlrpcinterface.h" #include "board.h" @@ -38,10 +37,12 @@ Board::Board(const QString& forumUrl, QObject *parent) : fetchConfigIfOutdated(); fetchForumsIfOutdated(); initializeBbCode(); // TODO This might depend on board config + initializeSmilies(); } Board::~Board() { + disconnect(this, SLOT(handleActionFinished(Action*))); QSqlDatabase::removeDatabase(_slug); } @@ -144,6 +145,28 @@ QString Board::bbcodeToRichText(QString text) const return text; } +QString Board::parseSmilies(QString text) const +{ + int pos = 0; + text.append(' '); // So that the regexp matches a smilie at the end. + while ((pos = _smilieRegexp.indexIn(text, pos)) != -1) { + const int len = _smilieRegexp.matchedLength(); + QString smilie = _smilieRegexp.cap(1); + const int smilie_pos = _smilieRegexp.pos(1); + const int smilie_len = smilie.length(); + QHash::const_iterator i = _smilies.find(smilie); + if (i != _smilies.end()) { + QString replacement = ""; + text.replace(smilie_pos, smilie_len, replacement); + pos += replacement.size(); + } else { + pos += len - 1; + } + } + text.remove(text.length() - 1, 1); + return text; +} + QString Board::renderHumanDate(const QDateTime &dateTime) { QDate date = dateTime.toLocalTime().date(); @@ -346,6 +369,38 @@ void Board::initializeBbCode() _bbcodes << qMakePair(QRegExp("\n"), QString("
")); } +void Board::initializeSmilies() +{ + _smilies[":)"] = "image://theme/icon-s-messaging-smiley-happy"; + _smilies[":("] = "image://theme/icon-s-messaging-smiley-sad"; + _smilies[":D"] = "image://theme/icon-s-messaging-smiley-very-happy"; + _smilies["=D>"] = "image://theme/icon-s-messaging-smiley-very-happy"; + _smilies[":lol:"] = "image://theme/icon-s-messaging-smiley-very-happy"; + _smilies[";)"] = "image://theme/icon-s-messaging-smiley-wink"; + _smilies[";D"] = "image://theme/icon-s-messaging-smiley-wink"; + _smilies[":wink:"] = "image://theme/icon-s-messaging-smiley-wink"; + _smilies[":P"] = "image://theme/icon-s-messaging-smiley-tongue"; + _smilies[":p"] = "image://theme/icon-s-messaging-smiley-tongue"; + _smilies[":mrgreen:"] = "image://theme/icon-s-messaging-smiley-grin"; + _smilies["O_O"] = "image://theme/icon-s-messaging-smiley-surprised"; + _smilies["O_o"] = "image://theme/icon-s-messaging-smiley-surprised"; + + // Let's construct a single regular expression that will cover all smilies + QString regexp("[^A-Za-z]("); + for (QHash::const_iterator i = _smilies.begin(); + i != _smilies.end(); + i++) { + if (i != _smilies.begin()) { + regexp += "|"; + } + regexp += QRegExp::escape(i.key()); + } + regexp += ")[^A-Za-z]"; + qDebug() << "Smilie regexp: " << regexp; + _smilieRegexp = QRegExp(regexp); + Q_ASSERT(_smilieRegexp.isValid()); +} + void Board::fetchConfigIfOutdated() { if (_iface->isAccessible()) { @@ -353,7 +408,7 @@ void Board::fetchConfigIfOutdated() QDateTime last_fetch = QDateTime::fromString( getConfig("last_config_fetch"), Qt::ISODate); if (!last_fetch.isValid() || last_fetch.daysTo(QDateTime::currentDateTimeUtc()) >= BOARD_CONFIG_TTL) { - enqueueAction(new FetchBoardConfigAction(this)); + enqueueAction(new FetchConfigAction(this)); } } diff --git a/board.h b/board.h index 78ebf8a..deb1dfb 100644 --- a/board.h +++ b/board.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -34,6 +35,7 @@ public: QString removeHtml(QString text) const; QString removeBbcode(QString text) const; QString bbcodeToRichText(QString text) const; + QString parseSmilies(QString text) const; QString renderHumanDate(const QDateTime& dateTime); QString renderHumanTime(const QDateTime& dateTime); @@ -41,14 +43,12 @@ public: // These functions wrap emitting the signals below void notifyConfigChanged(const QString& key = QString()); void notifyForumsChanged(); - void notifySmiliesChanged(); void notifyForumTopicsChanged(int forumId, int start, int end); void notifyTopicPostsChanged(int topicId, int start, int end); signals: void configChanged(const QString& key); void forumsChanged(); - void smiliesChanged(); void forumTopicsChanged(int forumId, int start, int end); void topicPostsChanged(int topicId, int start, int end); @@ -66,7 +66,6 @@ private: void initializeSmilies(); void fetchConfigIfOutdated(); void fetchForumsIfOutdated(); - void fetchSmiliesIfOutdated(); private slots: void handleActionFinished(Action *action); @@ -81,7 +80,8 @@ private: /** Configuration cache */ mutable QHash _config; QList< QPair > _bbcodes; - QList< QPair > _smilies; + QHash _smilies; + QRegExp _smilieRegexp; }; inline bool Board::busy() const diff --git a/fetchboardconfigaction.cpp b/fetchboardconfigaction.cpp deleted file mode 100644 index 2364dd1..0000000 --- a/fetchboardconfigaction.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include -#include -#include - -#include "board.h" -#include "xmlrpcinterface.h" -#include "xmlrpcreply.h" -#include "fetchboardconfigaction.h" - -FetchBoardConfigAction::FetchBoardConfigAction(Board *board) : - Action(board) -{ -} - -bool FetchBoardConfigAction::isSupersetOf(Action *action) const -{ - // If 'action' is also a fetch board config action then yes, this supersets 'action'. - return qobject_cast(action) != 0; -} - -void FetchBoardConfigAction::execute() -{ - _call = _board->service()->asyncCall("get_config"); - connect(_call, SIGNAL(finished(XmlRpcPendingCall*)), SLOT(handleFinishedCall())); -} - -void FetchBoardConfigAction::handleFinishedCall() -{ - XmlRpcReply result(_call); - if (result.isValid()) { - QVariantMap map = result; - QSqlDatabase db = _board->database(); - db.transaction(); - QSqlQuery query(db); - - // Let's add some of our config settings - map["last_config_fetch"] = QDateTime::currentDateTimeUtc().toString(Qt::ISODate); - map["tapasboard_db_version"] = Board::CURRENT_DB_VERSION; - - query.prepare("INSERT OR REPLACE INTO config (key, value) VALUES (:key, :value)"); - for (QVariantMap::iterator i = map.begin(); i != map.end(); i++) { - query.bindValue(":key", i.key()); - query.bindValue(":value", i.value().toString()); - if (!query.exec()) { - qWarning() << "Failed to set config key:" << i.key(); - } - } - db.commit(); - _board->notifyConfigChanged(); - } else { - qWarning() << "Could not fetch board configuration"; - // TODO emit error ... - } - emit finished(this); - _call->deleteLater(); -} diff --git a/fetchboardconfigaction.h b/fetchboardconfigaction.h deleted file mode 100644 index 7f350f9..0000000 --- a/fetchboardconfigaction.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef FETCHBOARDCONFIGACTION_H -#define FETCHBOARDCONFIGACTION_H - -#include "action.h" - -class XmlRpcPendingCall; - -class FetchBoardConfigAction : public Action -{ - Q_OBJECT -public: - explicit FetchBoardConfigAction(Board *board); - - bool isSupersetOf(Action *action) const; - - void execute(); - -private slots: - void handleFinishedCall(); - -private: - XmlRpcPendingCall *_call; -}; - -#endif // FETCHBOARDCONFIGACTION_H diff --git a/fetchconfigaction.cpp b/fetchconfigaction.cpp new file mode 100644 index 0000000..8c0ac63 --- /dev/null +++ b/fetchconfigaction.cpp @@ -0,0 +1,56 @@ +#include +#include +#include + +#include "board.h" +#include "xmlrpcinterface.h" +#include "xmlrpcreply.h" +#include "fetchconfigaction.h" + +FetchConfigAction::FetchConfigAction(Board *board) : + Action(board) +{ +} + +bool FetchConfigAction::isSupersetOf(Action *action) const +{ + // If 'action' is also a fetch board config action then yes, this supersets 'action'. + return qobject_cast(action) != 0; +} + +void FetchConfigAction::execute() +{ + _call = _board->service()->asyncCall("get_config"); + connect(_call, SIGNAL(finished(XmlRpcPendingCall*)), SLOT(handleFinishedCall())); +} + +void FetchConfigAction::handleFinishedCall() +{ + XmlRpcReply result(_call); + if (result.isValid()) { + QVariantMap map = result; + QSqlDatabase db = _board->database(); + db.transaction(); + QSqlQuery query(db); + + // Let's add some of our config settings + map["last_config_fetch"] = QDateTime::currentDateTimeUtc().toString(Qt::ISODate); + map["tapasboard_db_version"] = Board::CURRENT_DB_VERSION; + + query.prepare("INSERT OR REPLACE INTO config (key, value) VALUES (:key, :value)"); + for (QVariantMap::iterator i = map.begin(); i != map.end(); i++) { + query.bindValue(":key", i.key()); + query.bindValue(":value", i.value().toString()); + if (!query.exec()) { + qWarning() << "Failed to set config key:" << i.key(); + } + } + db.commit(); + _board->notifyConfigChanged(); + } else { + qWarning() << "Could not fetch board configuration"; + // TODO emit error ... + } + emit finished(this); + _call->deleteLater(); +} diff --git a/fetchconfigaction.h b/fetchconfigaction.h new file mode 100644 index 0000000..44dbd3d --- /dev/null +++ b/fetchconfigaction.h @@ -0,0 +1,25 @@ +#ifndef FETCHCONFIGACTION_H +#define FETCHCONFIGACTION_H + +#include "action.h" + +class XmlRpcPendingCall; + +class FetchConfigAction : public Action +{ + Q_OBJECT +public: + explicit FetchConfigAction(Board *board); + + bool isSupersetOf(Action *action) const; + + void execute(); + +private slots: + void handleFinishedCall(); + +private: + XmlRpcPendingCall *_call; +}; + +#endif // FETCHCONFIGACTION_H diff --git a/fetchpostsaction.cpp b/fetchpostsaction.cpp index 426f766..7ed9140 100644 --- a/fetchpostsaction.cpp +++ b/fetchpostsaction.cpp @@ -99,5 +99,6 @@ QString FetchPostsAction::unencodePostText(const QVariant &v) QString FetchPostsAction::unencodePostContent(const QVariant &v) { - return _board->bbcodeToRichText(unencodePostText(v)); + QString richText = _board->bbcodeToRichText(unencodePostText(v)); + return _board->parseSmilies(richText); } diff --git a/tapasboard.pro b/tapasboard.pro index a1173d5..8430ba0 100644 --- a/tapasboard.pro +++ b/tapasboard.pro @@ -18,6 +18,7 @@ symbian:TARGET.UID3 = 0xE33C9CB4 # Allow network access on Symbian symbian:TARGET.CAPABILITY += NetworkServices +# Extra QT modules required QT += network sql # If your application uses the Qt Mobility libraries, uncomment the following @@ -31,12 +32,11 @@ CONFIG += qdeclarative-boostable # Add dependency to Symbian components # CONFIG += qt-components -# The .cpp file which was generated for your project. Feel free to hack it. SOURCES += main.cpp \ action.cpp \ board.cpp \ boardmanager.cpp \ - fetchboardconfigaction.cpp \ + fetchconfigaction.cpp \ xmlrpcinterface.cpp \ xmlrpcpendingcall.cpp \ fetchforumsaction.cpp \ @@ -49,24 +49,11 @@ SOURCES += main.cpp \ imagecache.cpp \ imagenetworkaccessmanager.cpp -# Please do not modify the following two lines. Required for deployment. -include(qmlapplicationviewer/qmlapplicationviewer.pri) -qtcAddDeployment() - -OTHER_FILES += \ - qtc_packaging/debian_harmattan/rules \ - qtc_packaging/debian_harmattan/README \ - qtc_packaging/debian_harmattan/manifest.aegis \ - qtc_packaging/debian_harmattan/copyright \ - qtc_packaging/debian_harmattan/control \ - qtc_packaging/debian_harmattan/compat \ - qtc_packaging/debian_harmattan/changelog - HEADERS += \ action.h \ board.h \ boardmanager.h \ - fetchboardconfigaction.h \ + fetchconfigaction.h \ xmlrpcinterface.h \ xmlrpcpendingcall.h \ xmlrpcreply.h \ @@ -80,3 +67,16 @@ HEADERS += \ favoritesmodel.h \ imagecache.h \ imagenetworkaccessmanager.h + +OTHER_FILES += \ + qtc_packaging/debian_harmattan/rules \ + qtc_packaging/debian_harmattan/README \ + qtc_packaging/debian_harmattan/manifest.aegis \ + qtc_packaging/debian_harmattan/copyright \ + qtc_packaging/debian_harmattan/control \ + qtc_packaging/debian_harmattan/compat \ + qtc_packaging/debian_harmattan/changelog + +# Please do not modify the following two lines. Required for deployment. +include(qmlapplicationviewer/qmlapplicationviewer.pri) +qtcAddDeployment() -- cgit v1.2.3