add better support for markup in messages.
added a test class
This commit is contained in:
parent
252b7588cf
commit
bb447c91c1
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
include(ECMAddTests)
|
||||
find_package(Qt5Test)
|
||||
|
||||
ecm_add_tests( snorebenchmark.cpp LINK_LIBRARIES Snore::Libsnore Qt5::Test)
|
|
@ -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"
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ¬i);
|
||||
|
||||
SNORE_EXPORT QDebug operator<< (QDebug, const Snore::Notification::CloseReasons &);
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue