add better support for markup in messages.

added a test class
This commit is contained in:
Patrick von Reth 2015-06-23 17:04:57 +02:00
parent 252b7588cf
commit bb447c91c1
18 changed files with 183 additions and 63 deletions

View File

@ -71,6 +71,7 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin)
add_subdirectory(data)
add_subdirectory(lang)
add_subdirectory(src)
add_subdirectory(autotest)
add_subdirectory(share)

4
autotest/CMakeLists.txt Normal file
View File

@ -0,0 +1,4 @@
include(ECMAddTests)
find_package(Qt5Test)
ecm_add_tests( snorebenchmark.cpp LINK_LIBRARIES Snore::Libsnore Qt5::Test)

View File

@ -0,0 +1,76 @@
#include <libsnore/snore.h>
#include <libsnore/utils.h>
#include <QApplication>
#include <QDebug>
#include <QTextDocument>
#include <QTextDocumentFragment>
#include <QtTest>
using namespace Snore;
class SnoreBenchmark : public QObject{
Q_OBJECT
public:
SnoreBenchmark(){
SnoreCore::instance();
}
QString htmlTestString = QString("<i>Italic A</i><br>"
"<i>Italic B</i><br>"
"<b>Bold</b><br>"
"<u>Underline</u><br>"
"<font color=\"blue\">Font</font><br>"
"<a href=\"https://github.com/Snorenotify/Snorenotify\">Website</a><br>");
private slots:
void benchmarkUtilsToHtml();
void benchmarkUtilsToPlain();
private:
/**
* old toPlaintext function from Utils.
* @param string A string to decode if needed.
* @return if the string was rhichtext or html encoded a decoded string, else the original string.
*/
static inline QString toPlainText(const QString &string)
{
if (Qt::mightBeRichText(string)) {
return QTextDocumentFragment::fromHtml(string).toPlainText();
} else {
return string;
}
}
};
void SnoreBenchmark::benchmarkUtilsToHtml(){
QCOMPARE(Utils::normaliseMarkup(htmlTestString, Utils::NO_MARKUP), toPlainText(htmlTestString));
QCOMPARE(Utils::normaliseMarkup(htmlTestString, Utils::HREF), QString("Italic A\n"
"Italic B\n"
"Bold\n"
"Underline\n"
"Font\n"
"<a href=\"https://github.com/Snorenotify/Snorenotify\">Website</a>\n"));
QCOMPARE(Utils::normaliseMarkup(htmlTestString, Utils::HREF | Utils::BOLD | Utils::BREAK |
Utils::UNDERLINE | Utils::FONT | Utils::ITALIC), htmlTestString);
QBENCHMARK{
Utils::normaliseMarkup(htmlTestString, Utils::NO_MARKUP);
}
}
void SnoreBenchmark::benchmarkUtilsToPlain()
{
QBENCHMARK{
toPlainText(htmlTestString);
}
}
QTEST_MAIN(SnoreBenchmark)
#include "snorebenchmark.moc"

View File

@ -8,8 +8,14 @@ foreach( lang ${LIBSNORE_LANGS} )
endforeach()
set( snore_i18n_content "${snore_i18n_content}</qresource>\n</RCC>\n" )
file( WRITE ${CMAKE_BINARY_DIR}/lang/snore_i18n.qrc "${snore_i18n_content}" )
file( WRITE ${CMAKE_BINARY_DIR}/lang/snore_i18n.qrc.in "${snore_i18n_content}" )
#mark as a dependencie
add_custom_command(OUTPUT snore_i18n.qrc
COMMAND ${CMAKE_COMMAND}
ARGS -E copy ${CMAKE_BINARY_DIR}/lang/snore_i18n.qrc.in ${CMAKE_BINARY_DIR}/lang/snore_i18n.qrc
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
qt5_add_translation(libsnore_lang ${TS_FILES})
add_custom_target(libsnore_lang_translation ALL DEPENDS ${libsnore_lang})
add_custom_target(libsnore_lang_translation ALL DEPENDS ${libsnore_lang} DEPENDS snore_i18n.qrc)

View File

@ -92,14 +92,14 @@ const Application &Notification::application() const
return d->m_application;
}
QString Notification::title() const
QString Notification::title(Utils::MARKUP_FLAGS flags) const
{
return d->m_title;
return Utils::normaliseMarkup(d->m_title, flags);
}
QString Notification::text() const
QString Notification::text(Utils::MARKUP_FLAGS flags) const
{
return d->m_text;
return Utils::normaliseMarkup(d->m_text, flags);
}
const Alert &Notification::alert() const

View File

@ -23,6 +23,7 @@
#include "notificationaction.h"
#include "libsnore/hint.h"
#include "libsnore/application.h"
#include "libsnore/utils.h"
#include <QDebug>
@ -45,7 +46,7 @@ public:
/**
* The reason why the Notification was closed.
*/
enum CloseReason {
enum CloseReasons {
/**
* The default value, the notification was not closed.
*/
@ -79,14 +80,13 @@ public:
*/
REPLACED = 4
};
Q_DECLARE_FLAGS(CloseReasons, CloseReason)
Q_ENUMS(CloseReasons)
/**
* The Priority for the Notification.
* Some notification systems support this flag to filter notifications or indicate different prioritys by color.
*/
enum Priority {
enum Prioritys {
/**
* Indicates a low priority.
*/
@ -102,7 +102,6 @@ public:
*/
HIGH = +1
};
Q_DECLARE_FLAGS(Prioritys, Priority)
Notification();
/**
@ -170,13 +169,13 @@ public:
*
* @return the title
*/
QString title() const;
QString title(Utils::MARKUP_FLAGS flags = Utils::NO_MARKUP) const;
/**
*
* @return the text body
*/
QString text() const;
QString text(Utils::MARKUP_FLAGS flags = Utils::NO_MARKUP) const;
/**
*
@ -279,10 +278,6 @@ private:
}
Q_DECLARE_METATYPE(Snore::Notification)
Q_DECLARE_OPERATORS_FOR_FLAGS(Snore::Notification::CloseReasons)
Q_DECLARE_OPERATORS_FOR_FLAGS(Snore::Notification::Prioritys)
QDataStream &operator<< (QDataStream &stream, const Snore::Notification &noti);
SNORE_EXPORT QDebug operator<< (QDebug, const Snore::Notification::CloseReasons &);

View File

@ -33,13 +33,14 @@ class SNORE_EXPORT SnorePlugin : public QObject
Q_OBJECT
public:
enum PluginType {
NONE = 0,
ALL = 0xFFFFF,//for loading plugins
BACKEND = 0x1,
SECONDARY_BACKEND = 0x2,
FRONTEND = 0x4,
PLUGIN = 0x8
NONE = 0,
BACKEND = 1 << 0,
SECONDARY_BACKEND = 1 << 1,
FRONTEND = 1 << 2,
PLUGIN = 1 << 3,
ALL = ~0
};
Q_DECLARE_FLAGS(PluginTypes, PluginType)
Q_ENUMS(PluginType)

View File

@ -72,6 +72,7 @@ void SnoreCore::loadPlugins(SnorePlugin::PluginTypes types)
}
Q_D(SnoreCore);
setValue("PluginTypes", QVariant::fromValue(types), LOCAL_SETTING);
snoreDebug(SNORE_DEBUG) << "Loading plugin types:" << types;
for (SnorePlugin::PluginTypes type : SnorePlugin::types()) {
if (type != SnorePlugin::ALL && types & type) {
for (PluginContainer *info : PluginContainer::pluginCache(type).values()) {

View File

@ -25,6 +25,9 @@
#include <winuser.h>
#endif
#include <QRegExp>
#include <QMutex>
using namespace Snore;
Utils::Utils(QObject *parent):
@ -66,6 +69,40 @@ void Utils::raiseWindowToFront(qlonglong wid)
#endif
}
#define HTML_REPLACE(STRING, PATTERN){\
static QRegExp regexp(QLatin1String(PATTERN));\
STRING = STRING.replace(regexp, QStringLiteral("\\1"));\
}\
QString Utils::normaliseMarkup(QString string, MARKUP_FLAGS tags)
{
static QMutex mutex;
QMutexLocker lock(&mutex);
if (~tags & Utils::BREAK) {
static QRegExp br("<br>");
string = string.replace(br, "\n");
}
if (~tags & Utils::HREF) {
HTML_REPLACE(string, "<a href=.*>([^<]*)</a>");
}
if (~tags & Utils::ITALIC) {
HTML_REPLACE(string, "<i>([^<]*)</i>");
}
if (~tags & Utils::BOLD) {
HTML_REPLACE(string, "<b>([^<]*)</b>");
}
if (~tags & Utils::UNDERLINE) {
HTML_REPLACE(string, "<u>([^<]*)</u>");
}
if (~tags & Utils::FONT) {
HTML_REPLACE(string, "<font.*>([^<]*)</font>");
}
return string;
}
#ifdef Q_OS_WIN
int Utils::attatchToActiveProcess()
{

View File

@ -24,8 +24,6 @@
#include <QApplication>
#include <QCryptographicHash>
#include <QSettings>
#include <QTextDocument>
#include <QTextDocumentFragment>
namespace Snore
{
@ -33,6 +31,19 @@ class SNORE_EXPORT Utils : public QObject
{
Q_OBJECT
public:
enum MARKUP_FLAG{
NO_MARKUP = 0,
HREF = 1 << 0,
BREAK = 1 << 1,
BOLD = 1 << 2,
ITALIC = 1 << 3,
UNDERLINE = 1 << 4,
FONT = 1 << 5,
ALL_MARKUP = ~0
};
Q_DECLARE_FLAGS(MARKUP_FLAGS,MARKUP_FLAG)
Utils(QObject *parent = nullptr);
~Utils();
@ -49,33 +60,12 @@ public:
*/
Q_INVOKABLE static void raiseWindowToFront(qlonglong wid);
/**
*
* @param string A string to decode if needed.
* @return if the string was rhichtext or html encoded a decoded string, else the original string.
*/
static inline QString toPlainText(const QString &string)
{
if (Qt::mightBeRichText(string)) {
return QTextDocumentFragment::fromHtml(string).toPlainText();
} else {
return string;
}
}
/**
*
* @param string A string to encode if needed.
* @return if the string was rhichtext html encode string is returnd otherwise the original string.
*/
static inline QString toHtml(const QString &string)
{
if (Qt::mightBeRichText(string)) {
return QTextDocumentFragment::fromHtml(string).toHtml("UTF-8");
} else {
return string;
}
}
static QString normaliseMarkup(QString string, MARKUP_FLAGS tags);
/**
* Computes a md5 hash of the provided data.
@ -125,5 +115,6 @@ private:
};
}
Q_DECLARE_OPERATORS_FOR_FLAGS(Snore::Utils::MARKUP_FLAGS)
#endif // UTILS_H

View File

@ -111,11 +111,11 @@ void GrowlBackend::slotNotify(Notification notification)
{
Growl *growl = m_applications.value(notification.application().name());
QString alert = notification.alert().name();
snoreDebug(SNORE_DEBUG) << "Notify Growl:" << notification.application() << alert << Utils::toPlainText(notification.title());
snoreDebug(SNORE_DEBUG) << "Notify Growl:" << notification.application() << alert << notification.title();
GrowlNotificationData data(alert.toUtf8().constData(), notification.id(),
Utils::toPlainText(notification.title()).toUtf8().constData(),
Utils::toPlainText(notification.text()).toUtf8().constData());
notification.title().toUtf8().constData(),
notification.text().toUtf8().constData());
if (notification.icon().isValid()) {
data.setIcon(notification.icon().localUrl().toUtf8().constData());

View File

@ -217,8 +217,8 @@ void SnarlBackend::slotNotify(Notification notification)
if (!notification.isUpdate()) {
id = snarlInterface->Notify(notification.alert().name().toUtf8().constData(),
Utils::toPlainText(notification.title()).toUtf8().constData(),
Utils::toPlainText(notification.text()).toUtf8().constData(),
notification.title().toUtf8().constData(),
notification.text().toUtf8().constData(),
notification.timeout(),
notification.icon().isLocalFile() ? notification.icon().localUrl().toUtf8().constData() : 0,
!notification.icon().isLocalFile() ? Icon::dataFromImage(notification.icon().image()).toBase64().constData() : 0,
@ -234,8 +234,8 @@ void SnarlBackend::slotNotify(Notification notification)
id = notification.old().hints().privateValue(this, "id").toUInt();
snarlInterface->Update(id,
notification.alert().name().toUtf8().constData(),
Utils::toPlainText(notification.title()).toUtf8().constData(),
Utils::toPlainText(notification.text()).toUtf8().constData(),
notification.title().toUtf8().constData(),
notification.text().toUtf8().constData(),
notification.timeout(),
notification.icon().isLocalFile() ? notification.icon().localUrl().toUtf8().constData() : 0,
!notification.icon().isLocalFile() ? Icon::dataFromImage(notification.icon().image()).toBase64().constData() : 0,

View File

@ -43,9 +43,9 @@ void SnoreToast::slotNotify(Notification notification)
QStringList arguements;
arguements << "-t"
<< Utils::toPlainText(notification.title())
<< notification.title()
<< "-m"
<< Utils::toPlainText(notification.text());
<< notification.text();
if (notification.icon().isValid()) {
arguements << "-p"
<< QDir::toNativeSeparators(notification.icon().localUrl());

View File

@ -83,7 +83,7 @@ void TrayIconNotifer::displayNotification(QSystemTrayIcon *icon)
m_currentlyDisplaying = true;
Notification notification = m_notificationQue.takeFirst();
m_displayed = notification;
icon->showMessage(Utils::toPlainText(notification.title()), Utils::toPlainText(notification.text()), QSystemTrayIcon::NoIcon, notification.timeout() * 1000);
icon->showMessage(notification.title(), notification.text(), QSystemTrayIcon::NoIcon, notification.timeout() * 1000);
slotNotificationDisplayed(notification);
}

View File

@ -86,6 +86,8 @@ void SnarlNetworkFrontend::slotNotificationClosed(Snore::Notification notificati
case Notification::DISMISSED:
callback(notification, "SNP/1.1/302/Notification cancelled/");
break;
default:
snoreDebug(SNORE_WARNING) << "Unhandled close reason" << notification.closeReason();
}
}
}

View File

@ -51,10 +51,12 @@ void NotifyMyAndroid::slotNotify(Notification notification)
QString data(QString("apikey=%1&application=%2&event=%3&description=%4&priority=%5&content-type=text/html")
.arg(key,
notification.application().name(),
Utils::toPlainText(notification.title()),
Utils::toPlainText(notification.text()),
notification.title(),
notification.text(Utils::HREF | Utils::BOLD | Utils::BREAK |
Utils::UNDERLINE | Utils::FONT | Utils::ITALIC),
QString::number(notification.priority())));
QNetworkReply *reply = m_manager.post(request, data.toUtf8().constData());
connect(reply, &QNetworkReply::finished, [reply]() {
snoreDebug(SNORE_DEBUG) << reply->error();

View File

@ -52,15 +52,15 @@ void Pushover::slotNotify(Notification notification)
QHttpPart title;
title.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"title\""));
title.setBody(Utils::toPlainText(notification.title()).toUtf8().constData());
title.setBody(notification.title().toUtf8().constData());
mp->append(title);
QHttpPart text;
text.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"message\""));
text.setBody(Utils::toPlainText(notification.text()).toUtf8().constData());
text.setBody(notification.text(Utils::HREF | Utils::BOLD | Utils::UNDERLINE | Utils::FONT | Utils::ITALIC)
.toUtf8().constData());
mp->append(text);
QHttpPart priority;
priority.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"priority\""));
priority.setBody(QString::number(notification.priority()).toUtf8().constData());
@ -92,6 +92,10 @@ void Pushover::slotNotify(Notification notification)
user.setBody(key.toUtf8().constData());
mp->append(user);
QHttpPart html;
html.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"html\""));
html.setBody("1");
mp->append(html);
QNetworkReply *reply = m_manager.post(request, mp);
mp->setParent(reply);

View File

@ -49,12 +49,12 @@ void Toasty::slotNotify(Notification notification)
QHttpPart title;
title.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"title\""));
title.setBody(Utils::toPlainText(notification.title()).toUtf8().constData());
title.setBody(notification.title().toUtf8().constData());
mp->append(title);
QHttpPart text;
text.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"text\""));
text.setBody(Utils::toPlainText(notification.text()).toUtf8().constData());
text.setBody(notification.text().toUtf8().constData());
mp->append(text);
QHttpPart app;