diff --git a/headers/os/app/Notification.h b/headers/os/app/Notification.h index d11e4b1c2c..0d64505326 100644 --- a/headers/os/app/Notification.h +++ b/headers/os/app/Notification.h @@ -1,5 +1,5 @@ /* - * Copyright 2010, Haiku, Inc. All Rights Reserved. + * Copyright 2010-2017, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. */ #ifndef _NOTIFICATION_H @@ -34,6 +34,9 @@ public: static BArchivable* Instantiate(BMessage* archive); virtual status_t Archive(BMessage* archive, bool deep = true) const; + const char* SourceSignature() const; + const char* SourceName() const; + notification_type Type() const; const char* Group() const; @@ -73,6 +76,8 @@ public: private: status_t fInitStatus; + BString fSourceSignature; + BString fSourceName; notification_type fType; BString fGroup; BString fTitle; diff --git a/headers/private/notification/AppUsage.h b/headers/private/notification/AppUsage.h index 2c42961ef5..53b419ce83 100644 --- a/headers/private/notification/AppUsage.h +++ b/headers/private/notification/AppUsage.h @@ -1,5 +1,5 @@ /* - * Copyright 2010, Haiku, Inc. All Rights Reserved. + * Copyright 2010-2017, Haiku, Inc. All Rights Reserved. * Copyright 2008-2009, Pier Luigi Fiorini. All Rights Reserved. * Copyright 2004-2008, Michael Davidson. All Rights Reserved. * Copyright 2004-2007, Mikael Eiman. All Rights Reserved. @@ -17,16 +17,13 @@ #include class BMessage; -class NotificationReceived; - -typedef std::map notification_t; class AppUsage : public BFlattenable { public: AppUsage(); AppUsage(const char* name, + const char* signature, bool allow = true); - ~AppUsage(); virtual bool AllowsTypeCode(type_code code) const; virtual status_t Flatten(void* buffer, ssize_t numBytes) const; @@ -36,17 +33,15 @@ public: virtual status_t Unflatten(type_code code, const void* buffer, ssize_t numBytes); - const char* Name(); - bool Allowed(const char* title, notification_type type); + const char* AppName(); + const char* Signature(); bool Allowed(); - NotificationReceived* NotificationAt(int32 index); - int32 Notifications(); - void AddNotification(NotificationReceived* notification); + void SetAllowed(bool allow); private: - BString fName; + BString fAppName; + BString fSignature; bool fAllow; - notification_t fNotifications; }; #endif // _APP_USAGE_H diff --git a/headers/private/notification/Notifications.h b/headers/private/notification/Notifications.h index eb4ca737e1..18298a4270 100644 --- a/headers/private/notification/Notifications.h +++ b/headers/private/notification/Notifications.h @@ -1,11 +1,12 @@ /* - * Copyright 2010-2014, Haiku, Inc. All Rights Reserved. + * Copyright 2010-2017, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. */ #ifndef _NOTIFICATIONS_H #define _NOTIFICATIONS_H #include +#include #define kNotificationServerSignature "application/x-vnd.Haiku-notification_server" @@ -18,18 +19,18 @@ extern const char* kSettingsFile; // General settings extern const char* kAutoStartName; extern const char* kTimeoutName; +extern const char* kWidthName; +extern const char* kIconSizeName; // General default settings const bool kDefaultAutoStart = true; const int32 kDefaultTimeout = 10; - -// Display settings -extern const char* kWidthName; -extern const char* kIconSizeName; -extern const char* kLayoutName; - -// Display default settings +const int32 kMinimumTimeout = 3; +const int32 kMaximumTimeout = 30; const float kDefaultWidth = 300.0f; +const float kMinimumWidth = 300.0f; +const float kMaximumWidth = 1000.0f; +const int32 kWidthStep = 50; const icon_size kDefaultIconSize = B_LARGE_ICON; #endif // _NOTIFICATIONS_H diff --git a/src/kits/app/Notification.cpp b/src/kits/app/Notification.cpp index 1a14d5e68e..266aecde9f 100644 --- a/src/kits/app/Notification.cpp +++ b/src/kits/app/Notification.cpp @@ -1,10 +1,11 @@ /* - * Copyright 2010, Haiku, Inc. All Rights Reserved. + * Copyright 2010-2017, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com * Stephan Aßmus, superstippi@gmx.de + * Brian Hill, supernova@tycho.email */ @@ -20,6 +21,7 @@ #include #include #include +#include #include @@ -32,19 +34,24 @@ BNotification::BNotification(notification_type type) fFile(NULL), fBitmap(NULL) { + team_info teamInfo; + get_team_info(B_CURRENT_TEAM, &teamInfo); + app_info appInfo; + be_roster->GetRunningAppInfo(teamInfo.team, &appInfo); + int32 iconSize = B_LARGE_ICON; fBitmap = new BBitmap(BRect(0, 0, iconSize - 1, iconSize - 1), 0, B_RGBA32); if (fBitmap) { - team_info teamInfo; - get_team_info(B_CURRENT_TEAM, &teamInfo); - app_info appInfo; - be_roster->GetRunningAppInfo(teamInfo.team, &appInfo); if (BNodeInfo::GetTrackerIcon(&appInfo.ref, fBitmap, icon_size(iconSize)) != B_OK) { delete fBitmap; fBitmap = NULL; } } + fSourceSignature = appInfo.signature; + BPath path(&appInfo.ref); + if (path.InitCheck() == B_OK) + fSourceName = path.Leaf(); } @@ -56,6 +63,14 @@ BNotification::BNotification(BMessage* archive) fFile(NULL), fBitmap(NULL) { + BString appName; + if (archive->FindString("_appname", &appName) == B_OK) + fSourceName = appName; + + BString signature; + if (archive->FindString("_signature", &signature) == B_OK) + fSourceSignature = signature; + int32 type; if (archive->FindInt32("_type", &type) == B_OK) fType = (notification_type)type; @@ -166,6 +181,12 @@ BNotification::Archive(BMessage* archive, bool deep) const { status_t status = BArchivable::Archive(archive, deep); + if (status == B_OK) + status = archive->AddString("_appname", fSourceName); + + if (status == B_OK) + status = archive->AddString("_signature", fSourceSignature); + if (status == B_OK) status = archive->AddInt32("_type", (int32)fType); @@ -220,6 +241,28 @@ BNotification::Archive(BMessage* archive, bool deep) const } +/*! \brief Returns source application signature. + + \return Source application signature. +*/ +const char* +BNotification::SourceSignature() const +{ + return fSourceSignature; +} + + +/*! \brief Returns source application name. + + \return Source application name. +*/ +const char* +BNotification::SourceName() const +{ + return fSourceName; +} + + /*! \brief Notification's type. \return A value of the notification_type enum that represents diff --git a/src/preferences/notifications/AppRefFilter.cpp b/src/preferences/notifications/AppRefFilter.cpp new file mode 100644 index 0000000000..7357f8657f --- /dev/null +++ b/src/preferences/notifications/AppRefFilter.cpp @@ -0,0 +1,66 @@ +/* + * Copyright 2017, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Brian Hill, supernova@tycho.email + */ + +#include "AppRefFilter.h" + +#include + + +/* This class filters only applications in an open file panel */ +AppRefFilter::AppRefFilter() + : + BRefFilter() +{ +} + + +bool +AppRefFilter::Filter(const entry_ref *ref, BNode *node, + struct stat_beos *st, const char *filetype) +{ + char* type = NULL; + const char *constFileType; + // resolve symlinks + bool isSymlink = strcmp("application/x-vnd.Be-symlink", filetype) == 0; + if (isSymlink) { + BEntry linkedEntry(ref, true); + if (linkedEntry.InitCheck()!=B_OK) + return false; + BNode linkedNode(&linkedEntry); + if (linkedNode.InitCheck()!=B_OK) + return false; + BNodeInfo linkedNodeInfo(&linkedNode); + if (linkedNodeInfo.InitCheck()!=B_OK) + return false; + type = new char[B_ATTR_NAME_LENGTH]; + if (linkedNodeInfo.GetType(type)!=B_OK) { + delete[] type; + return false; + } + constFileType = type; + } else + constFileType = filetype; + + bool pass = false; + //folders + if (strcmp("application/x-vnd.Be-directory", constFileType) == 0) + pass = true; + //volumes + else if (strcmp("application/x-vnd.Be-volume", constFileType) == 0) + pass = true; + //apps + else if (strcmp("application/x-vnd.Be-elfexecutable", constFileType) == 0) + pass = true; + //hack for Haiku? Some apps are defined by MIME this way + else if (strcmp("application/x-vnd.be-elfexecutable", constFileType) == 0) + pass = true; + + if (isSymlink) + delete[] type; + return pass; +} diff --git a/src/preferences/notifications/AppRefFilter.h b/src/preferences/notifications/AppRefFilter.h new file mode 100644 index 0000000000..df9b4f2199 --- /dev/null +++ b/src/preferences/notifications/AppRefFilter.h @@ -0,0 +1,21 @@ +/* + * Copyright 2017, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef EP_APPREFFILTER_H +#define EP_APPREFFILTER_H + +#include +#include + + +class AppRefFilter : public BRefFilter { +public: + AppRefFilter(); + virtual bool Filter(const entry_ref *ref, + BNode *node, + struct stat_beos *st, + const char *filetype); +}; + +#endif diff --git a/src/preferences/notifications/DisplayView.cpp b/src/preferences/notifications/DisplayView.cpp deleted file mode 100644 index afe02a0928..0000000000 --- a/src/preferences/notifications/DisplayView.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright 2010, Haiku, Inc. All Rights Reserved. - * Copyright 2009, Pier Luigi Fiorini. - * Distributed under the terms of the MIT License. - * - * Authors: - * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com - */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "DisplayView.h" -#include "SettingsHost.h" - - -#undef B_TRANSLATION_CONTEXT -#define B_TRANSLATION_CONTEXT "DisplayView" - - -DisplayView::DisplayView(SettingsHost* host) - : - SettingsPane("display", host) -{ - // Window width - fWindowWidth = new BTextControl(B_TRANSLATE("Window width:"), NULL, - new BMessage(kSettingChanged)); - - // Icon size - fIconSize = new BMenu("iconSize"); - fIconSize->AddItem(new BMenuItem(B_TRANSLATE("Mini icon"), - new BMessage(kSettingChanged))); - fIconSize->AddItem(new BMenuItem(B_TRANSLATE("Large icon"), - new BMessage(kSettingChanged))); - fIconSize->SetLabelFromMarked(true); - fIconSizeField = new BMenuField(B_TRANSLATE("Icon size:"), fIconSize); - - BLayoutBuilder::Grid<>(this, B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING) - .Add(fWindowWidth->CreateLabelLayoutItem(), 0, 0) - .Add(fWindowWidth->CreateTextViewLayoutItem(), 1, 0) - .Add(fIconSizeField->CreateLabelLayoutItem(), 0, 1) - .Add(fIconSizeField->CreateMenuBarLayoutItem(), 1, 1) - .AddGlue(0, 2) - .SetInsets(B_USE_WINDOW_SPACING); -} - - -void -DisplayView::AttachedToWindow() -{ - fWindowWidth->SetTarget(this); - fIconSize->SetTargetForItems(this); -} - - -void -DisplayView::MessageReceived(BMessage* msg) -{ - switch (msg->what) { - case kSettingChanged: - SettingsPane::MessageReceived(msg); - break; - default: - BView::MessageReceived(msg); - } -} - - -status_t -DisplayView::Load(BMessage& settings) -{ -#if 0 - BPath path; - - if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) - return B_ERROR; - - path.Append(kSettingsFile); - - BFile file(path.Path(), B_READ_ONLY); - BMessage settings; - settings.Unflatten(&file); -#endif - - char buffer[255]; - int32 setting; - BMenuItem* item = NULL; - - float width; - if (settings.FindFloat(kWidthName, &width) != B_OK) - width = kDefaultWidth; - (void)sprintf(buffer, "%.2f", width); - fWindowWidth->SetText(buffer); - - icon_size iconSize; - if (settings.FindInt32(kIconSizeName, &setting) != B_OK) - iconSize = kDefaultIconSize; - else - iconSize = (icon_size)setting; - if (iconSize == B_MINI_ICON) - item = fIconSize->ItemAt(0); - else - item = fIconSize->ItemAt(1); - if (item) - item->SetMarked(true); - - return B_OK; -} - - -status_t -DisplayView::Save(BMessage& settings) -{ - float width = atof(fWindowWidth->Text()); - settings.AddFloat(kWidthName, width); - - icon_size iconSize = kDefaultIconSize; - switch (fIconSize->IndexOf(fIconSize->FindMarked())) { - case 0: - iconSize = B_MINI_ICON; - break; - default: - iconSize = B_LARGE_ICON; - } - settings.AddInt32(kIconSizeName, (int32)iconSize); - - return B_OK; -} - - -status_t -DisplayView::Revert() -{ - return B_ERROR; -} diff --git a/src/preferences/notifications/DisplayView.h b/src/preferences/notifications/DisplayView.h deleted file mode 100644 index c651865c82..0000000000 --- a/src/preferences/notifications/DisplayView.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2010, Haiku, Inc. All Rights Reserved. - * Copyright 2009, Pier Luigi Fiorini. - * Distributed under the terms of the MIT License. - */ -#ifndef _DISPLAY_VIEW_H -#define _DISPLAY_VIEW_H - -#include "SettingsPane.h" - -class BTextControl; -class BMenu; -class BMenuField; - -class DisplayView : public SettingsPane { -public: - DisplayView(SettingsHost* host); - - virtual void AttachedToWindow(); - virtual void MessageReceived(BMessage* msg); - - // SettingsPane hooks - status_t Load(BMessage&); - status_t Save(BMessage&); - status_t Revert(); - -private: - BTextControl* fWindowWidth; - BMenu* fIconSize; - BMenuField* fIconSizeField; - -}; - -#endif // _DISPLAY_VIEW_H diff --git a/src/preferences/notifications/GeneralView.cpp b/src/preferences/notifications/GeneralView.cpp index a11f4b9b9c..bbd831f138 100644 --- a/src/preferences/notifications/GeneralView.cpp +++ b/src/preferences/notifications/GeneralView.cpp @@ -1,10 +1,11 @@ /* - * Copyright 2010-2013, Haiku, Inc. All Rights Reserved. + * Copyright 2010-2017, Haiku, Inc. All Rights Reserved. * Copyright 2009, Pier Luigi Fiorini. * Distributed under the terms of the MIT License. * * Authors: * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com + * Brian Hill, supernova@tycho.email */ #include @@ -13,9 +14,9 @@ #include #include +#include #include #include -#include #include #include #include @@ -26,70 +27,87 @@ #include #include #include -#include #include -#include #include #include #include #include "GeneralView.h" +#include "NotificationsConstants.h" #include "SettingsHost.h" #undef B_TRANSLATION_CONTEXT #define B_TRANSLATION_CONTEXT "GeneralView" -const int32 kToggleNotifications = '_TSR'; + +const uint32 kToggleNotifications = '_TSR'; +const uint32 kWidthChanged = '_WIC'; +const uint32 kTimeoutChanged = '_TIC'; +const uint32 kServerChangeTriggered = '_SCT'; +const BString kSampleMessageID("NotificationsSample"); + GeneralView::GeneralView(SettingsHost* host) : SettingsPane("general", host) { - // Notifications + // Notification server fNotificationBox = new BCheckBox("server", B_TRANSLATE("Enable notifications"), new BMessage(kToggleNotifications)); + BBox* box = new BBox("box"); + box->SetLabel(fNotificationBox); - // Autostart - fAutoStart = new BCheckBox("autostart", - B_TRANSLATE("Enable notifications at startup"), - new BMessage(kSettingChanged)); + // Window width + int32 minWidth = int32(kMinimumWidth / kWidthStep); + int32 maxWidth = int32(kMaximumWidth / kWidthStep); + fWidthSlider = new BSlider("width", B_TRANSLATE("Window width:"), + new BMessage(kWidthChanged), minWidth, maxWidth, B_HORIZONTAL); + fWidthSlider->SetHashMarks(B_HASH_MARKS_BOTTOM); + fWidthSlider->SetHashMarkCount(maxWidth - minWidth + 1); + BString minWidthLabel; + minWidthLabel << int32(kMinimumWidth); + BString maxWidthLabel; + maxWidthLabel << int32(kMaximumWidth); + fWidthSlider->SetLimitLabels( + B_TRANSLATE_COMMENT(minWidthLabel.String(), "Slider low text"), + B_TRANSLATE_COMMENT(maxWidthLabel.String(), "Slider high text")); // Display time - fTimeout = new BTextControl(B_TRANSLATE("Hide notifications from screen" - " after"), NULL, new BMessage(kSettingChanged)); - BStringView* displayTimeLabel = new BStringView("dt_label", - B_TRANSLATE("seconds of inactivity")); - - // Default position - // TODO: Here will come a screen representation with the four corners - // clickable + fDurationSlider = new BSlider("duration", B_TRANSLATE("Duration:"), + new BMessage(kTimeoutChanged), kMinimumTimeout, kMaximumTimeout, + B_HORIZONTAL); + fDurationSlider->SetHashMarks(B_HASH_MARKS_BOTTOM); + fDurationSlider->SetHashMarkCount(kMaximumTimeout - kMinimumTimeout + 1); + BString minLabel; + minLabel << kMinimumTimeout; + BString maxLabel; + maxLabel << kMaximumTimeout; + fDurationSlider->SetLimitLabels( + B_TRANSLATE_COMMENT(minLabel.String(), "Slider low text"), + B_TRANSLATE_COMMENT(maxLabel.String(), "Slider high text")); + box->AddChild(BLayoutBuilder::Group<>(B_VERTICAL) + .SetInsets(B_USE_DEFAULT_SPACING) + .Add(fWidthSlider) + .Add(fDurationSlider) + .AddGlue() + .View()); + BLayoutBuilder::Group<>(this, B_VERTICAL) - .AddGroup(B_HORIZONTAL, B_USE_WINDOW_SPACING) - .Add(fNotificationBox) - .AddGlue() - .End() - .AddGroup(B_VERTICAL, B_USE_WINDOW_SPACING) - .Add(fAutoStart) - .AddGroup(B_HORIZONTAL) - .AddGroup(B_HORIZONTAL, 2) - .Add(fTimeout) - .Add(displayTimeLabel) - .End() - .End() - .End() .SetInsets(B_USE_WINDOW_SPACING) - .AddGlue(); + .Add(box) + .End(); } void GeneralView::AttachedToWindow() { + BView::AttachedToWindow(); fNotificationBox->SetTarget(this); - fAutoStart->SetTarget(this); - fTimeout->SetTarget(this); + fWidthSlider->SetTarget(this); + fDurationSlider->SetTarget(this); } @@ -99,70 +117,23 @@ GeneralView::MessageReceived(BMessage* msg) switch (msg->what) { case kToggleNotifications: { - entry_ref ref; - - // Check if server is available - if (!_CanFindServer(&ref)) { - BAlert* alert = new BAlert(B_TRANSLATE("Notifications"), - B_TRANSLATE("The notifications server cannot be" - " found, this means your InfoPopper installation was" - " not successfully completed."), B_TRANSLATE("OK"), - NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT); - alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); - (void)alert->Go(); - return; - } - - if (fNotificationBox->Value() == B_CONTROL_OFF) { - // Server team - team_id team = be_roster->TeamFor(kNotificationServerSignature); - - // Establish a connection to infopopper_server - status_t ret = B_ERROR; - BMessenger messenger(kNotificationServerSignature, team, &ret); - if (ret != B_OK) { - BAlert* alert = new BAlert(B_TRANSLATE( - "Notifications"), B_TRANSLATE("Notifications " - "cannot be stopped, because the server can't be" - " reached."), B_TRANSLATE("OK"), NULL, NULL, - B_WIDTH_AS_USUAL, B_STOP_ALERT); - alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); - (void)alert->Go(); - return; - } - - // Send quit message - if (messenger.SendMessage(B_QUIT_REQUESTED) != B_OK) { - BAlert* alert = new BAlert(B_TRANSLATE( - "Notifications"), B_TRANSLATE("Cannot disable" - " notifications because the server can't be " - "reached."), B_TRANSLATE("OK"), - NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT); - alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); - (void)alert->Go(); - return; - } - } else if (!_IsServerRunning()) { - // Start server - status_t err = be_roster->Launch(kNotificationServerSignature); - if (err != B_OK) { - BAlert* alert = new BAlert(B_TRANSLATE( - "Notifications"), B_TRANSLATE("Cannot enable" - " notifications because the server cannot be " - "found.\nThis means your InfoPopper installation" - " was not successfully completed."), - B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_AS_USUAL, - B_STOP_ALERT); - alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); - (void)alert->Go(); - return; - } - } + SettingsPane::SettingsChanged(false); + _EnableControls(); break; } - case kSettingChanged: - SettingsPane::MessageReceived(msg); + case kWidthChanged: { + int32 value = fWidthSlider->Value() * 50; + _SetWidthLabel(value); + SettingsPane::SettingsChanged(true); break; + } + case kTimeoutChanged: + { + int32 value = fDurationSlider->Value(); + _SetTimeoutLabel(value); + SettingsPane::SettingsChanged(true); + break; + } default: BView::MessageReceived(msg); break; @@ -173,34 +144,46 @@ GeneralView::MessageReceived(BMessage* msg) status_t GeneralView::Load(BMessage& settings) { - char buffer[255]; + bool autoStart = settings.GetBool(kAutoStartName, true); + fNotificationBox->SetValue(autoStart ? B_CONTROL_ON : B_CONTROL_OFF); - fNotificationBox->SetValue(_IsServerRunning() ? B_CONTROL_ON : B_CONTROL_OFF); + if (settings.FindFloat(kWidthName, &fOriginalWidth) != B_OK + || fOriginalWidth > kMaximumWidth + || fOriginalWidth < kMinimumWidth) + fOriginalWidth = kDefaultWidth; - bool autoStart; - if (settings.FindBool(kAutoStartName, &autoStart) != B_OK) - autoStart = kDefaultAutoStart; - fAutoStart->SetValue(autoStart ? B_CONTROL_ON : B_CONTROL_OFF); + if (settings.FindInt32(kTimeoutName, &fOriginalTimeout) != B_OK + || fOriginalTimeout > kMaximumTimeout + || fOriginalTimeout < kMinimumTimeout) + fOriginalTimeout = kDefaultTimeout; +// TODO need to save again if values outside of expected range + int32 setting; + if (settings.FindInt32(kIconSizeName, &setting) != B_OK) + fOriginalIconSize = kDefaultIconSize; + else + fOriginalIconSize = (icon_size)setting; - int32 timeout; - if (settings.FindInt32(kTimeoutName, &timeout) != B_OK) - timeout = kDefaultTimeout; - (void)sprintf(buffer, "%" B_PRId32, timeout); - fTimeout->SetText(buffer); - - return B_OK; + _EnableControls(); + + return Revert(); } status_t GeneralView::Save(BMessage& settings) { - bool autoStart = (fAutoStart->Value() == B_CONTROL_ON); + bool autoStart = (fNotificationBox->Value() == B_CONTROL_ON); settings.AddBool(kAutoStartName, autoStart); - int32 timeout = atol(fTimeout->Text()); + int32 timeout = fDurationSlider->Value(); settings.AddInt32(kTimeoutName, timeout); + float width = fWidthSlider->Value() * 50; + settings.AddFloat(kWidthName, width); + + icon_size iconSize = B_LARGE_ICON; + settings.AddInt32(kIconSizeName, (int32)iconSize); + return B_OK; } @@ -208,44 +191,97 @@ GeneralView::Save(BMessage& settings) status_t GeneralView::Revert() { - return B_ERROR; + fDurationSlider->SetValue(fOriginalTimeout); + _SetTimeoutLabel(fOriginalTimeout); + + fWidthSlider->SetValue(fOriginalWidth / 50); + _SetWidthLabel(fOriginalWidth); + + return B_OK; } bool -GeneralView::_CanFindServer(entry_ref* ref) +GeneralView::RevertPossible() { - // Try searching with be_roster - if (be_roster->FindApp(kNotificationServerSignature, ref) == B_OK) + int32 timeout = fDurationSlider->Value(); + if (fOriginalTimeout != timeout) + return true; + + int32 width = fWidthSlider->Value() * 50; + if (fOriginalWidth != width) return true; - // Try with a query and take the first result - BVolumeRoster vroster; - BVolume volume; - char volName[B_FILE_NAME_LENGTH]; - - vroster.Rewind(); - - while (vroster.GetNextVolume(&volume) == B_OK) { - if ((volume.InitCheck() != B_OK) || !volume.KnowsQuery()) - continue; - - volume.GetName(volName); - - BQuery *query = new BQuery(); - query->SetPredicate("(BEOS:APP_SIG==\"" kNotificationServerSignature - "\")"); - query->SetVolume(&volume); - query->Fetch(); - - if (query->GetNextRef(ref) == B_OK) - return true; - } - return false; } +status_t +GeneralView::Defaults() +{ + fDurationSlider->SetValue(kDefaultTimeout); + _SetTimeoutLabel(kDefaultTimeout); + + fWidthSlider->SetValue(kDefaultWidth / 50); + _SetWidthLabel(kDefaultWidth); + + return B_OK; +} + + +bool +GeneralView::DefaultsPossible() +{ + int32 timeout = fDurationSlider->Value(); + if (kDefaultTimeout != timeout) + return true; + + int32 width = fWidthSlider->Value() * 50; + if (kDefaultWidth != width) + return true; + + return false; +} + + +bool +GeneralView::UseDefaultRevertButtons() +{ + return true; +} + + +void +GeneralView::_EnableControls() +{ + bool enabled = fNotificationBox->Value() == B_CONTROL_ON; + fWidthSlider->SetEnabled(enabled); + fDurationSlider->SetEnabled(enabled); +} + + +void +GeneralView::_SetTimeoutLabel(int32 value) +{ + BString label(B_TRANSLATE("Timeout:")); + label.Append(" "); + label << value; + label.Append(" ").Append(B_TRANSLATE("seconds")); + fDurationSlider->SetLabel(label.String()); +} + + +void +GeneralView::_SetWidthLabel(int32 value) +{ + BString label(B_TRANSLATE("Width:")); + label.Append(" "); + label << value; + label.Append(" ").Append(B_TRANSLATE("pixels")); + fWidthSlider->SetLabel(label.String()); +} + + bool GeneralView::_IsServerRunning() { diff --git a/src/preferences/notifications/GeneralView.h b/src/preferences/notifications/GeneralView.h index 909fbd802e..0bd5a084b1 100644 --- a/src/preferences/notifications/GeneralView.h +++ b/src/preferences/notifications/GeneralView.h @@ -1,16 +1,24 @@ /* - * Copyright 2010, Haiku, Inc. All Rights Reserved. + * Copyright 2010-2017, Haiku, Inc. All Rights Reserved. * Copyright 2009, Pier Luigi Fiorini. * Distributed under the terms of the MIT License. */ #ifndef _GENERAL_VIEW_H #define _GENERAL_VIEW_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "SettingsPane.h" -class BCheckBox; -class BStringView; -class BTextControl; class GeneralView : public SettingsPane { public: @@ -23,14 +31,23 @@ public: status_t Load(BMessage&); status_t Save(BMessage&); status_t Revert(); + bool RevertPossible(); + status_t Defaults(); + bool DefaultsPossible(); + bool UseDefaultRevertButtons(); private: BCheckBox* fNotificationBox; - BCheckBox* fAutoStart; - BTextControl* fTimeout; - BCheckBox* fHideAll; + BSlider* fDurationSlider; + BSlider* fWidthSlider; + + int32 fOriginalTimeout; + float fOriginalWidth; + icon_size fOriginalIconSize; - bool _CanFindServer(entry_ref* ref); + void _EnableControls(); + void _SetWidthLabel(int32 value); + void _SetTimeoutLabel(int32 value); bool _IsServerRunning(); }; diff --git a/src/preferences/notifications/Jamfile b/src/preferences/notifications/Jamfile index fe980aea82..c44f1be4c7 100644 --- a/src/preferences/notifications/Jamfile +++ b/src/preferences/notifications/Jamfile @@ -1,18 +1,20 @@ SubDir HAIKU_TOP src preferences notifications ; -UsePrivateHeaders shared ; +UseHeaders [ FDirName $(HAIKU_TOP) src servers notification ] : true ; -UsePrivateHeaders interface ; +UsePrivateHeaders interface notification ; Application Notifications : + AppRefFilter.cpp Notifications.cpp PrefletWin.cpp PrefletView.cpp SettingsPane.cpp GeneralView.cpp - DisplayView.cpp NotificationsView.cpp - : be translation libcolumnlistview.a libnotification.a [ TargetLibstdc++ ] localestub + ../../servers/notification/NotificationView.cpp + ../../servers/notification/AppGroupView.cpp + : be translation tracker libcolumnlistview.a libnotification.a [ TargetLibstdc++ ] localestub : Notifications.rdef ; @@ -22,7 +24,6 @@ Depends Notifications : libnotification.a ; DoCatalogs Notifications : x-vnd.Haiku-Notifications : - DisplayView.cpp GeneralView.cpp PrefletWin.cpp PrefletView.cpp diff --git a/src/preferences/notifications/Notifications.cpp b/src/preferences/notifications/Notifications.cpp index 208e72a7df..555bb2d2e3 100644 --- a/src/preferences/notifications/Notifications.cpp +++ b/src/preferences/notifications/Notifications.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010, Haiku, Inc. All Rights Reserved. + * Copyright 2010-2017, Haiku, Inc. All Rights Reserved. * Copyright 2009, Pier Luigi Fiorini. * Distributed under the terms of the MIT License. * diff --git a/src/preferences/notifications/NotificationsConstants.h b/src/preferences/notifications/NotificationsConstants.h new file mode 100644 index 0000000000..a02fbcbf14 --- /dev/null +++ b/src/preferences/notifications/NotificationsConstants.h @@ -0,0 +1,25 @@ +/* + * Copyright 2017 Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef NOTIFICATIONS_CONSTANTS_H +#define NOTIFICATIONS_CONSTANTS_H + + +// interface messages +const uint32 kDefaults = '_DFT'; +const uint32 kRevert = '_RVT'; +const uint32 kApply = '_APY'; +const uint32 kApplyWithExample = '_APE'; +const uint32 kApplicationSelected = '_ASL'; +const uint32 kAddApplication = '_AAP'; +const uint32 kAddApplicationRef = '_AAR'; +const uint32 kRemoveApplication = '_RAP'; +const uint32 kMuteChanged = '_MCH'; + +// user interface +const float kEdgePadding = 5.0; +const float kCLVTitlePadding = 8.0; + + +#endif /* NOTIFICATIONS_CONSTANTS_H */ diff --git a/src/preferences/notifications/NotificationsView.cpp b/src/preferences/notifications/NotificationsView.cpp index b5fecbd024..a0183e5c5c 100644 --- a/src/preferences/notifications/NotificationsView.cpp +++ b/src/preferences/notifications/NotificationsView.cpp @@ -1,13 +1,15 @@ /* - * Copyright 2010, Haiku, Inc. All Rights Reserved. + * Copyright 2010-2017, Haiku, Inc. All Rights Reserved. * Copyright 2009, Pier Luigi Fiorini. * Distributed under the terms of the MIT License. * * Authors: * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com + * Brian Hill, supernova@tycho.email */ #include +#include #include #include #include @@ -23,90 +25,113 @@ #include #include +#include "NotificationsConstants.h" #include "NotificationsView.h" #undef B_TRANSLATION_CONTEXT #define B_TRANSLATION_CONTEXT "NotificationView" -const float kEdgePadding = 5.0; -const float kCLVTitlePadding = 8.0; - -const int32 kApplicationSelected = '_ASL'; -const int32 kNotificationSelected = '_NSL'; - -const int32 kCLVDeleteRow = 'av02'; - // Applications column indexes -const int32 kAppIndex = 0; +const int32 kAppNameIndex = 0; const int32 kAppEnabledIndex = 1; -// Notifications column indexes -const int32 kTitleIndex = 0; -const int32 kDateIndex = 1; -const int32 kTypeIndex = 2; -const int32 kAllowIndex = 3; + +AppRow::AppRow(const char* name, const char* signature, bool allowed) + : + BRow(), + fName(name), + fSignature(signature), + fAllowed(allowed) +{ + SetField(new BStringField(fName.String()), kAppNameIndex); + BString text = fAllowed ? B_TRANSLATE("Allowed") : B_TRANSLATE("Muted"); + SetField(new BStringField(text.String()), kAppEnabledIndex); +} + + +void +AppRow::SetAllowed(bool allowed) +{ + fAllowed = allowed; + RefreshEnabledField(); +} + + +void +AppRow::RefreshEnabledField() +{ + BStringField* field = (BStringField*)GetField(kAppEnabledIndex); + BString text = fAllowed ? B_TRANSLATE("Allowed") : B_TRANSLATE("Muted"); + field->SetString(text.String()); + Invalidate(); +} NotificationsView::NotificationsView(SettingsHost* host) : - SettingsPane("apps", host) + SettingsPane("apps", host), + fSelectedRow(NULL) { - BRect rect(0, 0, 100, 100); - - // Search application field - fSearch = new BTextControl(B_TRANSLATE("Search:"), NULL, - new BMessage(kSettingChanged)); - // Applications list fApplications = new BColumnListView(B_TRANSLATE("Applications"), - 0, B_FANCY_BORDER, true); + 0, B_FANCY_BORDER, false); fApplications->SetSelectionMode(B_SINGLE_SELECTION_LIST); + fApplications->SetSelectionMessage(new BMessage(kApplicationSelected)); - fAppCol = new BStringColumn(B_TRANSLATE("Application"), 200, - be_plain_font->StringWidth(B_TRANSLATE("Application")) + - (kCLVTitlePadding * 2), rect.Width(), B_TRUNCATE_END, B_ALIGN_LEFT); - fApplications->AddColumn(fAppCol, kAppIndex); + float colWidth = be_plain_font->StringWidth(B_TRANSLATE("Application")) + + (kCLVTitlePadding * 2); + fAppCol = new BStringColumn(B_TRANSLATE("Application"), colWidth * 2, + colWidth, colWidth * 4, B_TRUNCATE_END, B_ALIGN_LEFT); + fApplications->AddColumn(fAppCol, kAppNameIndex); - fAppEnabledCol = new BStringColumn(B_TRANSLATE("Enabled"), 10, - be_plain_font->StringWidth(B_TRANSLATE("Enabled")) + - (kCLVTitlePadding * 2), rect.Width(), B_TRUNCATE_END, B_ALIGN_LEFT); + colWidth = be_plain_font->StringWidth(B_TRANSLATE("Status")) + + (kCLVTitlePadding * 2); + fAppEnabledCol = new BStringColumn(B_TRANSLATE("Status"), colWidth * 1.5, + colWidth, colWidth * 3, B_TRUNCATE_END, B_ALIGN_LEFT); fApplications->AddColumn(fAppEnabledCol, kAppEnabledIndex); - - // Notifications list - fNotifications = new BColumnListView(B_TRANSLATE("Notifications"), - 0, B_FANCY_BORDER, true); - fNotifications->SetSelectionMode(B_SINGLE_SELECTION_LIST); - - fTitleCol = new BStringColumn(B_TRANSLATE("Title"), 100, - be_plain_font->StringWidth(B_TRANSLATE("Title")) + - (kCLVTitlePadding * 2), rect.Width(), B_TRUNCATE_END, B_ALIGN_LEFT); - fNotifications->AddColumn(fTitleCol, kTitleIndex); - - fDateCol = new BDateColumn(B_TRANSLATE("Last received"), 100, - be_plain_font->StringWidth(B_TRANSLATE("Last received")) + - (kCLVTitlePadding * 2), rect.Width(), B_ALIGN_LEFT); - fNotifications->AddColumn(fDateCol, kDateIndex); - - fTypeCol = new BStringColumn(B_TRANSLATE("Type"), 100, - be_plain_font->StringWidth(B_TRANSLATE("Type")) + - (kCLVTitlePadding * 2), rect.Width(), B_TRUNCATE_END, B_ALIGN_LEFT); - fNotifications->AddColumn(fTypeCol, kTypeIndex); - - fAllowCol = new BStringColumn(B_TRANSLATE("Allowed"), 100, - be_plain_font->StringWidth(B_TRANSLATE("Allowed")) + - (kCLVTitlePadding * 2), rect.Width(), B_TRUNCATE_END, B_ALIGN_LEFT); - fNotifications->AddColumn(fAllowCol, kAllowIndex); + fApplications->SetSortColumn(fAppCol, true, true); + + fAddButton = new BButton("add_app", B_TRANSLATE("Add" B_UTF8_ELLIPSIS), + new BMessage(kAddApplication)); + fRemoveButton = new BButton("add_app", B_TRANSLATE("Remove"), + new BMessage(kRemoveApplication)); + fRemoveButton->SetEnabled(false); + + fMuteAll = new BCheckBox("block", B_TRANSLATE("Mute notifications from " + "this application"), + new BMessage(kMuteChanged)); // Add views BLayoutBuilder::Group<>(this, B_VERTICAL) .AddGroup(B_HORIZONTAL) - .AddGlue() - .Add(fSearch) + .Add(fApplications) + .AddGroup(B_VERTICAL) + .Add(fAddButton) + .Add(fRemoveButton) + .AddGlue() + .End() .End() - .Add(fApplications) - .Add(fNotifications) + .Add(fMuteAll) .SetInsets(B_USE_WINDOW_SPACING, B_USE_WINDOW_SPACING, B_USE_WINDOW_SPACING, B_USE_DEFAULT_SPACING); + + // Set button sizes + float maxButtonWidth = std::max(fAddButton->PreferredSize().Width(), + fRemoveButton->PreferredSize().Width()); + fAddButton->SetExplicitMaxSize(BSize(maxButtonWidth, B_SIZE_UNSET)); + fRemoveButton->SetExplicitMaxSize(BSize(maxButtonWidth, B_SIZE_UNSET)); + + // File Panel + fPanelFilter = new AppRefFilter(); + fAddAppPanel = new BFilePanel(B_OPEN_PANEL, NULL, NULL, B_FILE_NODE, false, + NULL, fPanelFilter); +} + + +NotificationsView::~NotificationsView() +{ + delete fAddAppPanel; + delete fPanelFilter; } @@ -115,14 +140,11 @@ NotificationsView::AttachedToWindow() { fApplications->SetTarget(this); fApplications->SetInvocationMessage(new BMessage(kApplicationSelected)); - - fNotifications->SetTarget(this); - fNotifications->SetInvocationMessage(new BMessage(kNotificationSelected)); - -#if 0 - fNotifications->AddFilter(new BMessageFilter(B_ANY_DELIVERY, - B_ANY_SOURCE, B_KEY_DOWN, CatchDelete)); -#endif + fAddButton->SetTarget(this); + fRemoveButton->SetTarget(this); + fMuteAll->SetTarget(this); + fAddAppPanel->SetTarget(this); + _RecallItemSettings(); } @@ -132,22 +154,97 @@ NotificationsView::MessageReceived(BMessage* msg) switch (msg->what) { case kApplicationSelected: { - BRow* row = fApplications->CurrentSelection(); - if (row == NULL) - return; - BStringField* appName - = dynamic_cast(row->GetField(kAppIndex)); - if (appName == NULL) - break; - - appusage_t::iterator it = fAppFilters.find(appName->String()); - if (it != fAppFilters.end()) - _Populate(it->second); - + Window()->Lock(); + _ClearItemSettings(); + _UpdateSelectedItem(); + _RecallItemSettings(); + Window()->Unlock(); break; } - case kNotificationSelected: + case kMuteChanged: + { + bool allowed = fMuteAll->Value() == B_CONTROL_OFF; + fSelectedRow->SetAllowed(allowed); + appusage_t::iterator it = fAppFilters.find(fSelectedRow->Signature()); + if (it != fAppFilters.end()) + it->second->SetAllowed(allowed); + Window()->PostMessage(kApply); break; + } + case kAddApplication: + { + BMessage addmsg(kAddApplicationRef); + fAddAppPanel->SetMessage(&addmsg); + fAddAppPanel->Show(); + break; + } + case kAddApplicationRef: + { + entry_ref srcRef; + msg->FindRef("refs", &srcRef); + BEntry srcEntry(&srcRef, true); + BPath path(&srcEntry); + BNode node(&srcEntry); + char *buf = new char[B_ATTR_NAME_LENGTH]; + ssize_t size; + if ( (size = node.ReadAttr("BEOS:APP_SIG", 0, 0, buf, + B_ATTR_NAME_LENGTH)) > 0 ) + { + // Search for already existing app + appusage_t::iterator it = fAppFilters.find(buf); + if (it != fAppFilters.end()) { + BString text(path.Leaf()); + text.Append(B_TRANSLATE_COMMENT(" is already listed", + "Alert message")); + BAlert* alert = new BAlert("", text.String(), + B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_AS_USUAL, + B_WARNING_ALERT); + alert->Go(NULL); + } else { + AppUsage* appUsage = new AppUsage(path.Leaf(), buf, true); + fAppFilters[appUsage->Signature()] = appUsage; + AppRow* row = new AppRow(appUsage->AppName(), + appUsage->Signature(), appUsage->Allowed()); + fApplications->AddRow(row); + fApplications->DeselectAll(); + fApplications->AddToSelection(row); + fApplications->ScrollTo(row); + _UpdateSelectedItem(); + _RecallItemSettings(); + //row->Invalidate(); + //fApplications->InvalidateRow(row); + // TODO redraw row properly + Window()->PostMessage(kApply); + } + } else { + BAlert* alert = new BAlert("", + B_TRANSLATE_COMMENT("Application does not have " + "a valid signature", "Alert message"), + B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_AS_USUAL, + B_WARNING_ALERT); + alert->Go(NULL); + } + delete[] buf; + break; + } + case kRemoveApplication: + { + if (fSelectedRow) { + appusage_t::iterator it = fAppFilters.find(fSelectedRow->Signature()); + if (it != fAppFilters.end()) { + delete it->second; + fAppFilters.erase(it); + } + fApplications->RemoveRow(fSelectedRow); + delete fSelectedRow; + fSelectedRow = NULL; + _ClearItemSettings(); + _UpdateSelectedItem(); + _RecallItemSettings(); + Window()->PostMessage(kApply); + } + break; + } default: BView::MessageReceived(msg); break; @@ -174,7 +271,7 @@ NotificationsView::Load(BMessage& settings) for (int32 i = 0; i < count; i++) { AppUsage* app = new AppUsage(); settings.FindFlat("app_usage", i, app); - fAppFilters[app->Name()] = app; + fAppFilters[app->Signature()] = app; } // Load the applications list @@ -196,64 +293,84 @@ NotificationsView::Save(BMessage& storage) void -NotificationsView::_PopulateApplications() +NotificationsView::_ClearItemSettings() { - appusage_t::iterator it; - - fApplications->Clear(); - - for (it = fAppFilters.begin(); it != fAppFilters.end(); ++it) { - BRow* row = new BRow(); - row->SetField(new BStringField(it->first.String()), kAppIndex); - fApplications->AddRow(row); - } + fMuteAll->SetValue(B_CONTROL_OFF); } void -NotificationsView::_Populate(AppUsage* usage) +NotificationsView::_UpdateSelectedItem() { - // Sanity check - if (!usage) - return; + fSelectedRow = dynamic_cast(fApplications->CurrentSelection()); + +} - int32 size = usage->Notifications(); - if (usage->Allowed() == false) - fBlockAll->SetValue(B_CONTROL_ON); - - fNotifications->Clear(); - - for (int32 i = 0; i < size; i++) { - NotificationReceived* notification = usage->NotificationAt(i); - time_t updated = notification->LastReceived(); - const char* allow = notification->Allowed() ? B_TRANSLATE("Yes") - : B_TRANSLATE("No"); - const char* type = ""; - - switch (notification->Type()) { - case B_INFORMATION_NOTIFICATION: - type = B_TRANSLATE("Information"); - break; - case B_IMPORTANT_NOTIFICATION: - type = B_TRANSLATE("Important"); - break; - case B_ERROR_NOTIFICATION: - type = B_TRANSLATE("Error"); - break; - case B_PROGRESS_NOTIFICATION: - type = B_TRANSLATE("Progress"); - break; - default: - type = B_TRANSLATE("Unknown"); - } - - BRow* row = new BRow(); - row->SetField(new BStringField(notification->Title()), kTitleIndex); - row->SetField(new BDateField(&updated), kDateIndex); - row->SetField(new BStringField(type), kTypeIndex); - row->SetField(new BStringField(allow), kAllowIndex); - - fNotifications->AddRow(row); +void +NotificationsView::_RecallItemSettings() +{ + // No selected item + if(fSelectedRow == NULL) + { + fMuteAll->SetValue(B_CONTROL_OFF); + fMuteAll->SetEnabled(false); + fRemoveButton->SetEnabled(false); + } else { + fMuteAll->SetEnabled(true); + fRemoveButton->SetEnabled(true); + appusage_t::iterator it = fAppFilters.find(fSelectedRow->Signature()); + if (it != fAppFilters.end()) + fMuteAll->SetValue(!(it->second->Allowed())); + } +} + + +status_t +NotificationsView::Revert() +{ + return B_OK; +} + + +bool +NotificationsView::RevertPossible() +{ + return false; +} + + +status_t +NotificationsView::Defaults() +{ + return B_OK; +} + + +bool +NotificationsView::DefaultsPossible() +{ + return false; +} + + +bool +NotificationsView::UseDefaultRevertButtons() +{ + return false; +} + + +void +NotificationsView::_PopulateApplications() +{ + fApplications->Clear(); + + appusage_t::iterator it; + for (it = fAppFilters.begin(); it != fAppFilters.end(); ++it) { + AppUsage* appUsage = it->second; + AppRow* row = new AppRow(appUsage->AppName(), + appUsage->Signature(), appUsage->Allowed()); + fApplications->AddRow(row); } } diff --git a/src/preferences/notifications/NotificationsView.h b/src/preferences/notifications/NotificationsView.h index b44c7376cf..1eec7b12c5 100644 --- a/src/preferences/notifications/NotificationsView.h +++ b/src/preferences/notifications/NotificationsView.h @@ -1,50 +1,78 @@ /* - * Copyright 2010, Haiku, Inc. All Rights Reserved. + * Copyright 2010-2017, Haiku, Inc. All Rights Reserved. * Copyright 2009, Pier Luigi Fiorini. * Distributed under the terms of the MIT License. */ #ifndef _APPS_VIEW_H #define _APPS_VIEW_H +#include +#include #include #include +#include "AppRefFilter.h" #include "SettingsPane.h" typedef std::map appusage_t; +class BButton; class BCheckBox; class BTextControl; -class BColumnListView; class BStringColumn; class BDateColumn; + +class AppRow : public BRow { +public: + AppRow(const char* name, + const char* signature, bool allowed); + + const char* Name() const { return fName.String(); } + const char* Signature() { return fSignature.String(); }; + void SetAllowed(bool allowed); + bool Allowed() { return fAllowed; }; + void RefreshEnabledField(); + +private: + BString fName; + BString fSignature; + bool fAllowed; +}; + + class NotificationsView : public SettingsPane { public: NotificationsView(SettingsHost* host); + ~NotificationsView(); virtual void AttachedToWindow(); virtual void MessageReceived(BMessage* msg); + status_t Revert(); + bool RevertPossible(); + status_t Defaults(); + bool DefaultsPossible(); + bool UseDefaultRevertButtons(); private: status_t Load(BMessage&); status_t Save(BMessage&); - status_t Revert() {return B_OK;} // FIXME implement this + void _ClearItemSettings(); + void _UpdateSelectedItem(); + void _RecallItemSettings(); void _PopulateApplications(); - void _Populate(AppUsage* usage); appusage_t fAppFilters; - BCheckBox* fBlockAll; - BTextControl* fSearch; + AppRefFilter* fPanelFilter; + BFilePanel* fAddAppPanel; + BButton* fAddButton; + BButton* fRemoveButton; + BCheckBox* fMuteAll; BColumnListView* fApplications; + AppRow* fSelectedRow; BStringColumn* fAppCol; BStringColumn* fAppEnabledCol; - BColumnListView* fNotifications; - BStringColumn* fTitleCol; - BDateColumn* fDateCol; - BStringColumn* fTypeCol; - BStringColumn* fAllowCol; }; #endif // _APPS_VIEW_H diff --git a/src/preferences/notifications/PrefletView.cpp b/src/preferences/notifications/PrefletView.cpp index 152712180d..e69505f3be 100644 --- a/src/preferences/notifications/PrefletView.cpp +++ b/src/preferences/notifications/PrefletView.cpp @@ -1,10 +1,11 @@ /* - * Copyright 2010, Haiku, Inc. All Rights Reserved. + * Copyright 2010-2017, Haiku, Inc. All Rights Reserved. * Copyright 2009, Pier Luigi Fiorini. * Distributed under the terms of the MIT License. * * Authors: * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com + * Brian Hill, supernova@tycho.email */ #include @@ -13,9 +14,8 @@ #include #include #include +#include -#include "DisplayView.h" -#include "GeneralView.h" #include "NotificationsView.h" #include "PrefletView.h" #include "SettingsHost.h" @@ -25,30 +25,22 @@ #define B_TRANSLATION_CONTEXT "PrefletView" -const int32 kPageSelected = '_LCH'; - - PrefletView::PrefletView(SettingsHost* host) : BTabView("pages", B_WIDTH_FROM_WIDEST) { // Pages - GeneralView* general = new GeneralView(host); - DisplayView* display = new DisplayView(host); + fGeneralView = new GeneralView(host); NotificationsView* apps = new NotificationsView(host); // Page selector BTab* tab = new BTab(); - AddTab(general, tab); + AddTab(fGeneralView, tab); tab->SetLabel(B_TRANSLATE("General")); - tab = new BTab(); - AddTab(display, tab); - tab->SetLabel(B_TRANSLATE("Display")); - tab = new BTab(); AddTab(apps, tab); - tab->SetLabel(B_TRANSLATE("Notifications")); + tab->SetLabel(B_TRANSLATE("Applications")); } @@ -59,15 +51,24 @@ PrefletView::CurrentPage() } -int32 -PrefletView::CountPages() const -{ - return 3; -} - - BView* PrefletView::PageAt(int32 index) { return TabAt(index)->View(); } + + +void +PrefletView::Select(int32 index) +{ + if (index == Selection()) + return; + + BTabView::Select(index); + + SettingsPane* pane = dynamic_cast(PageAt(index)); + bool showButtons = (pane != NULL) && pane->UseDefaultRevertButtons(); + BMessage showMessage(kShowButtons); + showMessage.AddBool(kShowButtonsKey, showButtons); + Window()->PostMessage(&showMessage); +} diff --git a/src/preferences/notifications/PrefletView.h b/src/preferences/notifications/PrefletView.h index 404b261e90..c05605d054 100644 --- a/src/preferences/notifications/PrefletView.h +++ b/src/preferences/notifications/PrefletView.h @@ -1,24 +1,32 @@ /* - * Copyright 2010, Haiku, Inc. All Rights Reserved. + * Copyright 2010-2017, Haiku, Inc. All Rights Reserved. * Copyright 2009, Pier Luigi Fiorini. * Distributed under the terms of the MIT License. */ #ifndef _PREFLET_VIEW_H #define _PREFLET_VIEW_H +#include #include -class BIconRule; +#include "GeneralView.h" class SettingsHost; +const int32 kShowButtons = '_SHB'; +#define kShowButtonsKey "showButtons" + class PrefletView : public BTabView { public: PrefletView(SettingsHost* host); BView* CurrentPage(); - int32 CountPages() const; BView* PageAt(int32 index); + virtual void Select(int32 index); + +private: + GeneralView* fGeneralView; + BMessenger fMessenger; }; #endif // PREFLETVIEW_H diff --git a/src/preferences/notifications/PrefletWin.cpp b/src/preferences/notifications/PrefletWin.cpp index b269bb89ab..7f75b79b9d 100644 --- a/src/preferences/notifications/PrefletWin.cpp +++ b/src/preferences/notifications/PrefletWin.cpp @@ -1,10 +1,11 @@ /* - * Copyright 2010-2014, Haiku, Inc. All Rights Reserved. + * Copyright 2010-2017, Haiku, Inc. All Rights Reserved. * Copyright 2009, Pier Luigi Fiorini. * Distributed under the terms of the MIT License. * * Authors: * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com + * Brian Hill, supernova@tycho.email */ #include "PrefletWin.h" @@ -14,52 +15,62 @@ #include #include #include -#include +#include #include #include #include +#include "NotificationsConstants.h" #include "PrefletView.h" #undef B_TRANSLATION_CONTEXT #define B_TRANSLATION_CONTEXT "PrefletWin" - -const int32 kRevert = '_RVT'; -const int32 kApply = '_APY'; +const BString kSampleMessageID("NotificationsSample"); PrefletWin::PrefletWin() : - BWindow(BRect(0, 0, 500, 400), B_TRANSLATE_SYSTEM_NAME("Notifications"), + BWindow(BRect(0, 0, 160 + 20 * be_plain_font->Size(), 300), + B_TRANSLATE_SYSTEM_NAME("Notifications"), B_TITLED_WINDOW, B_NOT_ZOOMABLE | B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS) { // Preflet container view fMainView = new PrefletView(this); fMainView->SetBorder(B_NO_BORDER); - fMainView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); + fMainView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED)); - // Apply and revert buttons + // Defaults button + fDefaults = new BButton("defaults", B_TRANSLATE("Defaults"), + new BMessage(kDefaults)); + fDefaults->SetEnabled(false); + + // Revert button fRevert = new BButton("revert", B_TRANSLATE("Revert"), new BMessage(kRevert)); fRevert->SetEnabled(false); - fApply = new BButton("apply", B_TRANSLATE("Apply"), new BMessage(kApply)); - fApply->SetEnabled(false); // Build the layout + fButtonsView = new BGroupView(); + BLayoutBuilder::Group<>(fButtonsView, B_VERTICAL, 0) + .AddGroup(B_HORIZONTAL) + .Add(fDefaults) + .Add(fRevert) + .AddGlue() + .SetInsets(B_USE_WINDOW_SPACING, 0, B_USE_WINDOW_SPACING, + B_USE_WINDOW_SPACING) + .End(); + fButtonsLayout = fButtonsView->GroupLayout(); + BLayoutBuilder::Group<>(this, B_VERTICAL, 0) .SetInsets(0, B_USE_DEFAULT_SPACING, 0, 0) .Add(fMainView) - .Add(new BSeparatorView(B_HORIZONTAL)) - .AddGroup(B_HORIZONTAL) - .Add(fRevert) - .AddGlue() - .Add(fApply) - .SetInsets(B_USE_WINDOW_SPACING, B_USE_DEFAULT_SPACING, - B_USE_WINDOW_SPACING, B_USE_WINDOW_SPACING); + .Add(fButtonsView) + .End(); + fMainView->SetExplicitMinSize(BSize(Frame().Width(), B_SIZE_UNSET)); ReloadSettings(); @@ -74,6 +85,7 @@ PrefletWin::MessageReceived(BMessage* msg) { switch (msg->what) { case kApply: + case kApplyWithExample: { BPath path; @@ -85,13 +97,14 @@ PrefletWin::MessageReceived(BMessage* msg) path.Append(kSettingsFile); BMessage settingsStore; - for (int32 i = 0; i < fMainView->CountPages(); i++) { + int32 count = fMainView->CountTabs(); + for (int32 i = 0; i < count; i++) { SettingsPane* pane = dynamic_cast(fMainView->PageAt(i)); if (pane) { if (pane->Save(settingsStore) == B_OK) { - fApply->SetEnabled(false); - fRevert->SetEnabled(true); + fDefaults->SetEnabled(_DefaultsPossible()); + fRevert->SetEnabled(_RevertPossible()); } else break; } @@ -109,19 +122,28 @@ PrefletWin::MessageReceived(BMessage* msg) alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); (void)alert->Go(); } + file.Unset(); + + if (msg->what == kApplyWithExample) + _SendExampleNotification(); break; } - case kRevert: - for (int32 i = 0; i < fMainView->CountPages(); i++) { - SettingsPane* pane = - dynamic_cast(fMainView->PageAt(i)); - if (pane) { - if (pane->Revert() == B_OK) - fRevert->SetEnabled(false); - } - } + case kDefaults: + fDefaults->SetEnabled(false); + _Defaults(); + PostMessage(kApply); break; + case kRevert: + fRevert->SetEnabled(false); + _Revert(); + PostMessage(kApply); + break; + case kShowButtons: { + bool show = msg->GetBool(kShowButtonsKey, true); + fButtonsLayout->SetVisible(show); + break; + } default: BWindow::MessageReceived(msg); } @@ -137,9 +159,12 @@ PrefletWin::QuitRequested() void -PrefletWin::SettingChanged() +PrefletWin::SettingChanged(bool showExample) { - fApply->SetEnabled(true); + if (showExample) + PostMessage(kApplyWithExample); + else + PostMessage(kApply); } @@ -158,10 +183,80 @@ PrefletWin::ReloadSettings() BFile file(path.Path(), B_READ_ONLY); settings.Unflatten(&file); - for (int32 i = 0; i < fMainView->CountPages(); i++) { + int32 count = fMainView->CountTabs(); + for (int32 i = 0; i < count; i++) { SettingsPane* pane = dynamic_cast(fMainView->PageAt(i)); if (pane) pane->Load(settings); } + fDefaults->SetEnabled(_DefaultsPossible()); +} + + +status_t +PrefletWin::_Revert() +{ + int32 count = fMainView->CountTabs(); + for (int32 i = 0; i < count; i++) { + SettingsPane* pane = + dynamic_cast(fMainView->PageAt(i)); + if (pane) + pane->Revert(); + } + return B_OK; +} + + +bool +PrefletWin::_RevertPossible() +{ + int32 count = fMainView->CountTabs(); + for (int32 i = 0; i < count; i++) { + SettingsPane* pane = + dynamic_cast(fMainView->PageAt(i)); + if (pane && pane->RevertPossible()) + return true; + } + return false; +} + + +status_t +PrefletWin::_Defaults() +{ + int32 count = fMainView->CountTabs(); + for (int32 i = 0; i < count; i++) { + SettingsPane* pane = + dynamic_cast(fMainView->PageAt(i)); + if (pane) + pane->Defaults(); + } + return B_OK; +} + + +bool +PrefletWin::_DefaultsPossible() +{ + int32 count = fMainView->CountTabs(); + for (int32 i = 0; i < count; i++) { + SettingsPane* pane = + dynamic_cast(fMainView->PageAt(i)); + if (pane && pane->DefaultsPossible()) + return true; + } + return false; +} + + +void +PrefletWin::_SendExampleNotification() +{ + BNotification notification(B_INFORMATION_NOTIFICATION); + notification.SetMessageID(kSampleMessageID); + notification.SetGroup(B_TRANSLATE("Notifications")); + notification.SetTitle(B_TRANSLATE("Notifications preflet sample")); + notification.SetContent(B_TRANSLATE("This is a test notification message")); + notification.Send(); } diff --git a/src/preferences/notifications/PrefletWin.h b/src/preferences/notifications/PrefletWin.h index 561c1fb4c8..95175cab34 100644 --- a/src/preferences/notifications/PrefletWin.h +++ b/src/preferences/notifications/PrefletWin.h @@ -1,11 +1,15 @@ /* - * Copyright 2010, Haiku, Inc. All Rights Reserved. + * Copyright 2010-2017, Haiku, Inc. All Rights Reserved. * Copyright 2009, Pier Luigi Fiorini. * Distributed under the terms of the MIT License. */ #ifndef _PREFLET_WIN_H #define _PREFLET_WIN_H + +#include +#include +#include #include #include "SettingsHost.h" @@ -21,13 +25,21 @@ public: virtual bool QuitRequested(); virtual void MessageReceived(BMessage* msg); - virtual void SettingChanged(); + virtual void SettingChanged(bool showExample); void ReloadSettings(); private: + status_t _Revert(); + bool _RevertPossible(); + status_t _Defaults(); + bool _DefaultsPossible(); + void _SendExampleNotification(); + PrefletView* fMainView; - BButton* fApply; + BGroupView* fButtonsView; + BButton* fDefaults; BButton* fRevert; + BGroupLayout* fButtonsLayout; }; #endif // _PREFLET_WIN_H diff --git a/src/preferences/notifications/SettingsHost.h b/src/preferences/notifications/SettingsHost.h index 3774d7dd04..ca09a8ddca 100644 --- a/src/preferences/notifications/SettingsHost.h +++ b/src/preferences/notifications/SettingsHost.h @@ -1,5 +1,5 @@ /* - * Copyright 2010, Haiku, Inc. All Rights Reserved. + * Copyright 2010-2017, Haiku, Inc. All Rights Reserved. * Copyright 2009, Pier Luigi Fiorini. * Distributed under the terms of the MIT License. */ @@ -14,7 +14,7 @@ class SettingsHost { public: SettingsHost() {} - virtual void SettingChanged() = 0; + virtual void SettingChanged(bool showExample = false) = 0; }; #endif // _SETTINGS_HOST_H diff --git a/src/preferences/notifications/SettingsPane.cpp b/src/preferences/notifications/SettingsPane.cpp index 128e7a5521..457200ebbf 100644 --- a/src/preferences/notifications/SettingsPane.cpp +++ b/src/preferences/notifications/SettingsPane.cpp @@ -1,10 +1,11 @@ /* - * Copyright 2010, Haiku, Inc. All Rights Reserved. + * Copyright 2010-2017, Haiku, Inc. All Rights Reserved. * Copyright 2009, Pier Luigi Fiorini. * Distributed under the terms of the MIT License. * * Authors: * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com + * Brian Hill, supernova@tycho.email */ #include @@ -22,13 +23,7 @@ SettingsPane::SettingsPane(const char* name, SettingsHost* host) void -SettingsPane::MessageReceived(BMessage* msg) +SettingsPane::SettingsChanged(bool showExample) { - switch (msg->what) { - case kSettingChanged: - fHost->SettingChanged(); - break; - default: - BView::MessageReceived(msg); - } + fHost->SettingChanged(showExample); } diff --git a/src/preferences/notifications/SettingsPane.h b/src/preferences/notifications/SettingsPane.h index a14fd62a77..b8cd77e87c 100644 --- a/src/preferences/notifications/SettingsPane.h +++ b/src/preferences/notifications/SettingsPane.h @@ -1,5 +1,5 @@ /* - * Copyright 2010, Haiku, Inc. All Rights Reserved. + * Copyright 2010-2017, Haiku, Inc. All Rights Reserved. * Copyright 2009, Pier Luigi Fiorini. * Distributed under the terms of the MIT License. */ @@ -12,17 +12,20 @@ class BNode; class SettingsHost; -const int32 kSettingChanged = '_STC'; class SettingsPane : public BView { public: SettingsPane(const char* name, SettingsHost* host); - virtual void MessageReceived(BMessage* msg); + void SettingsChanged(bool showExample); virtual status_t Load(BMessage&) = 0; virtual status_t Save(BMessage&) = 0; virtual status_t Revert() = 0; + virtual bool RevertPossible() = 0; + virtual status_t Defaults() = 0; + virtual bool DefaultsPossible() = 0; + virtual bool UseDefaultRevertButtons() = 0; protected: SettingsHost* fHost; diff --git a/src/servers/notification/AppGroupView.cpp b/src/servers/notification/AppGroupView.cpp index 38fec7057f..f0d87c321c 100644 --- a/src/servers/notification/AppGroupView.cpp +++ b/src/servers/notification/AppGroupView.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010, Haiku, Inc. All Rights Reserved. + * Copyright 2010-2017, Haiku, Inc. All Rights Reserved. * Copyright 2008-2009, Pier Luigi Fiorini. All Rights Reserved. * Copyright 2004-2008, Michael Davidson. All Rights Reserved. * Copyright 2004-2007, Mikael Eiman. All Rights Reserved. @@ -9,6 +9,7 @@ * Michael Davidson, slaad@bong.com.au * Mikael Eiman, mikael@eiman.tv * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com + * Brian Hill, supernova@tycho.email */ #include @@ -22,21 +23,24 @@ #include "NotificationWindow.h" #include "NotificationView.h" - -static const int kHeaderSize = 23; +const float kCloseSize = 6; +const float kEdgePadding = 2; -AppGroupView::AppGroupView(NotificationWindow* win, const char* label) +AppGroupView::AppGroupView(const BMessenger& messenger, const char* label) : BGroupView("appGroup", B_VERTICAL, 0), fLabel(label), - fParent(win), + fMessenger(messenger), fCollapsed(false), - fCloseClicked(false) + fCloseClicked(false), + fPreviewModeOn(false) { SetFlags(Flags() | B_WILL_DRAW); - static_cast(GetLayout())->SetInsets(0, kHeaderSize, 0, 0); + fHeaderSize = be_plain_font->Size() + + be_control_look->ComposeSpacing(B_USE_ITEM_SPACING); + static_cast(GetLayout())->SetInsets(0, fHeaderSize, 0, 0); } @@ -47,7 +51,7 @@ AppGroupView::Draw(BRect updateRect) BRect bounds = Bounds(); rgb_color hilite = tint_color(menuColor, B_DARKEN_1_TINT); rgb_color vlight = tint_color(menuColor, B_LIGHTEN_2_TINT); - bounds.bottom = bounds.top + kHeaderSize; + bounds.bottom = bounds.top + fHeaderSize; // Draw the header background SetHighColor(tint_color(menuColor, 1.22)); @@ -55,18 +59,17 @@ AppGroupView::Draw(BRect updateRect) StrokeLine(bounds.LeftTop(), bounds.LeftBottom()); uint32 borders = BControlLook::B_TOP_BORDER | BControlLook::B_BOTTOM_BORDER | BControlLook::B_RIGHT_BORDER; - be_control_look->DrawButtonBackground(this, bounds, bounds, menuColor, 0, borders); // Draw the buttons - fCollapseRect.top = (kHeaderSize - kExpandSize) / 2; + fCollapseRect.top = (fHeaderSize - kExpandSize) / 2; fCollapseRect.left = kEdgePadding * 3; fCollapseRect.right = fCollapseRect.left + 1.5 * kExpandSize; fCollapseRect.bottom = fCollapseRect.top + kExpandSize; fCloseRect = bounds; - fCloseRect.top = (kHeaderSize - kCloseSize) / 2; + fCloseRect.top = (fHeaderSize - kCloseSize) / 2; // Take off the 1 to line this up with the close button on the // notification view fCloseRect.right -= kEdgePadding * 3 - 1; @@ -89,7 +92,9 @@ AppGroupView::Draw(BRect updateRect) if (fCollapsed) label << " (" << fInfo.size() << ")"; - SetFont(be_bold_font); + BFont boldFont(be_plain_font); + boldFont.SetFace(B_BOLD_FACE); + SetFont(&boldFont); font_height fontHeight; GetFontHeight(&fontHeight); float y = (bounds.top + bounds.bottom - ceilf(fontHeight.ascent) @@ -132,6 +137,10 @@ AppGroupView::_DrawCloseButton(const BRect& updateRect) void AppGroupView::MouseDown(BPoint point) { + // Preview Mode ignores any mouse clicks + if (fPreviewModeOn) + return; + if (BRect(fCloseRect).InsetBySelf(-5, -5).Contains(point)) { int32 children = fInfo.size(); for (int32 i = 0; i < children; i++) { @@ -144,7 +153,7 @@ AppGroupView::MouseDown(BPoint point) // Remove ourselves from the parent view BMessage message(kRemoveGroupView); message.AddPointer("view", this); - fParent->PostMessage(&message); + fMessenger.SendMessage(&message); } else if (BRect(fCollapseRect).InsetBySelf(-5, -5).Contains(point)) { fCollapsed = !fCollapsed; int32 children = fInfo.size(); @@ -186,13 +195,13 @@ AppGroupView::MessageReceived(BMessage* msg) view->RemoveSelf(); delete view; - fParent->PostMessage(msg); + fMessenger.SendMessage(msg); if (!this->HasChildren()) { Hide(); BMessage removeSelfMessage(kRemoveGroupView); removeSelfMessage.AddPointer("view", this); - fParent->PostMessage(&removeSelfMessage); + fMessenger.SendMessage(&removeSelfMessage); } break; @@ -211,17 +220,13 @@ AppGroupView::AddInfo(NotificationView* view) if (id.Length() > 0) { int32 children = fInfo.size(); - for (int32 i = 0; i < children; i++) { if (id == fInfo[i]->MessageID()) { NotificationView* oldView = fInfo[i]; - fParent->NotificationViewSwapped(oldView, view); oldView->RemoveSelf(); delete oldView; - fInfo[i] = view; found = true; - break; } } @@ -246,6 +251,13 @@ AppGroupView::AddInfo(NotificationView* view) } +void +AppGroupView::SetPreviewModeOn(bool enabled) +{ + fPreviewModeOn = enabled; +} + + const BString& AppGroupView::Group() const { @@ -253,6 +265,14 @@ AppGroupView::Group() const } +void +AppGroupView::SetGroup(const char* group) +{ + fLabel.SetTo(group); + Invalidate(); +} + + bool AppGroupView::HasChildren() { diff --git a/src/servers/notification/AppGroupView.h b/src/servers/notification/AppGroupView.h index c3cbeac18e..ea10fceffd 100644 --- a/src/servers/notification/AppGroupView.h +++ b/src/servers/notification/AppGroupView.h @@ -1,5 +1,5 @@ /* - * Copyright 2010, Haiku, Inc. All Rights Reserved. + * Copyright 2010-2017, Haiku, Inc. All Rights Reserved. * Copyright 2008-2009, Pier Luigi Fiorini. All Rights Reserved. * Copyright 2004-2008, Michael Davidson. All Rights Reserved. * Copyright 2004-2007, Mikael Eiman. All Rights Reserved. @@ -11,6 +11,7 @@ #include #include +#include #include class BGroupView; @@ -22,7 +23,7 @@ typedef std::vector infoview_t; class AppGroupView : public BGroupView { public: - AppGroupView(NotificationWindow* win, const char* label); + AppGroupView(const BMessenger& messenger, const char* label); virtual void MouseDown(BPoint point); virtual void MessageReceived(BMessage* msg); @@ -32,19 +33,23 @@ public: int32 ChildrenCount(); void AddInfo(NotificationView* view); + void SetPreviewModeOn(bool enabled); const BString& Group() const; + void SetGroup(const char* group); private: void _DrawCloseButton(const BRect& updateRect); BString fLabel; - NotificationWindow* fParent; + BMessenger fMessenger; infoview_t fInfo; bool fCollapsed; BRect fCloseRect; BRect fCollapseRect; + float fHeaderSize; bool fCloseClicked; + bool fPreviewModeOn; }; #endif // _APP_GROUP_VIEW_H diff --git a/src/servers/notification/AppUsage.cpp b/src/servers/notification/AppUsage.cpp index 2e1cb72521..6599c87c49 100644 --- a/src/servers/notification/AppUsage.cpp +++ b/src/servers/notification/AppUsage.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010, Haiku, Inc. All Rights Reserved. + * Copyright 2010-2017, Haiku, Inc. All Rights Reserved. * Copyright 2008-2009, Pier Luigi Fiorini. All Rights Reserved. * Copyright 2004-2008, Michael Davidson. All Rights Reserved. * Copyright 2004-2007, Mikael Eiman. All Rights Reserved. @@ -9,6 +9,7 @@ * Michael Davidson, slaad@bong.com.au * Mikael Eiman, mikael@eiman.tv * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com + * Brian Hill, supernova@tycho.email */ #include @@ -21,28 +22,22 @@ const type_code kTypeCode = 'ipau'; AppUsage::AppUsage() : - fName(""), + fAppName(""), + fSignature(""), fAllow(true) { } -AppUsage::AppUsage(const char* name, bool allow) +AppUsage::AppUsage(const char* name, const char* signature, bool allow) : - fName(name), + fAppName(name), + fSignature(signature), fAllow(allow) { } -AppUsage::~AppUsage() -{ - notification_t::iterator nIt; - for (nIt = fNotifications.begin(); nIt != fNotifications.end(); nIt++) - delete nIt->second; -} - - bool AppUsage::AllowsTypeCode(type_code code) const { @@ -54,13 +49,10 @@ status_t AppUsage::Flatten(void* buffer, ssize_t numBytes) const { BMessage msg; - msg.AddString("signature", fName); + msg.AddString("name", fAppName); + msg.AddString("signature", fSignature); msg.AddBool("allow", fAllow); - notification_t::const_iterator nIt; - for (nIt = fNotifications.begin(); nIt != fNotifications.end(); nIt++) - msg.AddFlat("notification", nIt->second); - if (numBytes < msg.FlattenedSize()) return B_ERROR; @@ -72,13 +64,10 @@ ssize_t AppUsage::FlattenedSize() const { BMessage msg; - msg.AddString("signature", fName); + msg.AddString("name", fAppName); + msg.AddString("signature", fSignature); msg.AddBool("allow", fAllow); - notification_t::const_iterator nIt; - for (nIt = fNotifications.begin(); nIt != fNotifications.end(); nIt++) - msg.AddFlat("notification", nIt->second); - return msg.FlattenedSize(); } @@ -110,23 +99,9 @@ AppUsage::Unflatten(type_code code, const void* buffer, status = msg.Unflatten((const char*)buffer); if (status == B_OK) { - msg.FindString("signature", &fName); + msg.FindString("name", &fAppName); + msg.FindString("signature", &fSignature); msg.FindBool("allow", &fAllow); - - type_code type; - int32 count = 0; - - status = msg.GetInfo("notification", &type, &count); - if (status != B_OK) - return status; - - for (int32 i = 0; i < count; i++) { - NotificationReceived *notification = new NotificationReceived(); - msg.FindFlat("notification", i, notification); - fNotifications[notification->Title()] = notification; - } - - status = B_OK; } return status; @@ -134,30 +109,16 @@ AppUsage::Unflatten(type_code code, const void* buffer, const char* -AppUsage::Name() +AppUsage::AppName() { - return fName.String(); + return fAppName.String(); } -bool -AppUsage::Allowed(const char* title, notification_type type) +const char* +AppUsage::Signature() { - bool allowed = fAllow; - - if (allowed) { - notification_t::iterator nIt = fNotifications.find(title); - if (nIt == fNotifications.end()) { - allowed = true; - fNotifications[title] = new NotificationReceived(title, type); - } else { - allowed = nIt->second->Allowed(); - nIt->second->UpdateTimeStamp(); - nIt->second->SetType(type); - } - } - - return allowed; + return fSignature.String(); } @@ -168,26 +129,8 @@ AppUsage::Allowed() } -NotificationReceived* -AppUsage::NotificationAt(int32 index) -{ - notification_t::iterator nIt = fNotifications.begin(); - for (int32 i = 0; i < index; i++) - nIt++; - - return nIt->second; -} - - -int32 -AppUsage::Notifications() -{ - return fNotifications.size(); -} - - void -AppUsage::AddNotification(NotificationReceived* notification) +AppUsage::SetAllowed(bool allow) { - fNotifications[notification->Title()] = notification; + fAllow = allow; } diff --git a/src/servers/notification/NotificationServer.cpp b/src/servers/notification/NotificationServer.cpp index 27cf979bb1..23eef11f69 100644 --- a/src/servers/notification/NotificationServer.cpp +++ b/src/servers/notification/NotificationServer.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2015, Haiku, Inc. All Rights Reserved. + * Copyright 2010-2017, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -11,9 +11,11 @@ #include +#include #include #include #include +#include #include "NotificationWindow.h" @@ -56,9 +58,8 @@ NotificationServer::MessageReceived(BMessage* message) if (!fWindow) return; - int32 type = 0; - // Emit a sound for this event + int32 type = 0; if (message->FindInt32("type", &type) == B_OK) { if (type < (int32)(sizeof(kSoundNames) / sizeof(const char*))) system_beep(kSoundNames[type]); diff --git a/src/servers/notification/NotificationServer.h b/src/servers/notification/NotificationServer.h index 50122f57af..091c877110 100644 --- a/src/servers/notification/NotificationServer.h +++ b/src/servers/notification/NotificationServer.h @@ -1,5 +1,5 @@ /* - * Copyright 2010-2015, Haiku, Inc. All Rights Reserved. + * Copyright 2010-2017, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. */ #ifndef _NOTIFICATION_SERVER_H diff --git a/src/servers/notification/NotificationView.cpp b/src/servers/notification/NotificationView.cpp index 2856b42f16..0f5f98ea6b 100644 --- a/src/servers/notification/NotificationView.cpp +++ b/src/servers/notification/NotificationView.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011, Haiku, Inc. All Rights Reserved. + * Copyright 2010-2017, Haiku, Inc. All Rights Reserved. * Copyright 2008-2009, Pier Luigi Fiorini. All Rights Reserved. * Copyright 2004-2008, Michael Davidson. All Rights Reserved. * Copyright 2004-2007, Mikael Eiman. All Rights Reserved. @@ -11,6 +11,7 @@ * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com * Stephan Aßmus * Adrien Destugues + * Brian Hill, supernova@tycho.email */ @@ -35,7 +36,10 @@ #include "NotificationWindow.h" -static const int kIconStripeWidth = 32; +const int kIconStripeWidth = 32; +const float kCloseSize = 6; +const float kEdgePadding = 2; +const float kSmallPadding = 2; property_info message_prop_list[] = { { "type", {B_GET_PROPERTY, B_SET_PROPERTY, 0}, @@ -54,23 +58,22 @@ property_info message_prop_list[] = { }; -NotificationView::NotificationView(NotificationWindow* win, - BNotification* notification, bigtime_t timeout) +NotificationView::NotificationView(BNotification* notification, bigtime_t timeout, + float iconSize, bool disableTimeout) : BView("NotificationView", B_WILL_DRAW), - fParent(win), fNotification(notification), fTimeout(timeout), + fIconSize(iconSize), + fDisableTimeout(disableTimeout), fRunner(NULL), fBitmap(NULL), - fCloseClicked(false) + fCloseClicked(false), + fPreviewModeOn(false) { if (fNotification->Icon() != NULL) fBitmap = new BBitmap(fNotification->Icon()); - if (fTimeout <= 0) - fTimeout = fParent->Timeout() * 1000000; - BGroupLayout* layout = new BGroupLayout(B_VERTICAL); SetLayout(layout); @@ -122,11 +125,12 @@ void NotificationView::AttachedToWindow() { SetText(); - - BMessage msg(kRemoveView); - msg.AddPointer("view", this); - - fRunner = new BMessageRunner(BMessenger(Parent()), &msg, fTimeout, 1); + + if (!fDisableTimeout) { + BMessage msg(kRemoveView); + msg.AddPointer("view", this); + fRunner = new BMessageRunner(BMessenger(Parent()), &msg, fTimeout, 1); + } } @@ -238,9 +242,6 @@ NotificationView::Draw(BRect updateRect) SetDrawingMode(B_OP_ALPHA); SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY); - // Icon size - float iconSize = (float)fParent->IconSize(); - BRect stripeRect = Bounds(); stripeRect.right = kIconStripeWidth; SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), @@ -258,7 +259,7 @@ NotificationView::Draw(BRect updateRect) // Draw icon if (fBitmap) { float ix = 18; - float iy = (Bounds().Height() - iconSize) / 4.0; + float iy = (Bounds().Height() - fIconSize) / 4.0; // Icon is vertically centered in view if (fNotification->Type() == B_PROGRESS_NOTIFICATION) @@ -267,7 +268,7 @@ NotificationView::Draw(BRect updateRect) iy -= (progRect.Height() + kEdgePadding); } - iconRect.Set(ix, iy, ix + iconSize - 1.0, iy + iconSize - 1.0); + iconRect.Set(ix, iy, ix + fIconSize - 1.0, iy + fIconSize - 1.0); DrawBitmapAsync(fBitmap, fBitmap->Bounds(), iconRect); } @@ -279,9 +280,10 @@ NotificationView::Draw(BRect updateRect) SetFont(&l->font); // Truncate the string. We have already line-wrapped the text but if // there is a very long 'word' we can only truncate it. - TruncateString(&(l->text), B_TRUNCATE_END, + BString text(l->text); + TruncateString(&text, B_TRUNCATE_END, Bounds().Width() - l->location.x); - DrawString(l->text.String(), l->text.Length(), l->location); + DrawString(text.String(), text.Length(), l->location); } AppGroupView* groupView = dynamic_cast(Parent()); @@ -333,6 +335,10 @@ NotificationView::_DrawCloseButton(const BRect& updateRect) void NotificationView::MouseDown(BPoint point) { + // Preview Mode ignores any mouse clicks + if (fPreviewModeOn) + return; + int32 buttons; Window()->CurrentMessage()->FindInt32("buttons", &buttons); @@ -447,20 +453,22 @@ NotificationView::SetText(float newMaxWidth) float iconRight = kIconStripeWidth; if (fBitmap != NULL) - iconRight += fParent->IconSize(); + iconRight += fIconSize; else iconRight += 32; + BFont boldFont(be_plain_font); + boldFont.SetFace(B_BOLD_FACE); font_height fh; - be_bold_font->GetHeight(&fh); + boldFont.GetHeight(&fh); float fontHeight = ceilf(fh.leading) + ceilf(fh.descent) + ceilf(fh.ascent); - float y = 2 * fontHeight; + float y = fontHeight + kEdgePadding * 2; // Title LineInfo* titleLine = new LineInfo; titleLine->text = fNotification->Title(); - titleLine->font = *be_bold_font; + titleLine->font = boldFont; titleLine->location = BPoint(iconRight + kEdgePadding, y); @@ -548,6 +556,13 @@ NotificationView::SetText(float newMaxWidth) } +void +NotificationView::SetPreviewModeOn(bool enabled) +{ + fPreviewModeOn = enabled; +} + + const char* NotificationView::MessageID() const { diff --git a/src/servers/notification/NotificationView.h b/src/servers/notification/NotificationView.h index da851cd141..41b7acb3e6 100644 --- a/src/servers/notification/NotificationView.h +++ b/src/servers/notification/NotificationView.h @@ -1,5 +1,5 @@ /* - * Copyright 2010, Haiku, Inc. All Rights Reserved. + * Copyright 2010-2017, Haiku, Inc. All Rights Reserved. * Copyright 2008-2009, Pier Luigi Fiorini. All Rights Reserved. * Copyright 2004-2008, Michael Davidson. All Rights Reserved. * Copyright 2004-2007, Mikael Eiman. All Rights Reserved. @@ -18,16 +18,16 @@ class BBitmap; class BMessageRunner; class BNotification; -class NotificationWindow; - const uint32 kRemoveView = 'ReVi'; +const float kExpandSize = 8; +const float kPenSize = 1; class NotificationView : public BView { public: - NotificationView(NotificationWindow* win, - BNotification* notification, - bigtime_t timeout = -1); + NotificationView(BNotification* notification, + bigtime_t timeout, float iconSize, + bool disableTimeout = false); virtual ~NotificationView(); virtual void AttachedToWindow(); @@ -47,6 +47,7 @@ public: virtual status_t GetSupportedSuites(BMessage* msg); void SetText(float newMaxWidth = -1); + void SetPreviewModeOn(bool enabled); const char* MessageID() const; @@ -62,9 +63,10 @@ private: typedef std::list LineInfoList; - NotificationWindow* fParent; BNotification* fNotification; bigtime_t fTimeout; + float fIconSize; + bool fDisableTimeout; BMessageRunner* fRunner; @@ -73,6 +75,7 @@ private: float fHeight; rgb_color fStripeColor; bool fCloseClicked; + bool fPreviewModeOn; }; #endif // _NOTIFICATION_VIEW_H diff --git a/src/servers/notification/NotificationWindow.cpp b/src/servers/notification/NotificationWindow.cpp index 7a9d9aa1c1..561e5196bd 100644 --- a/src/servers/notification/NotificationWindow.cpp +++ b/src/servers/notification/NotificationWindow.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010, Haiku, Inc. All Rights Reserved. + * Copyright 2010-2017, Haiku, Inc. All Rights Reserved. * Copyright 2008-2009, Pier Luigi Fiorini. All Rights Reserved. * Copyright 2004-2008, Michael Davidson. All Rights Reserved. * Copyright 2004-2007, Mikael Eiman. All Rights Reserved. @@ -9,6 +9,7 @@ * Michael Davidson, slaad@bong.com.au * Mikael Eiman, mikael@eiman.tv * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com + * Brian Hill, supernova@tycho.email */ #include "NotificationWindow.h" @@ -48,20 +49,22 @@ property_info main_prop_list[] = { }; -const float kCloseSize = 6; -const float kExpandSize = 8; -const float kPenSize = 1; -const float kEdgePadding = 2; -const float kSmallPadding = 2; - NotificationWindow::NotificationWindow() : BWindow(BRect(0, 0, -1, -1), B_TRANSLATE_MARK("Notification"), B_BORDERED_WINDOW_LOOK, B_FLOATING_ALL_WINDOW_FEEL, B_AVOID_FRONT | B_AVOID_FOCUS | B_NOT_CLOSABLE | B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE | B_NOT_RESIZABLE | B_NOT_MOVABLE | B_AUTO_UPDATE_SIZE_LIMITS, - B_ALL_WORKSPACES) + B_ALL_WORKSPACES), + fShouldRun(true) { + status_t result = find_directory(B_USER_CACHE_DIRECTORY, &fCachePath); + fCachePath.Append("Notifications"); + BDirectory cacheDir; + result = cacheDir.SetTo(fCachePath.Path()); + if(result == B_ENTRY_NOT_FOUND) + cacheDir.CreateDirectory(fCachePath.Path(), NULL); + SetLayout(new BGroupLayout(B_VERTICAL, 0)); _LoadSettings(true); @@ -126,62 +129,38 @@ NotificationWindow::MessageReceived(BMessage* message) _LoadSettings(); break; } - case B_COUNT_PROPERTIES: - { - BMessage reply(B_REPLY); - BMessage specifier; - const char* property = NULL; - bool messageOkay = true; - - if (message->FindMessage("specifiers", 0, &specifier) != B_OK) - messageOkay = false; - if (specifier.FindString("property", &property) != B_OK) - messageOkay = false; - if (strcmp(property, "message") != 0) - messageOkay = false; - - if (messageOkay) - reply.AddInt32("result", fViews.size()); - else { - reply.what = B_MESSAGE_NOT_UNDERSTOOD; - reply.AddInt32("error", B_ERROR); - } - - message->SendReply(&reply); - break; - } - case B_CREATE_PROPERTY: case kNotificationMessage: { + if (!fShouldRun) + break; + BMessage reply(B_REPLY); BNotification* notification = new BNotification(message); if (notification->InitCheck() == B_OK) { bigtime_t timeout; if (message->FindInt64("timeout", &timeout) != B_OK) - timeout = -1; - BMessenger messenger = message->ReturnAddress(); - app_info info; - - if (messenger.IsValid()) - be_roster->GetRunningAppInfo(messenger.Team(), &info); - else - be_roster->GetAppInfo("application/x-vnd.Be-SHEL", &info); + timeout = fTimeout; + BString sourceSignature(notification->SourceSignature()); + BString sourceName(notification->SourceName()); bool allow = false; - appfilter_t::iterator it = fAppFilters.find(info.signature); - + appfilter_t::iterator it = + fAppFilters.find(sourceSignature.String()); + + AppUsage* appUsage = NULL; if (it == fAppFilters.end()) { - AppUsage* appUsage = new AppUsage(notification->Group(), - true); - - appUsage->Allowed(notification->Title(), - notification->Type()); - fAppFilters[info.signature] = appUsage; + if (sourceSignature.Length() > 0 + && sourceName.Length() > 0) { + appUsage = new AppUsage(sourceName.String(), + sourceSignature.String(), true); + fAppFilters[sourceSignature.String()] = appUsage; + // TODO save back to settings file + } allow = true; } else { - allow = it->second->Allowed(notification->Title(), - notification->Type()); + appUsage = it->second; + allow = appUsage->Allowed(); } if (allow) { @@ -196,8 +175,8 @@ NotificationWindow::MessageReceived(BMessage* message) } else group = aIt->second; - NotificationView* view = new NotificationView(this, - notification, timeout); + NotificationView* view = new NotificationView(notification, + timeout, fIconSize); group->AddInfo(view); @@ -214,18 +193,6 @@ NotificationWindow::MessageReceived(BMessage* message) message->SendReply(&reply); break; } - case kRemoveView: - { - NotificationView* view = NULL; - if (message->FindPointer("view", (void**)&view) != B_OK) - return; - - views_t::iterator it = find(fViews.begin(), fViews.end(), view); - - if (it != fViews.end()) - fViews.erase(it); - break; - } case kRemoveGroupView: { AppGroupView* view = NULL; @@ -254,52 +221,6 @@ NotificationWindow::MessageReceived(BMessage* message) } -BHandler* -NotificationWindow::ResolveSpecifier(BMessage* msg, int32 index, - BMessage* spec, int32 form, const char* prop) -{ - BPropertyInfo prop_info(main_prop_list); - BHandler* handler = NULL; - - if (strcmp(prop,"message") == 0) { - switch (msg->what) { - case B_CREATE_PROPERTY: - { - msg->PopSpecifier(); - handler = this; - break; - } - case B_SET_PROPERTY: - case B_GET_PROPERTY: - { - int32 i; - - if (spec->FindInt32("index", &i) != B_OK) - i = -1; - - if (i >= 0 && i < (int32)fViews.size()) { - msg->PopSpecifier(); - handler = fViews[i]; - } else - handler = NULL; - break; - } - case B_COUNT_PROPERTIES: - msg->PopSpecifier(); - handler = this; - break; - default: - break; - } - } - - if (!handler) - handler = BWindow::ResolveSpecifier(msg, index, spec, form, prop); - - return handler; -} - - icon_size NotificationWindow::IconSize() { @@ -336,17 +257,6 @@ NotificationWindow::_ShowHide() } -void -NotificationWindow::NotificationViewSwapped(NotificationView* stale, - NotificationView* fresh) -{ - views_t::iterator it = find(fViews.begin(), fViews.end(), stale); - - if (it != fViews.end()) - *it = fresh; -} - - void NotificationWindow::SetPosition() { @@ -362,7 +272,8 @@ NotificationWindow::SetPosition() float bottomOffset = bounds.bottom - Frame().bottom; // Size of the borders around the window - float x = Frame().left, y = Frame().top; + float x = Frame().left; + float y = Frame().top; // If we can't guess, don't move... BDeskbar deskbar; @@ -414,7 +325,7 @@ NotificationWindow::_LoadSettings(bool startMonitor) path.Append(kSettingsFile); - BFile file(path.Path(), B_READ_ONLY); + BFile file(path.Path(), B_READ_ONLY | B_CREATE_FILE); settings.Unflatten(&file); _LoadGeneralSettings(settings); @@ -428,10 +339,10 @@ NotificationWindow::_LoadSettings(bool startMonitor) if (watch_node(&nref, B_WATCH_ALL, BMessenger(this)) != B_OK) { BAlert* alert = new BAlert(B_TRANSLATE("Warning"), - B_TRANSLATE("Couldn't start general settings monitor.\n" - "Live filter changes disabled."), B_TRANSLATE("OK")); + B_TRANSLATE("Couldn't start general settings monitor.\n" + "Live filter changes disabled."), B_TRANSLATE("OK")); alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); - alert->Go(); + alert->Go(NULL); } } } @@ -448,8 +359,10 @@ NotificationWindow::_LoadAppFilters(BMessage& settings) for (int32 i = 0; i < count; i++) { AppUsage* app = new AppUsage(); - settings.FindFlat("app_usage", i, app); - fAppFilters[app->Name()] = app; + if (settings.FindFlat("app_usage", i, app) == B_OK) + fAppFilters[app->Signature()] = app; + else + delete app; } } @@ -457,22 +370,18 @@ NotificationWindow::_LoadAppFilters(BMessage& settings) void NotificationWindow::_LoadGeneralSettings(BMessage& settings) { - bool shouldRun; - if (settings.FindBool(kAutoStartName, &shouldRun) == B_OK) { - if (shouldRun == false) { + if (settings.FindBool(kAutoStartName, &fShouldRun) == B_OK) { + if (fShouldRun == false) { // We should not start. Quit the app! be_app_messenger.SendMessage(B_QUIT_REQUESTED); } - } + } else + fShouldRun = true; + 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(); - } + fTimeout *= 1000000; + // Convert from seconds to microseconds } @@ -480,21 +389,22 @@ void NotificationWindow::_LoadDisplaySettings(BMessage& settings) { int32 setting; + float originalWidth = fWidth; if (settings.FindFloat(kWidthName, &fWidth) != B_OK) fWidth = kDefaultWidth; - GetLayout()->SetExplicitMaxSize(BSize(fWidth, B_SIZE_UNSET)); - GetLayout()->SetExplicitMinSize(BSize(fWidth, B_SIZE_UNSET)); + if (originalWidth != fWidth) + GetLayout()->SetExplicitSize(BSize(fWidth, B_SIZE_UNSET)); if (settings.FindInt32(kIconSizeName, &setting) != B_OK) fIconSize = kDefaultIconSize; else fIconSize = (icon_size)setting; - // Notify the view about the change - views_t::iterator it; - for (it = fViews.begin(); it != fViews.end(); ++it) { - NotificationView* view = (*it); + // Notify the views about the change + appview_t::iterator aIt; + for (aIt = fAppViews.begin(); aIt != fAppViews.end(); ++aIt) { + AppGroupView* view = aIt->second; view->Invalidate(); } } diff --git a/src/servers/notification/NotificationWindow.h b/src/servers/notification/NotificationWindow.h index a28dd64751..f4325a9ae2 100644 --- a/src/servers/notification/NotificationWindow.h +++ b/src/servers/notification/NotificationWindow.h @@ -1,5 +1,5 @@ /* - * Copyright 2010, Haiku, Inc. All Rights Reserved. + * Copyright 2010-2017, Haiku, Inc. All Rights Reserved. * Copyright 2008-2009, Pier Luigi Fiorini. All Rights Reserved. * Copyright 2004-2008, Michael Davidson. All Rights Reserved. * Copyright 2004-2007, Mikael Eiman. All Rights Reserved. @@ -13,6 +13,7 @@ #include #include +#include #include #include @@ -26,13 +27,6 @@ struct property_info; typedef std::map appview_t; typedef std::map appfilter_t; -typedef std::vector views_t; - -extern const float kEdgePadding; -extern const float kSmallPadding; -extern const float kCloseSize; -extern const float kExpandSize; -extern const float kPenSize; const uint32 kRemoveGroupView = 'RGVi'; @@ -47,8 +41,6 @@ public: virtual void WorkspaceActivated(int32, bool); virtual void FrameResized(float width, float height); virtual void ScreenChanged(BRect frame, color_space mode); - virtual BHandler* ResolveSpecifier(BMessage*, int32, BMessage*, - int32, const char*); icon_size IconSize(); int32 Timeout(); @@ -59,27 +51,20 @@ public: private: friend class AppGroupView; - void NotificationViewSwapped( - NotificationView* stale, - NotificationView* fresh); - void SetPosition(); void _LoadSettings(bool startMonitor = false); void _LoadAppFilters(BMessage& settings); void _LoadGeneralSettings(BMessage& settings); void _LoadDisplaySettings(BMessage& settings); - views_t fViews; appview_t fAppViews; - - BString fStatusText; - BString fMessageText; + appfilter_t fAppFilters; float fWidth; icon_size fIconSize; int32 fTimeout; - - appfilter_t fAppFilters; + bool fShouldRun; + BPath fCachePath; }; extern property_info main_prop_list[];