make it possible to set settings using the command line

This commit is contained in:
Patrick von Reth 2015-05-05 18:13:33 +02:00
parent e106584a0e
commit 2f58f1163e
21 changed files with 207 additions and 74 deletions

View File

@ -65,6 +65,8 @@ set(LIBSNORE_PLUGIN_PATH ${KDE_INSTALL_PLUGINDIR}/libsnore${SNORE_SUFFIX})
set(SNORE_PLUGIN_INSTALL_PATH LIBRARY DESTINATION ${LIBSNORE_PLUGIN_PATH})
message(STATUS "Installing plugins to ${LIBSNORE_PLUGIN_PATH}")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin)
add_subdirectory(data)
add_subdirectory(lang)

View File

@ -23,7 +23,6 @@
#include "plugins/plugincontainer.h"
#include <Qt>
using namespace Snore;
Notification::Notification() :
@ -148,18 +147,17 @@ bool Notification::isValid() const
return d;
}
void Notification::addActiveIn(const QObject *o)
{
bool contains = d->m_activeIn.contains(o);
Q_ASSERT_X(contains,Q_FUNC_INFO,"already active");
if(contains) {
Q_ASSERT_X(contains, Q_FUNC_INFO, "already active");
if (contains) {
snoreDebug(SNORE_WARNING) << o << "already active in" << id();
return;
}
d->m_activeIn.insert(o);
SnoreCorePrivate::instance()->m_activeNotifications[id()] = *this;
snoreDebug(SNORE_INFO) << d->m_activeIn.size() << o << qobject_cast<SnorePlugin*>(o);
snoreDebug(SNORE_INFO) << d->m_activeIn.size() << o << qobject_cast<SnorePlugin *>(o);
snoreDebug(SNORE_INFO) << SnoreCorePrivate::instance()->m_activeNotifications.size();
}
@ -171,7 +169,7 @@ bool Notification::isActiveIn(const QObject *o) const
bool Notification::removeActiveIn(const QObject *o)
{
bool out = d->m_activeIn.remove(o);
snoreDebug(SNORE_INFO) << d->m_activeIn.size() << o << qobject_cast<SnorePlugin*>(o);
snoreDebug(SNORE_INFO) << d->m_activeIn.size() << o << qobject_cast<SnorePlugin *>(o);
if (d->m_activeIn.isEmpty()) {
SnoreCorePrivate::instance()->m_activeNotifications.remove(id());
snoreDebug(SNORE_INFO) << SnoreCorePrivate::instance()->m_activeNotifications.size();

View File

@ -266,11 +266,10 @@ public:
*/
static int defaultTimeout();
//TODO: find a better name.
void addActiveIn(const QObject *o);
bool isActiveIn(const QObject *o) const;
bool removeActiveIn(const QObject* o);
bool removeActiveIn(const QObject *o);
private:
QExplicitlySharedDataPointer<NotificationData> d;

View File

@ -80,8 +80,7 @@ void NotificationData::setCloseReason(Snore::Notification::CloseReasons r)
void NotificationData::setTimeoutTimer(QTimer *timer)
{
if(m_timeoutTimer)
{
if (m_timeoutTimer) {
m_timeoutTimer->stop();
m_timeoutTimer->deleteLater();
}

View File

@ -66,15 +66,13 @@ private:
Hint m_hints;
Notification m_toReplace;
QScopedPointer<QTimer> m_timeoutTimer;
QSet<const QObject*> m_activeIn;
QSet<const QObject *> m_activeIn;
static uint notificationCount;
static uint m_idCount;
};
}
#endif // NOTIFICATIONDATA_H

View File

@ -32,7 +32,7 @@ using namespace Snore;
SnorePlugin::SnorePlugin(const QString &name) :
m_name(name)
{
Q_ASSERT_X(thread() != qApp->thread(), Q_FUNC_INFO, "Plugin initialized in wrong thread");
Q_ASSERT_X(thread() == qApp->thread(), Q_FUNC_INFO, "Plugin initialized in wrong thread");
if (thread() != qApp->thread()) {
snoreDebug(SNORE_WARNING) << "Plugin initialized in wrong thread.";
}
@ -164,12 +164,12 @@ QDebug operator<<(QDebug debug, const Snore::SnorePlugin::PluginTypes &flags)
}
QDebug operator<<(QDebug debug, const Snore::SnorePlugin *p){
debug.nospace() << p->metaObject()->className() << "(" << (void*)p << ", " << p->name() << ")";
QDebug operator<<(QDebug debug, const Snore::SnorePlugin *p)
{
debug.nospace() << p->metaObject()->className() << "(" << (void *)p << ", " << p->name() << ")";
return debug.space();
}
QDataStream &operator<<(QDataStream &out, const Snore::SnorePlugin::PluginTypes &type)
{
out << static_cast<int>(type);

View File

@ -63,7 +63,6 @@ public:
virtual PluginSettingsWidget *settingsWidget();
protected:
virtual QString settingsVersion() const;

View File

@ -201,9 +201,9 @@ void SnoreBackend::slotNotificationDisplayed(Notification notification)
timer->setInterval(notification.timeout() * 1000);
//dont use a capture for notification, as it can leak
uint id = notification.id();
connect(timer, &QTimer::timeout, [id](){
connect(timer, &QTimer::timeout, [id]() {
Notification notification = SnoreCore::instance().getActiveNotificationByID(id);
if(notification.isValid()){
if (notification.isValid()) {
snoreDebug(SNORE_DEBUG) << notification;
SnoreCore::instance().requestCloseNotification(notification, Notification::TIMED_OUT);
}

View File

@ -53,7 +53,7 @@ public slots:
protected slots:
void slotNotificationDisplayed(Notification notification);
void slotNotificationActionInvoked(Notification notification, const Action& action = Action());
void slotNotificationActionInvoked(Notification notification, const Action &action = Action());
protected:
void closeNotification(Snore::Notification, Snore::Notification::CloseReasons);

View File

@ -231,7 +231,6 @@ void SnoreCore::setDefaultValue(const QString &key, const QVariant &value, Setti
}
}
Notification SnoreCore::getActiveNotificationByID(uint id) const
{
Q_D(const SnoreCore);

View File

@ -175,17 +175,6 @@ void SnoreCorePrivate::syncSettings()
}
}
QStringList SnoreCorePrivate::knownClients()
{
QStringList out;
m_settings->beginGroup(versionSchema());
m_settings->beginGroup("LocalSettings");
out = m_settings->childGroups();
m_settings->endGroup();
m_settings->endGroup();
return out;
}
void SnoreCorePrivate::setLocalSttingsPrefix(const QString &prefix)
{
m_localSettingsPrefix = prefix;

View File

@ -22,6 +22,7 @@
#include "snore.h"
#include "version.h"
#include "plugins/snorebackend.h"
#include "utils.h"
#include <QPointer>
#include <QApplication>
@ -59,25 +60,13 @@ public:
bool initPrimaryNotificationBackend();
inline QString versionSchema() const
{
return "v1";
}
void syncSettings();
QString normalizeKey(const QString &key, SettingsType type) const
{
if (type == LOCAL_SETTING) {
return QString("%1/LocalSettings/%2/%3").arg(versionSchema(), m_localSettingsPrefix, key);
} else {
return QString("%1/%2").arg(versionSchema(), key);
}
return Snore::Utils::normalizeSettingsKey(key, type, m_localSettingsPrefix);
}
//TODO: rename
QStringList knownClients();
void setLocalSttingsPrefix(const QString &prefix);
void init();
@ -88,7 +77,6 @@ private slots:
void slotNotificationActionInvoked(Notification notification);
void slotNotificationDisplayed(Notification notification);
signals:
void applicationRegistered(const Snore::Application &);
void applicationDeregistered(const Snore::Application &);
@ -116,7 +104,7 @@ private:
QSettings *m_settings;
QHash<uint,Snore::Notification> m_activeNotifications;
QHash<uint, Snore::Notification> m_activeNotifications;
friend class Snore::Notification;
};

View File

@ -19,9 +19,11 @@
#define UTILS_H
#include "snore_exports.h"
#include "snoreglobals.h"
#include <QApplication>
#include <QCryptographicHash>
#include <QSettings>
#include <QTextDocument>
#include <QTextDocumentFragment>
@ -83,6 +85,37 @@ public:
return QCryptographicHash::hash(data, QCryptographicHash::Md5).toHex();
}
static inline QString settingsVersionSchema()
{
return "v1";
}
static inline QString normalizeSettingsKey(const QString &key, SettingsType type, const QString &application)
{
if (type == LOCAL_SETTING) {
return QString("%1/LocalSettings/%2/%3").arg(settingsVersionSchema(), application, key);
} else {
return QString("%1/GlobalSettings/%2").arg(settingsVersionSchema(), key);
}
}
template<typename Func>
static QStringList allSettingsKeysWithPrefix(const QString &prefix, QSettings &settings, Func fun)
{
QStringList groups = prefix.split("/");
QStringList out;
for (const QString group : groups) {
settings.beginGroup(group);
}
out = fun(settings);
for (int i = 0; i < groups.size(); ++i) {
settings.endGroup();
}
return out;
}
private:
#ifdef Q_OS_WIN
static int attatchToActiveProcess();

View File

@ -43,25 +43,29 @@ GrowlBackend::~GrowlBackend()
bool GrowlBackend::initialize()
{
s_instance = this;
auto func = [](growl_callback_data *data)->void{
auto func = [](growl_callback_data * data)->void {
snoreDebug(SNORE_DEBUG) << data->id << QString(data->reason) << QString(data->data);
Notification n = Snore::SnoreCore::instance().getActiveNotificationByID(data->id);
if (!n.isValid()) {
if (!n.isValid())
{
return;
}
Notification::CloseReasons r = Notification::NONE;
std::string reason(data->reason);
if (reason == "TIMEDOUT") {
if (reason == "TIMEDOUT")
{
r = Notification::TIMED_OUT;
} else if (reason == "CLOSED") {
} else if (reason == "CLOSED")
{
r = Notification::DISMISSED;
} else if (reason == "CLICK") {
} else if (reason == "CLICK")
{
r = Notification::ACTIVATED;
s_instance->slotNotificationActionInvoked(n);
}
s_instance->closeNotification(n, r);
};
if (Growl::init((GROWL_CALLBACK)static_cast<void(*)(growl_callback_data*)>(func))
if (Growl::init((GROWL_CALLBACK)static_cast<void(*)(growl_callback_data *)>(func))
&& Growl::isRunning(GROWL_TCP, value("Host").toString().toUtf8().constData())) {
return SnoreBackend::initialize();
}

View File

@ -33,7 +33,7 @@ SnoreNotifier::SnoreNotifier():
{
setDefaultValue("Position", Qt::TopRightCorner);
m_timer->setInterval(500);
connect(m_timer, &QTimer::timeout, [this](){
connect(m_timer, &QTimer::timeout, [this]() {
if (m_queue.isEmpty()) {
snoreDebug(SNORE_DEBUG) << "queue is empty";
m_timer->stop();
@ -64,7 +64,7 @@ SnoreNotifier::~SnoreNotifier()
void SnoreNotifier::slotNotify(Snore::Notification notification)
{
auto display = [this](NotifyWidget *w, Snore::Notification notification){
auto display = [this](NotifyWidget * w, Snore::Notification notification) {
w->display(notification);
notification.hints().setPrivateValue(this, "id", w->id());
slotNotificationDisplayed(notification);
@ -90,8 +90,8 @@ void SnoreNotifier::slotNotify(Snore::Notification notification)
if (m_queue.isEmpty()) {
foreach(NotifyWidget * w, m_widgets) {
if (w->acquire()) {
display(w, notification);
return;
display(w, notification);
return;
}
}
}
@ -113,13 +113,13 @@ bool SnoreNotifier::initialize()
for (int i = 0; i < m_widgets.size(); ++i) {
NotifyWidget *w = new NotifyWidget(i, this);
m_widgets[i] = w;
connect(w, &NotifyWidget::dismissed,[this, w](){
connect(w, &NotifyWidget::dismissed, [this, w]() {
Notification notification = w->notification();
closeNotification(notification, Notification::DISMISSED);
slotCloseNotification(notification);
});
connect(w, &NotifyWidget::invoked, [this, w](){
connect(w, &NotifyWidget::invoked, [this, w]() {
Notification notification = w->notification();
slotNotificationActionInvoked(notification);
closeNotification(notification, Notification::ACTIVATED);

View File

@ -1,4 +1,5 @@
if(WITH_FRONTENDS)
add_subdirectory(freedesktop)
add_subdirectory(snarlnetwork)
add_subdirectory(snp3)
endif()

View File

@ -71,7 +71,7 @@ bool FreedesktopFrontend::deinitialize()
void FreedesktopFrontend::slotActionInvoked(Notification notification)
{
if(notification.isActiveIn(this)) {
if (notification.isActiveIn(this)) {
if (notification.actionInvoked().isValid()) {
emit ActionInvoked(notification.id(), QString::number(notification.actionInvoked().id()));
}
@ -80,7 +80,7 @@ void FreedesktopFrontend::slotActionInvoked(Notification notification)
void FreedesktopFrontend::slotNotificationClosed(Notification notification)
{
if(notification.removeActiveIn(this)) {
if (notification.removeActiveIn(this)) {
emit NotificationClosed(notification.id(), notification.closeReason());
}
}
@ -150,12 +150,12 @@ void FreedesktopFrontend::CloseNotification(uint id)
QStringList FreedesktopFrontend::GetCapabilities()
{
return QStringList()
<< "body"
<< "urgency"
// << "body-hyperlinks"
<< "body-markup"
<< "icon-static"
<< "actions";
<< "body"
<< "urgency"
// << "body-hyperlinks"
<< "body-markup"
<< "icon-static"
<< "actions";
}
QString FreedesktopFrontend::GetServerInformation(QString &vendor, QString &version, QString &specVersion)

View File

@ -66,7 +66,7 @@ bool SnarlNetworkFrontend::deinitialize()
void SnarlNetworkFrontend::slotActionInvoked(Snore::Notification notification)
{
if(notification.isActiveIn(this)) {
if (notification.isActiveIn(this)) {
snoreDebug(SNORE_DEBUG) << notification.closeReason();
callback(notification, "SNP/1.1/304/Notification acknowledged/");
}
@ -75,7 +75,7 @@ void SnarlNetworkFrontend::slotActionInvoked(Snore::Notification notification)
void SnarlNetworkFrontend::slotNotificationClosed(Snore::Notification notification)
{
if(notification.removeActiveIn(this)) {
if (notification.removeActiveIn(this)) {
switch (notification.closeReason()) {
case Notification::TIMED_OUT:
callback(notification, "SNP/1.1/303/Notification timed out/");

View File

@ -1,21 +1,125 @@
#include "libsnore/snore.h"
#include "libsnore/snore_p.h"
#include "libsnore/version.h"
#include "settingswindow.h"
#include <QApplication>
#include <QCommandLineParser>
#include <QMainWindow>
#include <iostream>
using namespace Snore;
using namespace std;
bool setSetting(const QString &appName, SettingsType type, const QString &_key, const QString &value)
{
QSettings &settings = SettingsWindow::settings();
QString key = Utils::normalizeSettingsKey(_key, type, appName);
QVariant oldValue = settings.value(key);
//TODO: make sure that the values are valid qvariant.canConvert doesnt work.
if (!oldValue.isValid()) {
cout << "Invalid key: " << qPrintable(key) << endl;
return false;
}
settings.setValue(key, value);
cout << "Set: " << qPrintable(key) << " to " << qPrintable(settings.value(key).toString()) << endl;
return true;
}
void listApps()
{
for (const QString &app : SettingsWindow::knownApps()) {
cout << qPrintable(app) << endl;
}
}
void listSettings(SettingsType type, const QString &application)
{
QSettings &settings = SettingsWindow::settings();
auto getAllKeys = [](QSettings & settings) {
return settings.allKeys();
};
cout << qPrintable(application) << endl;
for (const QString &key : Utils::allSettingsKeysWithPrefix(
Utils::normalizeSettingsKey("", type, application), settings, getAllKeys)) {
cout << " " << qPrintable(key) << ": " << qPrintable(settings.value(Utils::normalizeSettingsKey(key, type, application)).toString()) << endl;
}
}
int main(int argc, char *argv[])
{
QScopedPointer<SettingsWindow> window;
QApplication app(argc, argv);
app.setApplicationName("SnoreSettings");
app.setOrganizationName("SnoreNotify");
app.setApplicationVersion(Snore::Version::version());
Snore::SnoreCore::instance().loadPlugins(Snore::SnorePlugin::ALL);
SettingsWindow window;
window.show();
return app.exec();
QCommandLineParser parser;
parser.setApplicationDescription("A settings interface for Snorenotify.");
parser.addHelpOption();
parser.addVersionOption();
//TODO: merge with appNameCommand ?
QCommandLineOption listAppsCommand("apps", "List possible application.");
parser.addOption(listAppsCommand);
QCommandLineOption listSettingsCommand({"l", "list"} , "List settings for the given --appName or the global settings.");
parser.addOption(listSettingsCommand);
QCommandLineOption appNameCommand({"a", "appName"} , "Set the Name of the app <app>.", "app", "GlobalSettings");
parser.addOption(appNameCommand);
QCommandLineOption typeCommand({"t", "type"} , "Type of the setting [global|local].", "type");
parser.addOption(typeCommand);
parser.addPositionalArgument("key", "The settings Key.");
parser.addPositionalArgument("value", "The new settings Value");
parser.process(app);
SettingsType type = GLOBAL_SETTING;
if (parser.isSet(typeCommand)) {
QString typeName = parser.value(typeCommand);
if (typeName != "global" && typeName == "local") {
type = LOCAL_SETTING;
} else {
parser.showHelp(1);
}
}
if (parser.isSet(appNameCommand)) {
type = LOCAL_SETTING;
}
if (parser.isSet(listAppsCommand)) {
listApps();
} else if (parser.isSet(listSettingsCommand)) {
listSettings(type, parser.value(appNameCommand));
} else if (parser.optionNames().empty() && parser.positionalArguments().empty()) {
window.reset(new SettingsWindow());
window->show();
return app.exec();
} else {
QStringList posArgs = parser.positionalArguments();
if (posArgs.size() != 2) {
parser.showHelp(1);
}
QString appName;
if (parser.isSet(appNameCommand)) {
appName = parser.value(appNameCommand);
}
if (!setSetting(appName, type, posArgs[0], posArgs[1])) {
return 1;
}
}
app.processEvents();
return 0;
}

View File

@ -4,6 +4,7 @@
#include "snore.h"
#include "snore_p.h"
#include "settingsdialog.h"
#include "utils.h"
#include <QApplication>
#include <QComboBox>
@ -18,7 +19,7 @@ SettingsWindow::SettingsWindow(QWidget *parent) :
ui->setupUi(this);
ui->widget->show();
QStringList list = SnoreCorePrivate::instance()->knownClients();
QStringList list = knownApps();
list.removeAll(qApp->applicationName());
ui->comboBox->addItems(list);
}
@ -28,6 +29,20 @@ SettingsWindow::~SettingsWindow()
delete ui;
}
QStringList SettingsWindow::knownApps()
{
return Utils::allSettingsKeysWithPrefix(QString("%1/%2").arg(Utils::settingsVersionSchema(), "LocalSettings"), settings(),
[](QSettings & settings) {
return settings.childGroups();
});
}
QSettings &SettingsWindow::settings()
{
static QSettings settings("Snorenotify", "libsnore");
return settings;
}
void SettingsWindow::on_comboBox_currentIndexChanged(const QString &arg1)
{
SnoreCorePrivate::instance()->setLocalSttingsPrefix(arg1);

View File

@ -2,6 +2,7 @@
#define SETTINGSWINDOW_H
#include <QMainWindow>
#include <QSettings>
namespace Ui
{
@ -18,6 +19,10 @@ public:
explicit SettingsWindow(QWidget *parent = 0);
~SettingsWindow();
static QStringList knownApps();
static QSettings &settings();
private slots:
void on_buttonBox_clicked(QAbstractButton *button);
void on_comboBox_currentIndexChanged(const QString &arg1);