Notifications: use a single settings file.

There were 3 setting files, each an archived BMessage. Now there is only
one with all the data inside.
* Rework the SettingsPane class to save and load settings from a
message, rather than having each panel pick a file path on its own
* Move saving the app filters to the preference app, rather than the
server (so it's done at the same place as other settings)
* Rework loading prefs in the server so the settings message is read
from the file once and all settings are loaded from it.

This turns out to be more changes than I anticipated.
Fixes #9424.
This commit is contained in:
Adrien Destugues 2014-10-21 18:46:17 +02:00
parent fe2b689642
commit 015a928b88
15 changed files with 142 additions and 278 deletions

View File

@ -13,10 +13,7 @@
const uint32 kNotificationMessage = 'nssm';
// Settings constants
extern const char* kSettingsDirectory;
extern const char* kFiltersSettings;
extern const char* kGeneralSettings;
extern const char* kDisplaySettings;
extern const char* kSettingsFile;
// General settings
extern const char* kAutoStartName;

View File

@ -52,9 +52,6 @@ DisplayView::DisplayView(SettingsHost* host)
fIconSize->SetLabelFromMarked(true);
fIconSizeField = new BMenuField(B_TRANSLATE("Icon size:"), fIconSize);
// Load settings
Load();
// Calculate inset
float inset = ceilf(be_plain_font->Size() * 0.7f);
@ -92,30 +89,20 @@ DisplayView::MessageReceived(BMessage* msg)
status_t
DisplayView::Load()
DisplayView::Load(BMessage& settings)
{
#if 0
BPath path;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
return B_ERROR;
path.Append(kSettingsDirectory);
if (create_directory(path.Path(), 0755) != B_OK) {
BAlert* alert = new BAlert("",
B_TRANSLATE("There was a problem saving the preferences.\n"
"It's possible you don't have write access to the "
"settings directory."), B_TRANSLATE("OK"), NULL, NULL,
B_WIDTH_AS_USUAL, B_STOP_ALERT);
alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
(void)alert->Go();
}
path.Append(kDisplaySettings);
path.Append(kSettingsFile);
BFile file(path.Path(), B_READ_ONLY);
BMessage settings;
settings.Unflatten(&file);
#endif
char buffer[255];
int32 setting;
@ -144,18 +131,8 @@ DisplayView::Load()
status_t
DisplayView::Save()
DisplayView::Save(BMessage& settings)
{
BPath path;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
return B_ERROR;
path.Append(kSettingsDirectory);
path.Append(kDisplaySettings);
BMessage settings;
float width = atof(fWindowWidth->Text());
settings.AddFloat(kWidthName, width);
@ -169,19 +146,6 @@ DisplayView::Save()
}
settings.AddInt32(kIconSizeName, (int32)iconSize);
// Save settings file
BFile file(path.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
status_t ret = settings.Flatten(&file);
if (ret != B_OK) {
BAlert* alert = new BAlert("",
B_TRANSLATE("Can't save preferenes, you probably don't have "
"write access to the settings directory or the disk is full."),
B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT);
alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
(void)alert->Go();
return ret;
}
return B_OK;
}

View File

@ -20,8 +20,8 @@ public:
virtual void MessageReceived(BMessage* msg);
// SettingsPane hooks
status_t Load();
status_t Save();
status_t Load(BMessage&);
status_t Save(BMessage&);
status_t Revert();
private:

View File

@ -65,9 +65,6 @@ GeneralView::GeneralView(SettingsHost* host)
// TODO: Here will come a screen representation with the four corners
// clickable
// Load settings
Load();
// Calculate inset
float inset = ceilf(be_plain_font->Size() * 0.7f);
@ -180,31 +177,8 @@ GeneralView::MessageReceived(BMessage* msg)
status_t
GeneralView::Load()
GeneralView::Load(BMessage& settings)
{
BPath path;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
return B_ERROR;
path.Append(kSettingsDirectory);
if (create_directory(path.Path(), 0755) != B_OK) {
BAlert* alert = new BAlert("",
B_TRANSLATE("There was a problem saving the preferences.\n"
"It's possible you don't have write access to the "
"settings directory."), B_TRANSLATE("OK"), NULL, NULL,
B_WIDTH_AS_USUAL, B_STOP_ALERT);
alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
(void)alert->Go();
}
path.Append(kGeneralSettings);
BMessage settings;
BFile file(path.Path(), B_READ_ONLY);
settings.Unflatten(&file);
char buffer[255];
fNotificationBox->SetValue(_IsServerRunning() ? B_CONTROL_ON : B_CONTROL_OFF);
@ -225,39 +199,14 @@ GeneralView::Load()
status_t
GeneralView::Save()
GeneralView::Save(BMessage& settings)
{
BPath path;
status_t ret = B_OK;
ret = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
if (ret != B_OK)
return ret;
path.Append(kSettingsDirectory);
path.Append(kGeneralSettings);
BMessage settings;
bool autoStart = (fAutoStart->Value() == B_CONTROL_ON);
settings.AddBool(kAutoStartName, autoStart);
int32 timeout = atol(fTimeout->Text());
settings.AddInt32(kTimeoutName, timeout);
// Save settings file
BFile file(path.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
ret = settings.Flatten(&file);
if (ret != B_OK) {
BAlert* alert = new BAlert("",
B_TRANSLATE("An error occurred saving the preferences.\n"
"It's possible you are running out of disk space."),
B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT);
alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
(void)alert->Go();
return ret;
}
// Find server path
entry_ref ref;
if (!_CanFindServer(&ref)) {
@ -273,7 +222,8 @@ GeneralView::Save()
BPath serverPath(&ref);
// Start server at boot time
ret = find_directory(B_USER_SETTINGS_DIRECTORY, &path, true);
BPath path;
status_t ret = find_directory(B_USER_SETTINGS_DIRECTORY, &path, true);
if (ret != B_OK) {
BAlert* alert = new BAlert("",
B_TRANSLATE("Can't save preferences, you probably don't have "

View File

@ -20,8 +20,8 @@ public:
virtual void MessageReceived(BMessage* msg);
// SettingsPane hooks
status_t Load();
status_t Save();
status_t Load(BMessage&);
status_t Save(BMessage&);
status_t Revert();
private:

View File

@ -47,12 +47,10 @@ const int32 kDateIndex = 1;
const int32 kTypeIndex = 2;
const int32 kAllowIndex = 3;
const int32 kSettingChanged = '_STC';
NotificationsView::NotificationsView()
NotificationsView::NotificationsView(SettingsHost* host)
:
BView("apps", B_WILL_DRAW)
SettingsPane("apps", host)
{
BRect rect(0, 0, 100, 100);
@ -100,10 +98,6 @@ NotificationsView::NotificationsView()
(kCLVTitlePadding * 2), rect.Width(), B_TRUNCATE_END, B_ALIGN_LEFT);
fNotifications->AddColumn(fAllowCol, kAllowIndex);
// Load the applications list
_LoadAppUsage();
_PopulateApplications();
// Calculate inset
float inset = ceilf(be_plain_font->Size() * 0.7f);
@ -169,33 +163,8 @@ NotificationsView::MessageReceived(BMessage* msg)
status_t
NotificationsView::_LoadAppUsage()
NotificationsView::Load(BMessage& settings)
{
BPath path;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
return B_ERROR;
path.Append(kSettingsDirectory);
if (create_directory(path.Path(), 0755) != B_OK) {
BAlert* alert = new BAlert("",
B_TRANSLATE("There was a problem saving the preferences.\n"
"It's possible you don't have write access to the "
"settings directory."), B_TRANSLATE("OK"), NULL, NULL,
B_WIDTH_AS_USUAL, B_STOP_ALERT);
alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
(void)alert->Go();
return B_ERROR;
}
path.Append(kFiltersSettings);
BFile file(path.Path(), B_READ_ONLY);
BMessage settings;
if (settings.Unflatten(&file) != B_OK)
return B_ERROR;
type_code type;
int32 count = 0;
@ -215,6 +184,20 @@ NotificationsView::_LoadAppUsage()
fAppFilters[app->Name()] = app;
}
// Load the applications list
_PopulateApplications();
return B_OK;
}
status_t
NotificationsView::Save(BMessage& storage)
{
appusage_t::iterator fIt;
for (fIt = fAppFilters.begin(); fIt != fAppFilters.end(); fIt++)
storage.AddFlat("app_usage", fIt->second);
return B_OK;
}

View File

@ -10,6 +10,8 @@
#include <notification/AppUsage.h>
#include "SettingsPane.h"
typedef std::map<BString, AppUsage *> appusage_t;
class BCheckBox;
@ -18,15 +20,17 @@ class BColumnListView;
class BStringColumn;
class BDateColumn;
class NotificationsView : public BView {
class NotificationsView : public SettingsPane {
public:
NotificationsView();
NotificationsView(SettingsHost* host);
virtual void AttachedToWindow();
virtual void MessageReceived(BMessage* msg);
private:
status_t _LoadAppUsage();
status_t Load(BMessage&);
status_t Save(BMessage&);
status_t Revert() {return B_OK;} // FIXME implement this
void _PopulateApplications();
void _Populate(AppUsage* usage);

View File

@ -35,7 +35,7 @@ PrefletView::PrefletView(SettingsHost* host)
// Pages
GeneralView* general = new GeneralView(host);
DisplayView* display = new DisplayView(host);
NotificationsView* apps = new NotificationsView();
NotificationsView* apps = new NotificationsView(host);
// Page selector
BTab* tab = new BTab();

View File

@ -7,13 +7,19 @@
* Pier Luigi Fiorini, pierluigi.fiorini@gmail.com
*/
#include "PrefletWin.h"
#include <Alert.h>
#include <Application.h>
#include <GroupLayout.h>
#include <GroupLayoutBuilder.h>
#include <Button.h>
#include <Catalog.h>
#include <FindDirectory.h>
#include <GroupLayout.h>
#include <GroupLayoutBuilder.h>
#include <Path.h>
#include <notification/Notifications.h>
#include "PrefletWin.h"
#include "PrefletView.h"
@ -60,6 +66,8 @@ PrefletWin::PrefletWin()
.SetInsets(inset, inset, inset, inset)
);
ReloadSettings();
// Center this window on screen and show it
CenterOnScreen();
Show();
@ -71,18 +79,44 @@ PrefletWin::MessageReceived(BMessage* msg)
{
switch (msg->what) {
case kApply:
{
BPath path;
status_t ret = B_OK;
ret = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
if (ret != B_OK)
return;
path.Append(kSettingsFile);
BMessage settingsStore;
for (int32 i = 0; i < fMainView->CountPages(); i++) {
SettingsPane* pane =
dynamic_cast<SettingsPane*>(fMainView->PageAt(i));
if (pane) {
if (pane->Save() == B_OK) {
if (pane->Save(settingsStore) == B_OK) {
fApply->SetEnabled(false);
fRevert->SetEnabled(true);
} else
break;
}
}
// Save settings file
BFile file(path.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
ret = settingsStore.Flatten(&file);
if (ret != B_OK) {
BAlert* alert = new BAlert("",
B_TRANSLATE("An error occurred saving the preferences.\n"
"It's possible you are running out of disk space."),
B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_AS_USUAL,
B_STOP_ALERT);
alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
(void)alert->Go();
}
break;
}
case kRevert:
for (int32 i = 0; i < fMainView->CountPages(); i++) {
SettingsPane* pane =
@ -112,3 +146,27 @@ PrefletWin::SettingChanged()
{
fApply->SetEnabled(true);
}
void
PrefletWin::ReloadSettings()
{
BPath path;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
return;
// FIXME don't load this again here, share with other tabs!
path.Append(kSettingsFile);
BMessage settings;
BFile file(path.Path(), B_READ_ONLY);
settings.Unflatten(&file);
for (int32 i = 0; i < fMainView->CountPages(); i++) {
SettingsPane* pane =
dynamic_cast<SettingsPane*>(fMainView->PageAt(i));
if (pane)
pane->Load(settings);
}
}

View File

@ -22,6 +22,7 @@ public:
virtual void MessageReceived(BMessage* msg);
virtual void SettingChanged();
void ReloadSettings();
private:
PrefletView* fMainView;

View File

@ -8,10 +8,6 @@
*/
#include <Message.h>
#include <Node.h>
#include <Path.h>
#include <FindDirectory.h>
#include <Directory.h>
#include "SettingsPane.h"
#include "SettingsHost.h"

View File

@ -20,8 +20,8 @@ public:
virtual void MessageReceived(BMessage* msg);
virtual status_t Load() = 0;
virtual status_t Save() = 0;
virtual status_t Load(BMessage&) = 0;
virtual status_t Save(BMessage&) = 0;
virtual status_t Revert() = 0;
protected:

View File

@ -65,7 +65,6 @@ NotificationWindow::NotificationWindow()
SetLayout(new BGroupLayout(B_VERTICAL, 0));
_LoadSettings(true);
_LoadAppFilters(true);
// Start the message loop
Hide();
@ -125,7 +124,6 @@ NotificationWindow::MessageReceived(BMessage* message)
case B_NODE_MONITOR:
{
_LoadSettings();
_LoadAppFilters();
break;
}
case B_COUNT_PROPERTIES:
@ -407,108 +405,21 @@ NotificationWindow::SetPosition()
void
NotificationWindow::_LoadSettings(bool startMonitor)
{
_LoadGeneralSettings(startMonitor);
_LoadDisplaySettings(startMonitor);
}
void
NotificationWindow::_LoadAppFilters(bool startMonitor)
{
BPath path;
BMessage settings;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
return;
path.Append(kSettingsDirectory);
if (create_directory(path.Path(), 0755) != B_OK)
return;
path.Append(kFiltersSettings);
path.Append(kSettingsFile);
BFile file(path.Path(), B_READ_ONLY);
BMessage settings;
if (settings.Unflatten(&file) != B_OK)
return;
settings.Unflatten(&file);
type_code type;
int32 count = 0;
if (settings.GetInfo("app_usage", &type, &count) != B_OK)
return;
for (int32 i = 0; i < count; i++) {
AppUsage* app = new AppUsage();
settings.FindFlat("app_usage", i, app);
fAppFilters[app->Name()] = app;
}
if (startMonitor) {
node_ref nref;
BEntry entry(path.Path());
entry.GetNodeRef(&nref);
if (watch_node(&nref, B_WATCH_ALL, BMessenger(this)) != B_OK) {
BAlert* alert = new BAlert(B_TRANSLATE("Warning"),
B_TRANSLATE("Couldn't start filter monitor."
" Live filter changes disabled."), B_TRANSLATE("Darn."));
alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
alert->Go();
}
}
}
void
NotificationWindow::_SaveAppFilters()
{
BPath path;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
return;
path.Append(kSettingsDirectory);
path.Append(kFiltersSettings);
BMessage settings;
BFile file(path.Path(), B_WRITE_ONLY);
appfilter_t::iterator fIt;
for (fIt = fAppFilters.begin(); fIt != fAppFilters.end(); fIt++)
settings.AddFlat("app_usage", fIt->second);
settings.Flatten(&file);
}
void
NotificationWindow::_LoadGeneralSettings(bool startMonitor)
{
BPath path;
BMessage settings;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
return;
path.Append(kSettingsDirectory);
if (create_directory(path.Path(), 0755) == B_OK) {
path.Append(kGeneralSettings);
BFile file(path.Path(), B_READ_ONLY);
settings.Unflatten(&file);
}
if (settings.FindInt32(kTimeoutName, &fTimeout) != B_OK)
fTimeout = kDefaultTimeout;
// Notify the view about the change
views_t::iterator it;
for (it = fViews.begin(); it != fViews.end(); ++it) {
NotificationView* view = (*it);
view->Invalidate();
}
_LoadGeneralSettings(settings);
_LoadDisplaySettings(settings);
_LoadAppFilters(settings);
if (startMonitor) {
node_ref nref;
@ -527,22 +438,40 @@ NotificationWindow::_LoadGeneralSettings(bool startMonitor)
void
NotificationWindow::_LoadDisplaySettings(bool startMonitor)
NotificationWindow::_LoadAppFilters(BMessage& settings)
{
BPath path;
BMessage settings;
type_code type;
int32 count = 0;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
if (settings.GetInfo("app_usage", &type, &count) != B_OK)
return;
path.Append(kSettingsDirectory);
if (create_directory(path.Path(), 0755) == B_OK) {
path.Append(kDisplaySettings);
BFile file(path.Path(), B_READ_ONLY);
settings.Unflatten(&file);
for (int32 i = 0; i < count; i++) {
AppUsage* app = new AppUsage();
settings.FindFlat("app_usage", i, app);
fAppFilters[app->Name()] = app;
}
}
void
NotificationWindow::_LoadGeneralSettings(BMessage& settings)
{
if (settings.FindInt32(kTimeoutName, &fTimeout) != B_OK)
fTimeout = kDefaultTimeout;
// Notify the view about the change
views_t::iterator it;
for (it = fViews.begin(); it != fViews.end(); ++it) {
NotificationView* view = (*it);
view->Invalidate();
}
}
void
NotificationWindow::_LoadDisplaySettings(BMessage& settings)
{
int32 setting;
if (settings.FindFloat(kWidthName, &fWidth) != B_OK)
@ -561,18 +490,4 @@ NotificationWindow::_LoadDisplaySettings(bool startMonitor)
NotificationView* view = (*it);
view->Invalidate();
}
if (startMonitor) {
node_ref nref;
BEntry entry(path.Path());
entry.GetNodeRef(&nref);
if (watch_node(&nref, B_WATCH_ALL, BMessenger(this)) != B_OK) {
BAlert* alert = new BAlert(B_TRANSLATE("Warning"),
B_TRANSLATE("Couldn't start display settings monitor.\n"
"Live filter changes disabled."), B_TRANSLATE("OK"));
alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
alert->Go();
}
}
}

View File

@ -65,10 +65,9 @@ private:
void SetPosition();
void _LoadSettings(bool startMonitor = false);
void _LoadAppFilters(bool startMonitor = false);
void _SaveAppFilters();
void _LoadGeneralSettings(bool startMonitor);
void _LoadDisplaySettings(bool startMonitor);
void _LoadAppFilters(BMessage& settings);
void _LoadGeneralSettings(BMessage& settings);
void _LoadDisplaySettings(BMessage& settings);
views_t fViews;
appview_t fAppViews;

View File

@ -8,10 +8,7 @@
// Settings constants
const char* kSettingsDirectory = "system/notifications";
const char* kFiltersSettings = "filters";
const char* kGeneralSettings = "general";
const char* kDisplaySettings = "display";
const char* kSettingsFile = "system/notifications";
// General settings
const char* kAutoStartName = "auto-start";