D-Bus server: made notification verbosity configurable with "notifyLevel"

The new "notifyLevel" per-peer configuration option allows users to
control how many desktop notifications the D-Bus server produces while
executing an automatic sync:

  0 - suppress all notifications
  1 - show only errors
  2 - show information about changes and errors (in practice currently the same as level 3)
  3 - show all notifications, including starting a sync (default)
This commit is contained in:
Patrick Ohly 2012-05-22 10:05:11 +02:00
parent d1db2d30a1
commit c1f4141321
6 changed files with 92 additions and 20 deletions

View File

@ -170,6 +170,7 @@ void AutoSyncManager::initConfig(const std::string &configName)
task->m_interval = config.getAutoSyncInterval();
task->m_delay = config.getAutoSyncDelay();
task->m_remoteDeviceId = config.getRemoteDevID();
task->m_notifyLevel = config.getNotifyLevel();
// Assume that whatever change was made might have resolved
// the past problem -> allow auto syncing again.
@ -424,7 +425,8 @@ void AutoSyncManager::autoSyncSuccessStart(AutoSyncTask *task)
task->m_syncSuccessStart = true;
SE_LOG_INFO(NULL, NULL,"Automatic sync for '%s' has been successfully started.\n",
task->m_peerName.c_str());
if (m_server.notificationsEnabled()) {
if (m_server.notificationsEnabled() &&
task->m_notifyLevel >= SyncConfig::NOTIFY_ALL) {
std::string summary = StringPrintf(_("%s is syncing"), task->m_peerName.c_str());
std::string body = StringPrintf(_("We have just started to sync your computer with the %s sync service."),
task->m_peerName.c_str());
@ -456,19 +458,23 @@ void AutoSyncManager::autoSyncDone(AutoSyncTask *task, SyncMLStatus status)
// send a notification to notification server
std::string summary, body;
if (task->m_syncSuccessStart && status == STATUS_OK) {
// if sync is successfully started and done
summary = StringPrintf(_("%s sync complete"), task->m_peerName.c_str());
body = StringPrintf(_("We have just finished syncing your computer with the %s sync service."),
task->m_peerName.c_str());
//TODO: set config information for 'sync-ui'
m_notificationManager->publish(summary, body);
if (task->m_notifyLevel >= SyncConfig::NOTIFY_ALL) {
// if sync is successfully started and done
summary = StringPrintf(_("%s sync complete"), task->m_peerName.c_str());
body = StringPrintf(_("We have just finished syncing your computer with the %s sync service."),
task->m_peerName.c_str());
//TODO: set config information for 'sync-ui'
m_notificationManager->publish(summary, body);
}
} else if (task->m_syncSuccessStart || !ErrorIsTemporary(status)) {
// if sync is successfully started and has errors, or not started successful with a permanent error
// that needs attention
summary = StringPrintf(_("Sync problem."));
body = StringPrintf(_("Sorry, there's a problem with your sync that you need to attend to."));
//TODO: set config information for 'sync-ui'
m_notificationManager->publish(summary, body);
if (task->m_notifyLevel >= SyncConfig::NOTIFY_ERROR) {
// if sync is successfully started and has errors, or not started successful with a permanent error
// that needs attention
summary = StringPrintf(_("Sync problem."));
body = StringPrintf(_("Sorry, there's a problem with your sync that you need to attend to."));
//TODO: set config information for 'sync-ui'
m_notificationManager->publish(summary, body);
}
}
}

View File

@ -26,6 +26,7 @@
#include <boost/signals2.hpp>
#include <syncevo/SyncML.h>
#include <syncevo/SyncContext.h>
#include <syncevo/SmartPtr.h>
#include <syncevo/util.h>
@ -101,6 +102,9 @@ class AutoSyncManager
/** copy of config's remoteDeviceId sync property */
std::string m_remoteDeviceId;
/** copy of config's notifyLevel property */
SyncConfig::NotifyLevel m_notifyLevel;
/** last auto sync attempt succeeded (needed for notification logic) */
bool m_syncSuccessStart;

View File

@ -3445,6 +3445,8 @@ protected:
"\n"
"loglevel (0, unshared)\n"
"\n"
"notifyLevel (3, unshared)\n"
"\n"
"printChanges (TRUE, unshared)\n"
"\n"
"dumpData (TRUE, unshared)\n"
@ -4856,6 +4858,7 @@ private:
".internal.ini:contextCurVersion = %d\n"
"config.ini:# logdir = \n"
"peers/scheduleworld/config.ini:# loglevel = 0\n"
"peers/scheduleworld/config.ini:# notifyLevel = 3\n"
"peers/scheduleworld/config.ini:# printChanges = 1\n"
"peers/scheduleworld/config.ini:# dumpData = 1\n"
"config.ini:# maxlogdirs = 10\n"
@ -4970,6 +4973,7 @@ private:
"spds/syncml/config.txt:# password = \n"
"spds/syncml/config.txt:# logdir = \n"
"spds/syncml/config.txt:# loglevel = 0\n"
"spds/syncml/config.txt:# notifyLevel = 3\n"
"spds/syncml/config.txt:# printChanges = 1\n"
"spds/syncml/config.txt:# dumpData = 1\n"
"spds/syncml/config.txt:# maxlogdirs = 10\n"

View File

@ -1257,6 +1257,16 @@ static UIntConfigProperty syncPropLogLevel("loglevel",
"- 2 = also INFO messages\n"
"- 3 = also DEBUG messages\n"
"> 3 = increasing amounts of debug messages for developers");
static UIntConfigProperty syncPropNotifyLevel("notifyLevel",
"Level of detail for desktop notifications. Currently such\n"
"notifications are generated only for automatically started\n"
"sync sessions.\n"
"\n"
"0 - suppress all notifications\n"
"1 - show only errors\n"
"2 - show information about changes and errors (in practice currently the same as level 3)\n"
"3 - show all notifications, including starting a sync\n",
"3");
static BoolConfigProperty syncPropPrintChanges("printChanges",
"enables or disables the detailed (and sometimes slow) comparison\n"
"of database content before and after a sync session",
@ -1528,6 +1538,7 @@ public:
registry.push_back(&syncPropPassword);
registry.push_back(&syncPropLogDir);
registry.push_back(&syncPropLogLevel);
registry.push_back(&syncPropNotifyLevel);
registry.push_back(&syncPropPrintChanges);
registry.push_back(&syncPropDumpData);
registry.push_back(&syncPropMaxLogDirs);
@ -1845,6 +1856,11 @@ InitState<unsigned int> SyncConfig::getMaxLogDirs() const { return syncPropMaxLo
void SyncConfig::setMaxLogDirs(unsigned int value, bool temporarily) { syncPropMaxLogDirs.setProperty(*getNode(syncPropMaxLogDirs), value, temporarily); }
InitState<unsigned int> SyncConfig::getLogLevel() const { return syncPropLogLevel.getPropertyValue(*getNode(syncPropLogLevel)); }
void SyncConfig::setLogLevel(unsigned int value, bool temporarily) { syncPropLogLevel.setProperty(*getNode(syncPropLogLevel), value, temporarily); }
InitState<SyncConfig::NotifyLevel> SyncConfig::getNotifyLevel() const {
InitState<unsigned int> res = syncPropNotifyLevel.getPropertyValue(*getNode(syncPropNotifyLevel));
return InitState<SyncConfig::NotifyLevel>(static_cast<SyncConfig::NotifyLevel>(res.get()), res.wasSet());
}
void SyncConfig::setNotifyLevel(SyncConfig::NotifyLevel value, bool temporarily) { syncPropNotifyLevel.setProperty(*getNode(syncPropNotifyLevel), value, temporarily); }
InitState<unsigned int> SyncConfig::getRetryDuration() const {return syncPropRetryDuration.getPropertyValue(*getNode(syncPropRetryDuration));}
void SyncConfig::setRetryDuration(unsigned int value, bool temporarily) { syncPropRetryDuration.setProperty(*getNode(syncPropRetryDuration), value, temporarily); }
InitState<unsigned int> SyncConfig::getRetryInterval() const { return syncPropRetryInterval.getPropertyValue(*getNode(syncPropRetryInterval)); }

View File

@ -1385,6 +1385,15 @@ class SyncConfig {
virtual InitState<unsigned int> getLogLevel() const;
virtual void setLogLevel(unsigned int value, bool temporarily = false);
enum NotifyLevel {
NOTIFY_NONE, /**< suppress all notifications */
NOTIFY_ERROR, /**< show only errors */
NOTIFY_CHANGES, /**< show information about changes and errors */
NOTIFY_ALL /**< show all notifications, including starting a sync */
};
virtual InitState<NotifyLevel> getNotifyLevel() const;
virtual void setNotifyLevel(NotifyLevel value, bool temporarily = false);
virtual InitState<bool> getPrintChanges() const;
virtual void setPrintChanges(bool value, bool temporarily = false);

View File

@ -2570,8 +2570,7 @@ class TestSessionAPIsDummy(DBusUtil, unittest.TestCase):
self.runTestDBusCheck = checkDBusLog
@timeout(60)
def testAutoSyncLocalConfigError(self):
"""TestSessionAPIsDummy.testAutoSyncLocalConfigError - test that auto-sync is triggered for local sync, fails due to permanent config error here"""
def doAutoSyncLocalConfigError(self, notifyLevel):
self.setupConfig()
# enable auto-sync
config = copy.deepcopy(self.config)
@ -2580,6 +2579,8 @@ class TestSessionAPIsDummy(DBusUtil, unittest.TestCase):
config[""]["autoSyncDelay"] = "0"
config[""]["autoSyncInterval"] = "10s"
config[""]["password"] = "foobar"
if notifyLevel != 3:
config[""]["notifyLevel"] = str(notifyLevel)
self.session.SetConfig(True, False, config, utf8_strings=True)
def session_ready(object, ready):
@ -2622,6 +2623,7 @@ class TestSessionAPIsDummy(DBusUtil, unittest.TestCase):
def checkDBusLog(self, content):
notifications = GrepNotifications(content)
self.assertEqual(notifications,
notifyLevel >= 1 and
[' string "SyncEvolution"\n'
' uint32 0\n'
' string ""\n'
@ -2635,7 +2637,8 @@ class TestSessionAPIsDummy(DBusUtil, unittest.TestCase):
' ]\n'
' array [\n'
' ]\n'
' int32 -1\n'])
' int32 -1\n']
or [])
# check that no other session is started at the time of
# the next regular auto sync session
@ -2667,9 +2670,22 @@ class TestSessionAPIsDummy(DBusUtil, unittest.TestCase):
# done as part of post-processing in runTest()
self.runTestDBusCheck = checkDBusLog
@timeout(120)
def testAutoSyncLocalSuccess(self):
"""TestSessionAPIsDummy.testAutoSyncLocalSuccess - test that auto-sync is done successfully for local sync between file backends"""
@timeout(60)
def testAutoSyncLocalConfigError(self):
"""TestSessionAPIsDummy.testAutoSyncLocalConfigError - test that auto-sync is triggered for local sync, fails due to permanent config error here"""
self.doAutoSyncLocalConfigError(3)
@timeout(60)
def testAutoSyncLocalConfigErrorEssential(self):
"""TestSessionAPIsDummy.testAutoSyncLocalConfigErrorEssential - test that auto-sync is triggered for local sync, fails due to permanent config error here, with only the essential error notification"""
self.doAutoSyncLocalConfigError(1)
@timeout(60)
def testAutoSyncLocalConfigErrorQuiet(self):
"""TestSessionAPIsDummy.testAutoSyncLocalConfigErrorQuiet - test that auto-sync is triggered for local sync, fails due to permanent config error here, with no notification"""
self.doAutoSyncLocalConfigError(0)
def doAutoSyncLocalSuccess(self, notifyLevel):
# create @foobar config
self.session.Detach()
self.setUpSession("target-config@foobar")
@ -2690,6 +2706,8 @@ class TestSessionAPIsDummy(DBusUtil, unittest.TestCase):
config[""]["PeerIsClient"] = "1"
config[""]["autoSync"] = "1"
config[""]["autoSyncDelay"] = "0"
if notifyLevel != 3:
config[""]["notifyLevel"] = str(notifyLevel)
del config[""]["password"]
# must be small enough (otherwise test runs a long time)
# but not too small (otherwise the next sync already starts
@ -2738,6 +2756,7 @@ class TestSessionAPIsDummy(DBusUtil, unittest.TestCase):
def checkDBusLog(self, content):
notifications = GrepNotifications(content)
self.assertEqual(notifications,
notifyLevel >= 3 and
[' string "SyncEvolution"\n'
' uint32 0\n'
' string ""\n'
@ -2766,11 +2785,21 @@ class TestSessionAPIsDummy(DBusUtil, unittest.TestCase):
' ]\n'
' array [\n'
' ]\n'
' int32 -1\n'])
' int32 -1\n']
or [])
# done as part of post-processing in runTest()
self.runTestDBusCheck = checkDBusLog
@timeout(120)
def testAutoSyncLocalSuccess(self):
"""TestSessionAPIsDummy.testAutoSyncLocalSuccess - test that auto-sync is done successfully for local sync between file backends, with notifications"""
self.doAutoSyncLocalSuccess(3)
@timeout(120)
def testAutoSyncLocalSuccessQuiet(self):
"""TestSessionAPIsDummy.testAutoSyncLocalSuccessQuiet - test that auto-sync is done successfully for local sync between file backends, without notifications"""
self.doAutoSyncLocalSuccess(1)
class TestSessionAPIsReal(DBusUtil, unittest.TestCase):
""" This class is used to test those unit tests of session APIs, depending on doing sync.
@ -4396,6 +4425,7 @@ peers/scheduleworld/config.ini:# password =
.internal.ini:contextCurVersion = {3}
config.ini:# logdir =
peers/scheduleworld/config.ini:# loglevel = 0
peers/scheduleworld/config.ini:# notifyLevel = 3
peers/scheduleworld/config.ini:# printChanges = 1
peers/scheduleworld/config.ini:# dumpData = 1
config.ini:# maxlogdirs = 10
@ -4597,6 +4627,7 @@ spds/syncml/config.txt:# username =
spds/syncml/config.txt:# password =
spds/syncml/config.txt:# logdir =
spds/syncml/config.txt:# loglevel = 0
spds/syncml/config.txt:# notifyLevel = 3
spds/syncml/config.txt:# printChanges = 1
spds/syncml/config.txt:# dumpData = 1
spds/syncml/config.txt:# maxlogdirs = 10
@ -5521,6 +5552,8 @@ logdir (no default, shared)
loglevel (0, unshared)
notifyLevel (3, unshared)
printChanges (TRUE, unshared)
dumpData (TRUE, unshared)