Notifications preflet and notification_server

Notifications preflet:
-Use sliders instead of text fields for width and timeout
-Remove icon size choice (mini icon looks horrible)
-Consolidate both "Enable" checkboxes into one
-Fix Revert button, remove Apply button, add Defaults button
-All changes to settings saved immediately
-Live example notification message shown when settings changes are made
-Add setting for individual apps to specify whether their notifications
	should be muted
-Remove history list (to be implemented later)

BNotification class:
-BNotification records the signature and name of application that
	created it
-New functions to get source application signature and name

Notification Server:
-Notification pop up view layout fixes and bold font size fix
-Remove notifications history from AppUsage class (will be saved in
	cache instead)
-Remove vector of NotificationView objects which isn't needed
-Get source application info from notification object, not the received
	message which is not reliable
This commit is contained in:
Brian Hill
2017-09-23 11:41:33 -04:00
parent 7cb920e579
commit 6aa0587222
31 changed files with 1045 additions and 880 deletions
+6 -1
View File
@@ -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. * Distributed under the terms of the MIT License.
*/ */
#ifndef _NOTIFICATION_H #ifndef _NOTIFICATION_H
@@ -34,6 +34,9 @@ public:
static BArchivable* Instantiate(BMessage* archive); static BArchivable* Instantiate(BMessage* archive);
virtual status_t Archive(BMessage* archive, bool deep = true) const; virtual status_t Archive(BMessage* archive, bool deep = true) const;
const char* SourceSignature() const;
const char* SourceName() const;
notification_type Type() const; notification_type Type() const;
const char* Group() const; const char* Group() const;
@@ -73,6 +76,8 @@ public:
private: private:
status_t fInitStatus; status_t fInitStatus;
BString fSourceSignature;
BString fSourceName;
notification_type fType; notification_type fType;
BString fGroup; BString fGroup;
BString fTitle; BString fTitle;
+7 -12
View File
@@ -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 2008-2009, Pier Luigi Fiorini. All Rights Reserved.
* Copyright 2004-2008, Michael Davidson. All Rights Reserved. * Copyright 2004-2008, Michael Davidson. All Rights Reserved.
* Copyright 2004-2007, Mikael Eiman. All Rights Reserved. * Copyright 2004-2007, Mikael Eiman. All Rights Reserved.
@@ -17,16 +17,13 @@
#include <String.h> #include <String.h>
class BMessage; class BMessage;
class NotificationReceived;
typedef std::map<BString, NotificationReceived*> notification_t;
class AppUsage : public BFlattenable { class AppUsage : public BFlattenable {
public: public:
AppUsage(); AppUsage();
AppUsage(const char* name, AppUsage(const char* name,
const char* signature,
bool allow = true); bool allow = true);
~AppUsage();
virtual bool AllowsTypeCode(type_code code) const; virtual bool AllowsTypeCode(type_code code) const;
virtual status_t Flatten(void* buffer, ssize_t numBytes) 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, virtual status_t Unflatten(type_code code, const void* buffer,
ssize_t numBytes); ssize_t numBytes);
const char* Name(); const char* AppName();
bool Allowed(const char* title, notification_type type); const char* Signature();
bool Allowed(); bool Allowed();
NotificationReceived* NotificationAt(int32 index); void SetAllowed(bool allow);
int32 Notifications();
void AddNotification(NotificationReceived* notification);
private: private:
BString fName; BString fAppName;
BString fSignature;
bool fAllow; bool fAllow;
notification_t fNotifications;
}; };
#endif // _APP_USAGE_H #endif // _APP_USAGE_H
+9 -8
View File
@@ -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. * Distributed under the terms of the MIT License.
*/ */
#ifndef _NOTIFICATIONS_H #ifndef _NOTIFICATIONS_H
#define _NOTIFICATIONS_H #define _NOTIFICATIONS_H
#include <Mime.h> #include <Mime.h>
#include <String.h>
#define kNotificationServerSignature "application/x-vnd.Haiku-notification_server" #define kNotificationServerSignature "application/x-vnd.Haiku-notification_server"
@@ -18,18 +19,18 @@ extern const char* kSettingsFile;
// General settings // General settings
extern const char* kAutoStartName; extern const char* kAutoStartName;
extern const char* kTimeoutName; extern const char* kTimeoutName;
extern const char* kWidthName;
extern const char* kIconSizeName;
// General default settings // General default settings
const bool kDefaultAutoStart = true; const bool kDefaultAutoStart = true;
const int32 kDefaultTimeout = 10; const int32 kDefaultTimeout = 10;
const int32 kMinimumTimeout = 3;
// Display settings const int32 kMaximumTimeout = 30;
extern const char* kWidthName;
extern const char* kIconSizeName;
extern const char* kLayoutName;
// Display default settings
const float kDefaultWidth = 300.0f; 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; const icon_size kDefaultIconSize = B_LARGE_ICON;
#endif // _NOTIFICATIONS_H #endif // _NOTIFICATIONS_H
+48 -5
View File
@@ -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. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
* Pier Luigi Fiorini, [email protected] * Pier Luigi Fiorini, [email protected]
* Stephan Aßmus, [email protected] * Stephan Aßmus, [email protected]
* Brian Hill, [email protected]
*/ */
@@ -20,6 +21,7 @@
#include <Bitmap.h> #include <Bitmap.h>
#include <Message.h> #include <Message.h>
#include <NodeInfo.h> #include <NodeInfo.h>
#include <Path.h>
#include <Roster.h> #include <Roster.h>
@@ -32,19 +34,24 @@ BNotification::BNotification(notification_type type)
fFile(NULL), fFile(NULL),
fBitmap(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; int32 iconSize = B_LARGE_ICON;
fBitmap = new BBitmap(BRect(0, 0, iconSize - 1, iconSize - 1), 0, B_RGBA32); fBitmap = new BBitmap(BRect(0, 0, iconSize - 1, iconSize - 1), 0, B_RGBA32);
if (fBitmap) { 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, if (BNodeInfo::GetTrackerIcon(&appInfo.ref, fBitmap,
icon_size(iconSize)) != B_OK) { icon_size(iconSize)) != B_OK) {
delete fBitmap; delete fBitmap;
fBitmap = NULL; 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), fFile(NULL),
fBitmap(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; int32 type;
if (archive->FindInt32("_type", &type) == B_OK) if (archive->FindInt32("_type", &type) == B_OK)
fType = (notification_type)type; fType = (notification_type)type;
@@ -166,6 +181,12 @@ BNotification::Archive(BMessage* archive, bool deep) const
{ {
status_t status = BArchivable::Archive(archive, deep); 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) if (status == B_OK)
status = archive->AddInt32("_type", (int32)fType); 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. /*! \brief Notification's type.
\return A value of the notification_type enum that represents \return A value of the notification_type enum that represents
@@ -0,0 +1,66 @@
/*
* Copyright 2017, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Brian Hill, [email protected]
*/
#include "AppRefFilter.h"
#include <string.h>
/* 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;
}
@@ -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 <FilePanel.h>
#include <NodeInfo.h>
class AppRefFilter : public BRefFilter {
public:
AppRefFilter();
virtual bool Filter(const entry_ref *ref,
BNode *node,
struct stat_beos *st,
const char *filetype);
};
#endif
@@ -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, [email protected]
*/
#include <stdio.h>
#include <stdlib.h>
#include <Alert.h>
#include <Catalog.h>
#include <Directory.h>
#include <FindDirectory.h>
#include <LayoutBuilder.h>
#include <Menu.h>
#include <MenuItem.h>
#include <MenuField.h>
#include <Message.h>
#include <Mime.h>
#include <Node.h>
#include <Path.h>
#include <SpaceLayoutItem.h>
#include <TextControl.h>
#include <notification/Notifications.h>
#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;
}
@@ -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
+173 -137
View File
@@ -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. * Copyright 2009, Pier Luigi Fiorini.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
* Pier Luigi Fiorini, [email protected] * Pier Luigi Fiorini, [email protected]
* Brian Hill, [email protected]
*/ */
#include <stdio.h> #include <stdio.h>
@@ -13,9 +14,9 @@
#include <vector> #include <vector>
#include <Alert.h> #include <Alert.h>
#include <Box.h>
#include <Button.h> #include <Button.h>
#include <Catalog.h> #include <Catalog.h>
#include <CheckBox.h>
#include <Directory.h> #include <Directory.h>
#include <File.h> #include <File.h>
#include <FindDirectory.h> #include <FindDirectory.h>
@@ -26,70 +27,87 @@
#include <Query.h> #include <Query.h>
#include <Roster.h> #include <Roster.h>
#include <String.h> #include <String.h>
#include <StringView.h>
#include <SymLink.h> #include <SymLink.h>
#include <TextControl.h>
#include <Volume.h> #include <Volume.h>
#include <VolumeRoster.h> #include <VolumeRoster.h>
#include <notification/Notifications.h> #include <notification/Notifications.h>
#include "GeneralView.h" #include "GeneralView.h"
#include "NotificationsConstants.h"
#include "SettingsHost.h" #include "SettingsHost.h"
#undef B_TRANSLATION_CONTEXT #undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "GeneralView" #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) GeneralView::GeneralView(SettingsHost* host)
: :
SettingsPane("general", host) SettingsPane("general", host)
{ {
// Notifications // Notification server
fNotificationBox = new BCheckBox("server", fNotificationBox = new BCheckBox("server",
B_TRANSLATE("Enable notifications"), B_TRANSLATE("Enable notifications"),
new BMessage(kToggleNotifications)); new BMessage(kToggleNotifications));
BBox* box = new BBox("box");
box->SetLabel(fNotificationBox);
// Autostart // Window width
fAutoStart = new BCheckBox("autostart", int32 minWidth = int32(kMinimumWidth / kWidthStep);
B_TRANSLATE("Enable notifications at startup"), int32 maxWidth = int32(kMaximumWidth / kWidthStep);
new BMessage(kSettingChanged)); 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 // Display time
fTimeout = new BTextControl(B_TRANSLATE("Hide notifications from screen" fDurationSlider = new BSlider("duration", B_TRANSLATE("Duration:"),
" after"), NULL, new BMessage(kSettingChanged)); new BMessage(kTimeoutChanged), kMinimumTimeout, kMaximumTimeout,
BStringView* displayTimeLabel = new BStringView("dt_label", B_HORIZONTAL);
B_TRANSLATE("seconds of inactivity")); fDurationSlider->SetHashMarks(B_HASH_MARKS_BOTTOM);
fDurationSlider->SetHashMarkCount(kMaximumTimeout - kMinimumTimeout + 1);
// Default position BString minLabel;
// TODO: Here will come a screen representation with the four corners minLabel << kMinimumTimeout;
// clickable 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) 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) .SetInsets(B_USE_WINDOW_SPACING)
.AddGlue(); .Add(box)
.End();
} }
void void
GeneralView::AttachedToWindow() GeneralView::AttachedToWindow()
{ {
BView::AttachedToWindow();
fNotificationBox->SetTarget(this); fNotificationBox->SetTarget(this);
fAutoStart->SetTarget(this); fWidthSlider->SetTarget(this);
fTimeout->SetTarget(this); fDurationSlider->SetTarget(this);
} }
@@ -99,70 +117,23 @@ GeneralView::MessageReceived(BMessage* msg)
switch (msg->what) { switch (msg->what) {
case kToggleNotifications: case kToggleNotifications:
{ {
entry_ref ref; SettingsPane::SettingsChanged(false);
_EnableControls();
// 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;
}
}
break; break;
} }
case kSettingChanged: case kWidthChanged: {
SettingsPane::MessageReceived(msg); int32 value = fWidthSlider->Value() * 50;
_SetWidthLabel(value);
SettingsPane::SettingsChanged(true);
break; break;
}
case kTimeoutChanged:
{
int32 value = fDurationSlider->Value();
_SetTimeoutLabel(value);
SettingsPane::SettingsChanged(true);
break;
}
default: default:
BView::MessageReceived(msg); BView::MessageReceived(msg);
break; break;
@@ -173,34 +144,46 @@ GeneralView::MessageReceived(BMessage* msg)
status_t status_t
GeneralView::Load(BMessage& settings) 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.FindInt32(kTimeoutName, &fOriginalTimeout) != B_OK
if (settings.FindBool(kAutoStartName, &autoStart) != B_OK) || fOriginalTimeout > kMaximumTimeout
autoStart = kDefaultAutoStart; || fOriginalTimeout < kMinimumTimeout)
fAutoStart->SetValue(autoStart ? B_CONTROL_ON : B_CONTROL_OFF); 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; _EnableControls();
if (settings.FindInt32(kTimeoutName, &timeout) != B_OK)
timeout = kDefaultTimeout; return Revert();
(void)sprintf(buffer, "%" B_PRId32, timeout);
fTimeout->SetText(buffer);
return B_OK;
} }
status_t status_t
GeneralView::Save(BMessage& settings) GeneralView::Save(BMessage& settings)
{ {
bool autoStart = (fAutoStart->Value() == B_CONTROL_ON); bool autoStart = (fNotificationBox->Value() == B_CONTROL_ON);
settings.AddBool(kAutoStartName, autoStart); settings.AddBool(kAutoStartName, autoStart);
int32 timeout = atol(fTimeout->Text()); int32 timeout = fDurationSlider->Value();
settings.AddInt32(kTimeoutName, timeout); 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; return B_OK;
} }
@@ -208,44 +191,97 @@ GeneralView::Save(BMessage& settings)
status_t status_t
GeneralView::Revert() GeneralView::Revert()
{ {
return B_ERROR; fDurationSlider->SetValue(fOriginalTimeout);
_SetTimeoutLabel(fOriginalTimeout);
fWidthSlider->SetValue(fOriginalWidth / 50);
_SetWidthLabel(fOriginalWidth);
return B_OK;
} }
bool bool
GeneralView::_CanFindServer(entry_ref* ref) GeneralView::RevertPossible()
{ {
// Try searching with be_roster int32 timeout = fDurationSlider->Value();
if (be_roster->FindApp(kNotificationServerSignature, ref) == B_OK) if (fOriginalTimeout != timeout)
return true;
int32 width = fWidthSlider->Value() * 50;
if (fOriginalWidth != width)
return true; 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; 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 bool
GeneralView::_IsServerRunning() GeneralView::_IsServerRunning()
{ {
+25 -8
View File
@@ -1,16 +1,24 @@
/* /*
* Copyright 2010, Haiku, Inc. All Rights Reserved. * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
* Copyright 2009, Pier Luigi Fiorini. * Copyright 2009, Pier Luigi Fiorini.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef _GENERAL_VIEW_H #ifndef _GENERAL_VIEW_H
#define _GENERAL_VIEW_H #define _GENERAL_VIEW_H
#include <Button.h>
#include <CheckBox.h>
#include <Menu.h>
#include <MenuField.h>
#include <Mime.h>
#include <RadioButton.h>
#include <Slider.h>
#include <StringView.h>
#include <TextControl.h>
#include "SettingsPane.h" #include "SettingsPane.h"
class BCheckBox;
class BStringView;
class BTextControl;
class GeneralView : public SettingsPane { class GeneralView : public SettingsPane {
public: public:
@@ -23,14 +31,23 @@ public:
status_t Load(BMessage&); status_t Load(BMessage&);
status_t Save(BMessage&); status_t Save(BMessage&);
status_t Revert(); status_t Revert();
bool RevertPossible();
status_t Defaults();
bool DefaultsPossible();
bool UseDefaultRevertButtons();
private: private:
BCheckBox* fNotificationBox; BCheckBox* fNotificationBox;
BCheckBox* fAutoStart; BSlider* fDurationSlider;
BTextControl* fTimeout; BSlider* fWidthSlider;
BCheckBox* fHideAll;
int32 fOriginalTimeout;
float fOriginalWidth;
icon_size fOriginalIconSize;
bool _CanFindServer(entry_ref* ref); void _EnableControls();
void _SetWidthLabel(int32 value);
void _SetTimeoutLabel(int32 value);
bool _IsServerRunning(); bool _IsServerRunning();
}; };
+6 -5
View File
@@ -1,18 +1,20 @@
SubDir HAIKU_TOP src preferences notifications ; SubDir HAIKU_TOP src preferences notifications ;
UsePrivateHeaders shared ; UseHeaders [ FDirName $(HAIKU_TOP) src servers notification ] : true ;
UsePrivateHeaders interface ; UsePrivateHeaders interface notification ;
Application Notifications : Application Notifications :
AppRefFilter.cpp
Notifications.cpp Notifications.cpp
PrefletWin.cpp PrefletWin.cpp
PrefletView.cpp PrefletView.cpp
SettingsPane.cpp SettingsPane.cpp
GeneralView.cpp GeneralView.cpp
DisplayView.cpp
NotificationsView.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 : Notifications.rdef
; ;
@@ -22,7 +24,6 @@ Depends Notifications : libnotification.a ;
DoCatalogs Notifications : DoCatalogs Notifications :
x-vnd.Haiku-Notifications x-vnd.Haiku-Notifications
: :
DisplayView.cpp
GeneralView.cpp GeneralView.cpp
PrefletWin.cpp PrefletWin.cpp
PrefletView.cpp PrefletView.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. * Copyright 2009, Pier Luigi Fiorini.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
@@ -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 */
@@ -1,13 +1,15 @@
/* /*
* Copyright 2010, Haiku, Inc. All Rights Reserved. * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
* Copyright 2009, Pier Luigi Fiorini. * Copyright 2009, Pier Luigi Fiorini.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
* Pier Luigi Fiorini, [email protected] * Pier Luigi Fiorini, [email protected]
* Brian Hill, [email protected]
*/ */
#include <Alert.h> #include <Alert.h>
#include <Button.h>
#include <Catalog.h> #include <Catalog.h>
#include <CheckBox.h> #include <CheckBox.h>
#include <ColumnListView.h> #include <ColumnListView.h>
@@ -23,90 +25,113 @@
#include <notification/Notifications.h> #include <notification/Notifications.h>
#include <notification/NotificationReceived.h> #include <notification/NotificationReceived.h>
#include "NotificationsConstants.h"
#include "NotificationsView.h" #include "NotificationsView.h"
#undef B_TRANSLATION_CONTEXT #undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "NotificationView" #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 // Applications column indexes
const int32 kAppIndex = 0; const int32 kAppNameIndex = 0;
const int32 kAppEnabledIndex = 1; const int32 kAppEnabledIndex = 1;
// Notifications column indexes
const int32 kTitleIndex = 0; AppRow::AppRow(const char* name, const char* signature, bool allowed)
const int32 kDateIndex = 1; :
const int32 kTypeIndex = 2; BRow(),
const int32 kAllowIndex = 3; 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) 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 // Applications list
fApplications = new BColumnListView(B_TRANSLATE("Applications"), fApplications = new BColumnListView(B_TRANSLATE("Applications"),
0, B_FANCY_BORDER, true); 0, B_FANCY_BORDER, false);
fApplications->SetSelectionMode(B_SINGLE_SELECTION_LIST); fApplications->SetSelectionMode(B_SINGLE_SELECTION_LIST);
fApplications->SetSelectionMessage(new BMessage(kApplicationSelected));
fAppCol = new BStringColumn(B_TRANSLATE("Application"), 200, float colWidth = be_plain_font->StringWidth(B_TRANSLATE("Application"))
be_plain_font->StringWidth(B_TRANSLATE("Application")) + + (kCLVTitlePadding * 2);
(kCLVTitlePadding * 2), rect.Width(), B_TRUNCATE_END, B_ALIGN_LEFT); fAppCol = new BStringColumn(B_TRANSLATE("Application"), colWidth * 2,
fApplications->AddColumn(fAppCol, kAppIndex); colWidth, colWidth * 4, B_TRUNCATE_END, B_ALIGN_LEFT);
fApplications->AddColumn(fAppCol, kAppNameIndex);
fAppEnabledCol = new BStringColumn(B_TRANSLATE("Enabled"), 10, colWidth = be_plain_font->StringWidth(B_TRANSLATE("Status"))
be_plain_font->StringWidth(B_TRANSLATE("Enabled")) + + (kCLVTitlePadding * 2);
(kCLVTitlePadding * 2), rect.Width(), B_TRUNCATE_END, B_ALIGN_LEFT); fAppEnabledCol = new BStringColumn(B_TRANSLATE("Status"), colWidth * 1.5,
colWidth, colWidth * 3, B_TRUNCATE_END, B_ALIGN_LEFT);
fApplications->AddColumn(fAppEnabledCol, kAppEnabledIndex); fApplications->AddColumn(fAppEnabledCol, kAppEnabledIndex);
fApplications->SetSortColumn(fAppCol, true, true);
// Notifications list
fNotifications = new BColumnListView(B_TRANSLATE("Notifications"), fAddButton = new BButton("add_app", B_TRANSLATE("Add" B_UTF8_ELLIPSIS),
0, B_FANCY_BORDER, true); new BMessage(kAddApplication));
fNotifications->SetSelectionMode(B_SINGLE_SELECTION_LIST); fRemoveButton = new BButton("add_app", B_TRANSLATE("Remove"),
new BMessage(kRemoveApplication));
fTitleCol = new BStringColumn(B_TRANSLATE("Title"), 100, fRemoveButton->SetEnabled(false);
be_plain_font->StringWidth(B_TRANSLATE("Title")) +
(kCLVTitlePadding * 2), rect.Width(), B_TRUNCATE_END, B_ALIGN_LEFT); fMuteAll = new BCheckBox("block", B_TRANSLATE("Mute notifications from "
fNotifications->AddColumn(fTitleCol, kTitleIndex); "this application"),
new BMessage(kMuteChanged));
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);
// Add views // Add views
BLayoutBuilder::Group<>(this, B_VERTICAL) BLayoutBuilder::Group<>(this, B_VERTICAL)
.AddGroup(B_HORIZONTAL) .AddGroup(B_HORIZONTAL)
.AddGlue() .Add(fApplications)
.Add(fSearch) .AddGroup(B_VERTICAL)
.Add(fAddButton)
.Add(fRemoveButton)
.AddGlue()
.End()
.End() .End()
.Add(fApplications) .Add(fMuteAll)
.Add(fNotifications)
.SetInsets(B_USE_WINDOW_SPACING, B_USE_WINDOW_SPACING, .SetInsets(B_USE_WINDOW_SPACING, B_USE_WINDOW_SPACING,
B_USE_WINDOW_SPACING, B_USE_DEFAULT_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->SetTarget(this);
fApplications->SetInvocationMessage(new BMessage(kApplicationSelected)); fApplications->SetInvocationMessage(new BMessage(kApplicationSelected));
fAddButton->SetTarget(this);
fNotifications->SetTarget(this); fRemoveButton->SetTarget(this);
fNotifications->SetInvocationMessage(new BMessage(kNotificationSelected)); fMuteAll->SetTarget(this);
fAddAppPanel->SetTarget(this);
#if 0 _RecallItemSettings();
fNotifications->AddFilter(new BMessageFilter(B_ANY_DELIVERY,
B_ANY_SOURCE, B_KEY_DOWN, CatchDelete));
#endif
} }
@@ -132,22 +154,97 @@ NotificationsView::MessageReceived(BMessage* msg)
switch (msg->what) { switch (msg->what) {
case kApplicationSelected: case kApplicationSelected:
{ {
BRow* row = fApplications->CurrentSelection(); Window()->Lock();
if (row == NULL) _ClearItemSettings();
return; _UpdateSelectedItem();
BStringField* appName _RecallItemSettings();
= dynamic_cast<BStringField*>(row->GetField(kAppIndex)); Window()->Unlock();
if (appName == NULL)
break;
appusage_t::iterator it = fAppFilters.find(appName->String());
if (it != fAppFilters.end())
_Populate(it->second);
break; 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; 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: default:
BView::MessageReceived(msg); BView::MessageReceived(msg);
break; break;
@@ -174,7 +271,7 @@ NotificationsView::Load(BMessage& settings)
for (int32 i = 0; i < count; i++) { for (int32 i = 0; i < count; i++) {
AppUsage* app = new AppUsage(); AppUsage* app = new AppUsage();
settings.FindFlat("app_usage", i, app); settings.FindFlat("app_usage", i, app);
fAppFilters[app->Name()] = app; fAppFilters[app->Signature()] = app;
} }
// Load the applications list // Load the applications list
@@ -196,64 +293,84 @@ NotificationsView::Save(BMessage& storage)
void void
NotificationsView::_PopulateApplications() NotificationsView::_ClearItemSettings()
{ {
appusage_t::iterator it; fMuteAll->SetValue(B_CONTROL_OFF);
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);
}
} }
void void
NotificationsView::_Populate(AppUsage* usage) NotificationsView::_UpdateSelectedItem()
{ {
// Sanity check fSelectedRow = dynamic_cast<AppRow*>(fApplications->CurrentSelection());
if (!usage)
return; }
int32 size = usage->Notifications();
if (usage->Allowed() == false) void
fBlockAll->SetValue(B_CONTROL_ON); NotificationsView::_RecallItemSettings()
{
fNotifications->Clear(); // No selected item
if(fSelectedRow == NULL)
for (int32 i = 0; i < size; i++) { {
NotificationReceived* notification = usage->NotificationAt(i); fMuteAll->SetValue(B_CONTROL_OFF);
time_t updated = notification->LastReceived(); fMuteAll->SetEnabled(false);
const char* allow = notification->Allowed() ? B_TRANSLATE("Yes") fRemoveButton->SetEnabled(false);
: B_TRANSLATE("No"); } else {
const char* type = ""; fMuteAll->SetEnabled(true);
fRemoveButton->SetEnabled(true);
switch (notification->Type()) { appusage_t::iterator it = fAppFilters.find(fSelectedRow->Signature());
case B_INFORMATION_NOTIFICATION: if (it != fAppFilters.end())
type = B_TRANSLATE("Information"); fMuteAll->SetValue(!(it->second->Allowed()));
break; }
case B_IMPORTANT_NOTIFICATION: }
type = B_TRANSLATE("Important");
break;
case B_ERROR_NOTIFICATION: status_t
type = B_TRANSLATE("Error"); NotificationsView::Revert()
break; {
case B_PROGRESS_NOTIFICATION: return B_OK;
type = B_TRANSLATE("Progress"); }
break;
default:
type = B_TRANSLATE("Unknown"); bool
} NotificationsView::RevertPossible()
{
BRow* row = new BRow(); return false;
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); status_t
NotificationsView::Defaults()
fNotifications->AddRow(row); {
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);
} }
} }
@@ -1,50 +1,78 @@
/* /*
* Copyright 2010, Haiku, Inc. All Rights Reserved. * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
* Copyright 2009, Pier Luigi Fiorini. * Copyright 2009, Pier Luigi Fiorini.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef _APPS_VIEW_H #ifndef _APPS_VIEW_H
#define _APPS_VIEW_H #define _APPS_VIEW_H
#include <FilePanel.h>
#include <ColumnListView.h>
#include <View.h> #include <View.h>
#include <notification/AppUsage.h> #include <notification/AppUsage.h>
#include "AppRefFilter.h"
#include "SettingsPane.h" #include "SettingsPane.h"
typedef std::map<BString, AppUsage *> appusage_t; typedef std::map<BString, AppUsage *> appusage_t;
class BButton;
class BCheckBox; class BCheckBox;
class BTextControl; class BTextControl;
class BColumnListView;
class BStringColumn; class BStringColumn;
class BDateColumn; 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 { class NotificationsView : public SettingsPane {
public: public:
NotificationsView(SettingsHost* host); NotificationsView(SettingsHost* host);
~NotificationsView();
virtual void AttachedToWindow(); virtual void AttachedToWindow();
virtual void MessageReceived(BMessage* msg); virtual void MessageReceived(BMessage* msg);
status_t Revert();
bool RevertPossible();
status_t Defaults();
bool DefaultsPossible();
bool UseDefaultRevertButtons();
private: private:
status_t Load(BMessage&); status_t Load(BMessage&);
status_t Save(BMessage&); status_t Save(BMessage&);
status_t Revert() {return B_OK;} // FIXME implement this void _ClearItemSettings();
void _UpdateSelectedItem();
void _RecallItemSettings();
void _PopulateApplications(); void _PopulateApplications();
void _Populate(AppUsage* usage);
appusage_t fAppFilters; appusage_t fAppFilters;
BCheckBox* fBlockAll; AppRefFilter* fPanelFilter;
BTextControl* fSearch; BFilePanel* fAddAppPanel;
BButton* fAddButton;
BButton* fRemoveButton;
BCheckBox* fMuteAll;
BColumnListView* fApplications; BColumnListView* fApplications;
AppRow* fSelectedRow;
BStringColumn* fAppCol; BStringColumn* fAppCol;
BStringColumn* fAppEnabledCol; BStringColumn* fAppEnabledCol;
BColumnListView* fNotifications;
BStringColumn* fTitleCol;
BDateColumn* fDateCol;
BStringColumn* fTypeCol;
BStringColumn* fAllowCol;
}; };
#endif // _APPS_VIEW_H #endif // _APPS_VIEW_H
+22 -21
View File
@@ -1,10 +1,11 @@
/* /*
* Copyright 2010, Haiku, Inc. All Rights Reserved. * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
* Copyright 2009, Pier Luigi Fiorini. * Copyright 2009, Pier Luigi Fiorini.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
* Pier Luigi Fiorini, [email protected] * Pier Luigi Fiorini, [email protected]
* Brian Hill, [email protected]
*/ */
#include <Catalog.h> #include <Catalog.h>
@@ -13,9 +14,8 @@
#include <GroupLayoutBuilder.h> #include <GroupLayoutBuilder.h>
#include <LayoutItem.h> #include <LayoutItem.h>
#include <Message.h> #include <Message.h>
#include <Window.h>
#include "DisplayView.h"
#include "GeneralView.h"
#include "NotificationsView.h" #include "NotificationsView.h"
#include "PrefletView.h" #include "PrefletView.h"
#include "SettingsHost.h" #include "SettingsHost.h"
@@ -25,30 +25,22 @@
#define B_TRANSLATION_CONTEXT "PrefletView" #define B_TRANSLATION_CONTEXT "PrefletView"
const int32 kPageSelected = '_LCH';
PrefletView::PrefletView(SettingsHost* host) PrefletView::PrefletView(SettingsHost* host)
: :
BTabView("pages", B_WIDTH_FROM_WIDEST) BTabView("pages", B_WIDTH_FROM_WIDEST)
{ {
// Pages // Pages
GeneralView* general = new GeneralView(host); fGeneralView = new GeneralView(host);
DisplayView* display = new DisplayView(host);
NotificationsView* apps = new NotificationsView(host); NotificationsView* apps = new NotificationsView(host);
// Page selector // Page selector
BTab* tab = new BTab(); BTab* tab = new BTab();
AddTab(general, tab); AddTab(fGeneralView, tab);
tab->SetLabel(B_TRANSLATE("General")); tab->SetLabel(B_TRANSLATE("General"));
tab = new BTab();
AddTab(display, tab);
tab->SetLabel(B_TRANSLATE("Display"));
tab = new BTab(); tab = new BTab();
AddTab(apps, tab); 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* BView*
PrefletView::PageAt(int32 index) PrefletView::PageAt(int32 index)
{ {
return TabAt(index)->View(); return TabAt(index)->View();
} }
void
PrefletView::Select(int32 index)
{
if (index == Selection())
return;
BTabView::Select(index);
SettingsPane* pane = dynamic_cast<SettingsPane*>(PageAt(index));
bool showButtons = (pane != NULL) && pane->UseDefaultRevertButtons();
BMessage showMessage(kShowButtons);
showMessage.AddBool(kShowButtonsKey, showButtons);
Window()->PostMessage(&showMessage);
}
+11 -3
View File
@@ -1,24 +1,32 @@
/* /*
* Copyright 2010, Haiku, Inc. All Rights Reserved. * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
* Copyright 2009, Pier Luigi Fiorini. * Copyright 2009, Pier Luigi Fiorini.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef _PREFLET_VIEW_H #ifndef _PREFLET_VIEW_H
#define _PREFLET_VIEW_H #define _PREFLET_VIEW_H
#include <Messenger.h>
#include <TabView.h> #include <TabView.h>
class BIconRule; #include "GeneralView.h"
class SettingsHost; class SettingsHost;
const int32 kShowButtons = '_SHB';
#define kShowButtonsKey "showButtons"
class PrefletView : public BTabView { class PrefletView : public BTabView {
public: public:
PrefletView(SettingsHost* host); PrefletView(SettingsHost* host);
BView* CurrentPage(); BView* CurrentPage();
int32 CountPages() const;
BView* PageAt(int32 index); BView* PageAt(int32 index);
virtual void Select(int32 index);
private:
GeneralView* fGeneralView;
BMessenger fMessenger;
}; };
#endif // PREFLETVIEW_H #endif // PREFLETVIEW_H
+127 -32
View File
@@ -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. * Copyright 2009, Pier Luigi Fiorini.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
* Pier Luigi Fiorini, [email protected] * Pier Luigi Fiorini, [email protected]
* Brian Hill, [email protected]
*/ */
#include "PrefletWin.h" #include "PrefletWin.h"
@@ -14,52 +15,62 @@
#include <Button.h> #include <Button.h>
#include <Catalog.h> #include <Catalog.h>
#include <FindDirectory.h> #include <FindDirectory.h>
#include <LayoutBuilder.h> #include <Notification.h>
#include <Path.h> #include <Path.h>
#include <SeparatorView.h> #include <SeparatorView.h>
#include <notification/Notifications.h> #include <notification/Notifications.h>
#include "NotificationsConstants.h"
#include "PrefletView.h" #include "PrefletView.h"
#undef B_TRANSLATION_CONTEXT #undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "PrefletWin" #define B_TRANSLATION_CONTEXT "PrefletWin"
const BString kSampleMessageID("NotificationsSample");
const int32 kRevert = '_RVT';
const int32 kApply = '_APY';
PrefletWin::PrefletWin() 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_TITLED_WINDOW, B_NOT_ZOOMABLE | B_ASYNCHRONOUS_CONTROLS
| B_AUTO_UPDATE_SIZE_LIMITS) | B_AUTO_UPDATE_SIZE_LIMITS)
{ {
// Preflet container view // Preflet container view
fMainView = new PrefletView(this); fMainView = new PrefletView(this);
fMainView->SetBorder(B_NO_BORDER); 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"), fRevert = new BButton("revert", B_TRANSLATE("Revert"),
new BMessage(kRevert)); new BMessage(kRevert));
fRevert->SetEnabled(false); fRevert->SetEnabled(false);
fApply = new BButton("apply", B_TRANSLATE("Apply"), new BMessage(kApply));
fApply->SetEnabled(false);
// Build the layout // 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) BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
.SetInsets(0, B_USE_DEFAULT_SPACING, 0, 0) .SetInsets(0, B_USE_DEFAULT_SPACING, 0, 0)
.Add(fMainView) .Add(fMainView)
.Add(new BSeparatorView(B_HORIZONTAL)) .Add(fButtonsView)
.AddGroup(B_HORIZONTAL) .End();
.Add(fRevert) fMainView->SetExplicitMinSize(BSize(Frame().Width(), B_SIZE_UNSET));
.AddGlue()
.Add(fApply)
.SetInsets(B_USE_WINDOW_SPACING, B_USE_DEFAULT_SPACING,
B_USE_WINDOW_SPACING, B_USE_WINDOW_SPACING);
ReloadSettings(); ReloadSettings();
@@ -74,6 +85,7 @@ PrefletWin::MessageReceived(BMessage* msg)
{ {
switch (msg->what) { switch (msg->what) {
case kApply: case kApply:
case kApplyWithExample:
{ {
BPath path; BPath path;
@@ -85,13 +97,14 @@ PrefletWin::MessageReceived(BMessage* msg)
path.Append(kSettingsFile); path.Append(kSettingsFile);
BMessage settingsStore; BMessage settingsStore;
for (int32 i = 0; i < fMainView->CountPages(); i++) { int32 count = fMainView->CountTabs();
for (int32 i = 0; i < count; i++) {
SettingsPane* pane = SettingsPane* pane =
dynamic_cast<SettingsPane*>(fMainView->PageAt(i)); dynamic_cast<SettingsPane*>(fMainView->PageAt(i));
if (pane) { if (pane) {
if (pane->Save(settingsStore) == B_OK) { if (pane->Save(settingsStore) == B_OK) {
fApply->SetEnabled(false); fDefaults->SetEnabled(_DefaultsPossible());
fRevert->SetEnabled(true); fRevert->SetEnabled(_RevertPossible());
} else } else
break; break;
} }
@@ -109,19 +122,28 @@ PrefletWin::MessageReceived(BMessage* msg)
alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
(void)alert->Go(); (void)alert->Go();
} }
file.Unset();
if (msg->what == kApplyWithExample)
_SendExampleNotification();
break; break;
} }
case kRevert: case kDefaults:
for (int32 i = 0; i < fMainView->CountPages(); i++) { fDefaults->SetEnabled(false);
SettingsPane* pane = _Defaults();
dynamic_cast<SettingsPane*>(fMainView->PageAt(i)); PostMessage(kApply);
if (pane) {
if (pane->Revert() == B_OK)
fRevert->SetEnabled(false);
}
}
break; break;
case kRevert:
fRevert->SetEnabled(false);
_Revert();
PostMessage(kApply);
break;
case kShowButtons: {
bool show = msg->GetBool(kShowButtonsKey, true);
fButtonsLayout->SetVisible(show);
break;
}
default: default:
BWindow::MessageReceived(msg); BWindow::MessageReceived(msg);
} }
@@ -137,9 +159,12 @@ PrefletWin::QuitRequested()
void 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); BFile file(path.Path(), B_READ_ONLY);
settings.Unflatten(&file); settings.Unflatten(&file);
for (int32 i = 0; i < fMainView->CountPages(); i++) { int32 count = fMainView->CountTabs();
for (int32 i = 0; i < count; i++) {
SettingsPane* pane = SettingsPane* pane =
dynamic_cast<SettingsPane*>(fMainView->PageAt(i)); dynamic_cast<SettingsPane*>(fMainView->PageAt(i));
if (pane) if (pane)
pane->Load(settings); 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<SettingsPane*>(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<SettingsPane*>(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<SettingsPane*>(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<SettingsPane*>(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();
} }
+15 -3
View File
@@ -1,11 +1,15 @@
/* /*
* Copyright 2010, Haiku, Inc. All Rights Reserved. * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
* Copyright 2009, Pier Luigi Fiorini. * Copyright 2009, Pier Luigi Fiorini.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef _PREFLET_WIN_H #ifndef _PREFLET_WIN_H
#define _PREFLET_WIN_H #define _PREFLET_WIN_H
#include <GroupView.h>
#include <LayoutBuilder.h>
#include <Message.h>
#include <Window.h> #include <Window.h>
#include "SettingsHost.h" #include "SettingsHost.h"
@@ -21,13 +25,21 @@ public:
virtual bool QuitRequested(); virtual bool QuitRequested();
virtual void MessageReceived(BMessage* msg); virtual void MessageReceived(BMessage* msg);
virtual void SettingChanged(); virtual void SettingChanged(bool showExample);
void ReloadSettings(); void ReloadSettings();
private: private:
status_t _Revert();
bool _RevertPossible();
status_t _Defaults();
bool _DefaultsPossible();
void _SendExampleNotification();
PrefletView* fMainView; PrefletView* fMainView;
BButton* fApply; BGroupView* fButtonsView;
BButton* fDefaults;
BButton* fRevert; BButton* fRevert;
BGroupLayout* fButtonsLayout;
}; };
#endif // _PREFLET_WIN_H #endif // _PREFLET_WIN_H
+2 -2
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2010, Haiku, Inc. All Rights Reserved. * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
* Copyright 2009, Pier Luigi Fiorini. * Copyright 2009, Pier Luigi Fiorini.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
@@ -14,7 +14,7 @@ class SettingsHost {
public: public:
SettingsHost() {} SettingsHost() {}
virtual void SettingChanged() = 0; virtual void SettingChanged(bool showExample = false) = 0;
}; };
#endif // _SETTINGS_HOST_H #endif // _SETTINGS_HOST_H
@@ -1,10 +1,11 @@
/* /*
* Copyright 2010, Haiku, Inc. All Rights Reserved. * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
* Copyright 2009, Pier Luigi Fiorini. * Copyright 2009, Pier Luigi Fiorini.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
* Pier Luigi Fiorini, [email protected] * Pier Luigi Fiorini, [email protected]
* Brian Hill, [email protected]
*/ */
#include <Message.h> #include <Message.h>
@@ -22,13 +23,7 @@ SettingsPane::SettingsPane(const char* name, SettingsHost* host)
void void
SettingsPane::MessageReceived(BMessage* msg) SettingsPane::SettingsChanged(bool showExample)
{ {
switch (msg->what) { fHost->SettingChanged(showExample);
case kSettingChanged:
fHost->SettingChanged();
break;
default:
BView::MessageReceived(msg);
}
} }
+6 -3
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2010, Haiku, Inc. All Rights Reserved. * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
* Copyright 2009, Pier Luigi Fiorini. * Copyright 2009, Pier Luigi Fiorini.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
@@ -12,17 +12,20 @@ class BNode;
class SettingsHost; class SettingsHost;
const int32 kSettingChanged = '_STC';
class SettingsPane : public BView { class SettingsPane : public BView {
public: public:
SettingsPane(const char* name, SettingsHost* host); SettingsPane(const char* name, SettingsHost* host);
virtual void MessageReceived(BMessage* msg); void SettingsChanged(bool showExample);
virtual status_t Load(BMessage&) = 0; virtual status_t Load(BMessage&) = 0;
virtual status_t Save(BMessage&) = 0; virtual status_t Save(BMessage&) = 0;
virtual status_t Revert() = 0; virtual status_t Revert() = 0;
virtual bool RevertPossible() = 0;
virtual status_t Defaults() = 0;
virtual bool DefaultsPossible() = 0;
virtual bool UseDefaultRevertButtons() = 0;
protected: protected:
SettingsHost* fHost; SettingsHost* fHost;
+39 -19
View File
@@ -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 2008-2009, Pier Luigi Fiorini. All Rights Reserved.
* Copyright 2004-2008, Michael Davidson. All Rights Reserved. * Copyright 2004-2008, Michael Davidson. All Rights Reserved.
* Copyright 2004-2007, Mikael Eiman. All Rights Reserved. * Copyright 2004-2007, Mikael Eiman. All Rights Reserved.
@@ -9,6 +9,7 @@
* Michael Davidson, [email protected] * Michael Davidson, [email protected]
* Mikael Eiman, [email protected] * Mikael Eiman, [email protected]
* Pier Luigi Fiorini, [email protected] * Pier Luigi Fiorini, [email protected]
* Brian Hill, [email protected]
*/ */
#include <algorithm> #include <algorithm>
@@ -22,21 +23,24 @@
#include "NotificationWindow.h" #include "NotificationWindow.h"
#include "NotificationView.h" #include "NotificationView.h"
const float kCloseSize = 6;
static const int kHeaderSize = 23; const float kEdgePadding = 2;
AppGroupView::AppGroupView(NotificationWindow* win, const char* label) AppGroupView::AppGroupView(const BMessenger& messenger, const char* label)
: :
BGroupView("appGroup", B_VERTICAL, 0), BGroupView("appGroup", B_VERTICAL, 0),
fLabel(label), fLabel(label),
fParent(win), fMessenger(messenger),
fCollapsed(false), fCollapsed(false),
fCloseClicked(false) fCloseClicked(false),
fPreviewModeOn(false)
{ {
SetFlags(Flags() | B_WILL_DRAW); SetFlags(Flags() | B_WILL_DRAW);
static_cast<BGroupLayout*>(GetLayout())->SetInsets(0, kHeaderSize, 0, 0); fHeaderSize = be_plain_font->Size()
+ be_control_look->ComposeSpacing(B_USE_ITEM_SPACING);
static_cast<BGroupLayout*>(GetLayout())->SetInsets(0, fHeaderSize, 0, 0);
} }
@@ -47,7 +51,7 @@ AppGroupView::Draw(BRect updateRect)
BRect bounds = Bounds(); BRect bounds = Bounds();
rgb_color hilite = tint_color(menuColor, B_DARKEN_1_TINT); rgb_color hilite = tint_color(menuColor, B_DARKEN_1_TINT);
rgb_color vlight = tint_color(menuColor, B_LIGHTEN_2_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 // Draw the header background
SetHighColor(tint_color(menuColor, 1.22)); SetHighColor(tint_color(menuColor, 1.22));
@@ -55,18 +59,17 @@ AppGroupView::Draw(BRect updateRect)
StrokeLine(bounds.LeftTop(), bounds.LeftBottom()); StrokeLine(bounds.LeftTop(), bounds.LeftBottom());
uint32 borders = BControlLook::B_TOP_BORDER uint32 borders = BControlLook::B_TOP_BORDER
| BControlLook::B_BOTTOM_BORDER | BControlLook::B_RIGHT_BORDER; | BControlLook::B_BOTTOM_BORDER | BControlLook::B_RIGHT_BORDER;
be_control_look->DrawButtonBackground(this, bounds, bounds, menuColor, be_control_look->DrawButtonBackground(this, bounds, bounds, menuColor,
0, borders); 0, borders);
// Draw the buttons // Draw the buttons
fCollapseRect.top = (kHeaderSize - kExpandSize) / 2; fCollapseRect.top = (fHeaderSize - kExpandSize) / 2;
fCollapseRect.left = kEdgePadding * 3; fCollapseRect.left = kEdgePadding * 3;
fCollapseRect.right = fCollapseRect.left + 1.5 * kExpandSize; fCollapseRect.right = fCollapseRect.left + 1.5 * kExpandSize;
fCollapseRect.bottom = fCollapseRect.top + kExpandSize; fCollapseRect.bottom = fCollapseRect.top + kExpandSize;
fCloseRect = bounds; 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 // Take off the 1 to line this up with the close button on the
// notification view // notification view
fCloseRect.right -= kEdgePadding * 3 - 1; fCloseRect.right -= kEdgePadding * 3 - 1;
@@ -89,7 +92,9 @@ AppGroupView::Draw(BRect updateRect)
if (fCollapsed) if (fCollapsed)
label << " (" << fInfo.size() << ")"; label << " (" << fInfo.size() << ")";
SetFont(be_bold_font); BFont boldFont(be_plain_font);
boldFont.SetFace(B_BOLD_FACE);
SetFont(&boldFont);
font_height fontHeight; font_height fontHeight;
GetFontHeight(&fontHeight); GetFontHeight(&fontHeight);
float y = (bounds.top + bounds.bottom - ceilf(fontHeight.ascent) float y = (bounds.top + bounds.bottom - ceilf(fontHeight.ascent)
@@ -132,6 +137,10 @@ AppGroupView::_DrawCloseButton(const BRect& updateRect)
void void
AppGroupView::MouseDown(BPoint point) AppGroupView::MouseDown(BPoint point)
{ {
// Preview Mode ignores any mouse clicks
if (fPreviewModeOn)
return;
if (BRect(fCloseRect).InsetBySelf(-5, -5).Contains(point)) { if (BRect(fCloseRect).InsetBySelf(-5, -5).Contains(point)) {
int32 children = fInfo.size(); int32 children = fInfo.size();
for (int32 i = 0; i < children; i++) { for (int32 i = 0; i < children; i++) {
@@ -144,7 +153,7 @@ AppGroupView::MouseDown(BPoint point)
// Remove ourselves from the parent view // Remove ourselves from the parent view
BMessage message(kRemoveGroupView); BMessage message(kRemoveGroupView);
message.AddPointer("view", this); message.AddPointer("view", this);
fParent->PostMessage(&message); fMessenger.SendMessage(&message);
} else if (BRect(fCollapseRect).InsetBySelf(-5, -5).Contains(point)) { } else if (BRect(fCollapseRect).InsetBySelf(-5, -5).Contains(point)) {
fCollapsed = !fCollapsed; fCollapsed = !fCollapsed;
int32 children = fInfo.size(); int32 children = fInfo.size();
@@ -186,13 +195,13 @@ AppGroupView::MessageReceived(BMessage* msg)
view->RemoveSelf(); view->RemoveSelf();
delete view; delete view;
fParent->PostMessage(msg); fMessenger.SendMessage(msg);
if (!this->HasChildren()) { if (!this->HasChildren()) {
Hide(); Hide();
BMessage removeSelfMessage(kRemoveGroupView); BMessage removeSelfMessage(kRemoveGroupView);
removeSelfMessage.AddPointer("view", this); removeSelfMessage.AddPointer("view", this);
fParent->PostMessage(&removeSelfMessage); fMessenger.SendMessage(&removeSelfMessage);
} }
break; break;
@@ -211,17 +220,13 @@ AppGroupView::AddInfo(NotificationView* view)
if (id.Length() > 0) { if (id.Length() > 0) {
int32 children = fInfo.size(); int32 children = fInfo.size();
for (int32 i = 0; i < children; i++) { for (int32 i = 0; i < children; i++) {
if (id == fInfo[i]->MessageID()) { if (id == fInfo[i]->MessageID()) {
NotificationView* oldView = fInfo[i]; NotificationView* oldView = fInfo[i];
fParent->NotificationViewSwapped(oldView, view);
oldView->RemoveSelf(); oldView->RemoveSelf();
delete oldView; delete oldView;
fInfo[i] = view; fInfo[i] = view;
found = true; found = true;
break; break;
} }
} }
@@ -246,6 +251,13 @@ AppGroupView::AddInfo(NotificationView* view)
} }
void
AppGroupView::SetPreviewModeOn(bool enabled)
{
fPreviewModeOn = enabled;
}
const BString& const BString&
AppGroupView::Group() const AppGroupView::Group() const
{ {
@@ -253,6 +265,14 @@ AppGroupView::Group() const
} }
void
AppGroupView::SetGroup(const char* group)
{
fLabel.SetTo(group);
Invalidate();
}
bool bool
AppGroupView::HasChildren() AppGroupView::HasChildren()
{ {
+8 -3
View File
@@ -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 2008-2009, Pier Luigi Fiorini. All Rights Reserved.
* Copyright 2004-2008, Michael Davidson. All Rights Reserved. * Copyright 2004-2008, Michael Davidson. All Rights Reserved.
* Copyright 2004-2007, Mikael Eiman. All Rights Reserved. * Copyright 2004-2007, Mikael Eiman. All Rights Reserved.
@@ -11,6 +11,7 @@
#include <vector> #include <vector>
#include <GroupView.h> #include <GroupView.h>
#include <Messenger.h>
#include <String.h> #include <String.h>
class BGroupView; class BGroupView;
@@ -22,7 +23,7 @@ typedef std::vector<NotificationView*> infoview_t;
class AppGroupView : public BGroupView { class AppGroupView : public BGroupView {
public: public:
AppGroupView(NotificationWindow* win, const char* label); AppGroupView(const BMessenger& messenger, const char* label);
virtual void MouseDown(BPoint point); virtual void MouseDown(BPoint point);
virtual void MessageReceived(BMessage* msg); virtual void MessageReceived(BMessage* msg);
@@ -32,19 +33,23 @@ public:
int32 ChildrenCount(); int32 ChildrenCount();
void AddInfo(NotificationView* view); void AddInfo(NotificationView* view);
void SetPreviewModeOn(bool enabled);
const BString& Group() const; const BString& Group() const;
void SetGroup(const char* group);
private: private:
void _DrawCloseButton(const BRect& updateRect); void _DrawCloseButton(const BRect& updateRect);
BString fLabel; BString fLabel;
NotificationWindow* fParent; BMessenger fMessenger;
infoview_t fInfo; infoview_t fInfo;
bool fCollapsed; bool fCollapsed;
BRect fCloseRect; BRect fCloseRect;
BRect fCollapseRect; BRect fCollapseRect;
float fHeaderSize;
bool fCloseClicked; bool fCloseClicked;
bool fPreviewModeOn;
}; };
#endif // _APP_GROUP_VIEW_H #endif // _APP_GROUP_VIEW_H
+20 -77
View File
@@ -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 2008-2009, Pier Luigi Fiorini. All Rights Reserved.
* Copyright 2004-2008, Michael Davidson. All Rights Reserved. * Copyright 2004-2008, Michael Davidson. All Rights Reserved.
* Copyright 2004-2007, Mikael Eiman. All Rights Reserved. * Copyright 2004-2007, Mikael Eiman. All Rights Reserved.
@@ -9,6 +9,7 @@
* Michael Davidson, [email protected] * Michael Davidson, [email protected]
* Mikael Eiman, [email protected] * Mikael Eiman, [email protected]
* Pier Luigi Fiorini, [email protected] * Pier Luigi Fiorini, [email protected]
* Brian Hill, [email protected]
*/ */
#include <Message.h> #include <Message.h>
@@ -21,28 +22,22 @@ const type_code kTypeCode = 'ipau';
AppUsage::AppUsage() AppUsage::AppUsage()
: :
fName(""), fAppName(""),
fSignature(""),
fAllow(true) 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) fAllow(allow)
{ {
} }
AppUsage::~AppUsage()
{
notification_t::iterator nIt;
for (nIt = fNotifications.begin(); nIt != fNotifications.end(); nIt++)
delete nIt->second;
}
bool bool
AppUsage::AllowsTypeCode(type_code code) const AppUsage::AllowsTypeCode(type_code code) const
{ {
@@ -54,13 +49,10 @@ status_t
AppUsage::Flatten(void* buffer, ssize_t numBytes) const AppUsage::Flatten(void* buffer, ssize_t numBytes) const
{ {
BMessage msg; BMessage msg;
msg.AddString("signature", fName); msg.AddString("name", fAppName);
msg.AddString("signature", fSignature);
msg.AddBool("allow", fAllow); 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()) if (numBytes < msg.FlattenedSize())
return B_ERROR; return B_ERROR;
@@ -72,13 +64,10 @@ ssize_t
AppUsage::FlattenedSize() const AppUsage::FlattenedSize() const
{ {
BMessage msg; BMessage msg;
msg.AddString("signature", fName); msg.AddString("name", fAppName);
msg.AddString("signature", fSignature);
msg.AddBool("allow", fAllow); 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(); return msg.FlattenedSize();
} }
@@ -110,23 +99,9 @@ AppUsage::Unflatten(type_code code, const void* buffer,
status = msg.Unflatten((const char*)buffer); status = msg.Unflatten((const char*)buffer);
if (status == B_OK) { if (status == B_OK) {
msg.FindString("signature", &fName); msg.FindString("name", &fAppName);
msg.FindString("signature", &fSignature);
msg.FindBool("allow", &fAllow); 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; return status;
@@ -134,30 +109,16 @@ AppUsage::Unflatten(type_code code, const void* buffer,
const char* const char*
AppUsage::Name() AppUsage::AppName()
{ {
return fName.String(); return fAppName.String();
} }
bool const char*
AppUsage::Allowed(const char* title, notification_type type) AppUsage::Signature()
{ {
bool allowed = fAllow; return fSignature.String();
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;
} }
@@ -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 void
AppUsage::AddNotification(NotificationReceived* notification) AppUsage::SetAllowed(bool allow)
{ {
fNotifications[notification->Title()] = notification; fAllow = allow;
} }
@@ -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. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
@@ -11,9 +11,11 @@
#include <stdlib.h> #include <stdlib.h>
#include <Alert.h>
#include <Beep.h> #include <Beep.h>
#include <Notifications.h> #include <Notifications.h>
#include <PropertyInfo.h> #include <PropertyInfo.h>
#include <Roster.h>
#include "NotificationWindow.h" #include "NotificationWindow.h"
@@ -56,9 +58,8 @@ NotificationServer::MessageReceived(BMessage* message)
if (!fWindow) if (!fWindow)
return; return;
int32 type = 0;
// Emit a sound for this event // Emit a sound for this event
int32 type = 0;
if (message->FindInt32("type", &type) == B_OK) { if (message->FindInt32("type", &type) == B_OK) {
if (type < (int32)(sizeof(kSoundNames) / sizeof(const char*))) if (type < (int32)(sizeof(kSoundNames) / sizeof(const char*)))
system_beep(kSoundNames[type]); system_beep(kSoundNames[type]);
@@ -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. * Distributed under the terms of the MIT License.
*/ */
#ifndef _NOTIFICATION_SERVER_H #ifndef _NOTIFICATION_SERVER_H
+40 -25
View File
@@ -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 2008-2009, Pier Luigi Fiorini. All Rights Reserved.
* Copyright 2004-2008, Michael Davidson. All Rights Reserved. * Copyright 2004-2008, Michael Davidson. All Rights Reserved.
* Copyright 2004-2007, Mikael Eiman. All Rights Reserved. * Copyright 2004-2007, Mikael Eiman. All Rights Reserved.
@@ -11,6 +11,7 @@
* Pier Luigi Fiorini, [email protected] * Pier Luigi Fiorini, [email protected]
* Stephan Aßmus <[email protected]> * Stephan Aßmus <[email protected]>
* Adrien Destugues <[email protected]> * Adrien Destugues <[email protected]>
* Brian Hill, [email protected]
*/ */
@@ -35,7 +36,10 @@
#include "NotificationWindow.h" #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[] = { property_info message_prop_list[] = {
{ "type", {B_GET_PROPERTY, B_SET_PROPERTY, 0}, { "type", {B_GET_PROPERTY, B_SET_PROPERTY, 0},
@@ -54,23 +58,22 @@ property_info message_prop_list[] = {
}; };
NotificationView::NotificationView(NotificationWindow* win, NotificationView::NotificationView(BNotification* notification, bigtime_t timeout,
BNotification* notification, bigtime_t timeout) float iconSize, bool disableTimeout)
: :
BView("NotificationView", B_WILL_DRAW), BView("NotificationView", B_WILL_DRAW),
fParent(win),
fNotification(notification), fNotification(notification),
fTimeout(timeout), fTimeout(timeout),
fIconSize(iconSize),
fDisableTimeout(disableTimeout),
fRunner(NULL), fRunner(NULL),
fBitmap(NULL), fBitmap(NULL),
fCloseClicked(false) fCloseClicked(false),
fPreviewModeOn(false)
{ {
if (fNotification->Icon() != NULL) if (fNotification->Icon() != NULL)
fBitmap = new BBitmap(fNotification->Icon()); fBitmap = new BBitmap(fNotification->Icon());
if (fTimeout <= 0)
fTimeout = fParent->Timeout() * 1000000;
BGroupLayout* layout = new BGroupLayout(B_VERTICAL); BGroupLayout* layout = new BGroupLayout(B_VERTICAL);
SetLayout(layout); SetLayout(layout);
@@ -122,11 +125,12 @@ void
NotificationView::AttachedToWindow() NotificationView::AttachedToWindow()
{ {
SetText(); SetText();
BMessage msg(kRemoveView); if (!fDisableTimeout) {
msg.AddPointer("view", this); BMessage msg(kRemoveView);
msg.AddPointer("view", this);
fRunner = new BMessageRunner(BMessenger(Parent()), &msg, fTimeout, 1); fRunner = new BMessageRunner(BMessenger(Parent()), &msg, fTimeout, 1);
}
} }
@@ -238,9 +242,6 @@ NotificationView::Draw(BRect updateRect)
SetDrawingMode(B_OP_ALPHA); SetDrawingMode(B_OP_ALPHA);
SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY); SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
// Icon size
float iconSize = (float)fParent->IconSize();
BRect stripeRect = Bounds(); BRect stripeRect = Bounds();
stripeRect.right = kIconStripeWidth; stripeRect.right = kIconStripeWidth;
SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR),
@@ -258,7 +259,7 @@ NotificationView::Draw(BRect updateRect)
// Draw icon // Draw icon
if (fBitmap) { if (fBitmap) {
float ix = 18; float ix = 18;
float iy = (Bounds().Height() - iconSize) / 4.0; float iy = (Bounds().Height() - fIconSize) / 4.0;
// Icon is vertically centered in view // Icon is vertically centered in view
if (fNotification->Type() == B_PROGRESS_NOTIFICATION) if (fNotification->Type() == B_PROGRESS_NOTIFICATION)
@@ -267,7 +268,7 @@ NotificationView::Draw(BRect updateRect)
iy -= (progRect.Height() + kEdgePadding); 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); DrawBitmapAsync(fBitmap, fBitmap->Bounds(), iconRect);
} }
@@ -279,9 +280,10 @@ NotificationView::Draw(BRect updateRect)
SetFont(&l->font); SetFont(&l->font);
// Truncate the string. We have already line-wrapped the text but if // Truncate the string. We have already line-wrapped the text but if
// there is a very long 'word' we can only truncate it. // 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); 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<AppGroupView*>(Parent()); AppGroupView* groupView = dynamic_cast<AppGroupView*>(Parent());
@@ -333,6 +335,10 @@ NotificationView::_DrawCloseButton(const BRect& updateRect)
void void
NotificationView::MouseDown(BPoint point) NotificationView::MouseDown(BPoint point)
{ {
// Preview Mode ignores any mouse clicks
if (fPreviewModeOn)
return;
int32 buttons; int32 buttons;
Window()->CurrentMessage()->FindInt32("buttons", &buttons); Window()->CurrentMessage()->FindInt32("buttons", &buttons);
@@ -447,20 +453,22 @@ NotificationView::SetText(float newMaxWidth)
float iconRight = kIconStripeWidth; float iconRight = kIconStripeWidth;
if (fBitmap != NULL) if (fBitmap != NULL)
iconRight += fParent->IconSize(); iconRight += fIconSize;
else else
iconRight += 32; iconRight += 32;
BFont boldFont(be_plain_font);
boldFont.SetFace(B_BOLD_FACE);
font_height fh; font_height fh;
be_bold_font->GetHeight(&fh); boldFont.GetHeight(&fh);
float fontHeight = ceilf(fh.leading) + ceilf(fh.descent) float fontHeight = ceilf(fh.leading) + ceilf(fh.descent)
+ ceilf(fh.ascent); + ceilf(fh.ascent);
float y = 2 * fontHeight; float y = fontHeight + kEdgePadding * 2;
// Title // Title
LineInfo* titleLine = new LineInfo; LineInfo* titleLine = new LineInfo;
titleLine->text = fNotification->Title(); titleLine->text = fNotification->Title();
titleLine->font = *be_bold_font; titleLine->font = boldFont;
titleLine->location = BPoint(iconRight + kEdgePadding, y); titleLine->location = BPoint(iconRight + kEdgePadding, y);
@@ -548,6 +556,13 @@ NotificationView::SetText(float newMaxWidth)
} }
void
NotificationView::SetPreviewModeOn(bool enabled)
{
fPreviewModeOn = enabled;
}
const char* const char*
NotificationView::MessageID() const NotificationView::MessageID() const
{ {
+10 -7
View File
@@ -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 2008-2009, Pier Luigi Fiorini. All Rights Reserved.
* Copyright 2004-2008, Michael Davidson. All Rights Reserved. * Copyright 2004-2008, Michael Davidson. All Rights Reserved.
* Copyright 2004-2007, Mikael Eiman. All Rights Reserved. * Copyright 2004-2007, Mikael Eiman. All Rights Reserved.
@@ -18,16 +18,16 @@ class BBitmap;
class BMessageRunner; class BMessageRunner;
class BNotification; class BNotification;
class NotificationWindow;
const uint32 kRemoveView = 'ReVi'; const uint32 kRemoveView = 'ReVi';
const float kExpandSize = 8;
const float kPenSize = 1;
class NotificationView : public BView { class NotificationView : public BView {
public: public:
NotificationView(NotificationWindow* win, NotificationView(BNotification* notification,
BNotification* notification, bigtime_t timeout, float iconSize,
bigtime_t timeout = -1); bool disableTimeout = false);
virtual ~NotificationView(); virtual ~NotificationView();
virtual void AttachedToWindow(); virtual void AttachedToWindow();
@@ -47,6 +47,7 @@ public:
virtual status_t GetSupportedSuites(BMessage* msg); virtual status_t GetSupportedSuites(BMessage* msg);
void SetText(float newMaxWidth = -1); void SetText(float newMaxWidth = -1);
void SetPreviewModeOn(bool enabled);
const char* MessageID() const; const char* MessageID() const;
@@ -62,9 +63,10 @@ private:
typedef std::list<LineInfo*> LineInfoList; typedef std::list<LineInfo*> LineInfoList;
NotificationWindow* fParent;
BNotification* fNotification; BNotification* fNotification;
bigtime_t fTimeout; bigtime_t fTimeout;
float fIconSize;
bool fDisableTimeout;
BMessageRunner* fRunner; BMessageRunner* fRunner;
@@ -73,6 +75,7 @@ private:
float fHeight; float fHeight;
rgb_color fStripeColor; rgb_color fStripeColor;
bool fCloseClicked; bool fCloseClicked;
bool fPreviewModeOn;
}; };
#endif // _NOTIFICATION_VIEW_H #endif // _NOTIFICATION_VIEW_H
+56 -146
View File
@@ -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 2008-2009, Pier Luigi Fiorini. All Rights Reserved.
* Copyright 2004-2008, Michael Davidson. All Rights Reserved. * Copyright 2004-2008, Michael Davidson. All Rights Reserved.
* Copyright 2004-2007, Mikael Eiman. All Rights Reserved. * Copyright 2004-2007, Mikael Eiman. All Rights Reserved.
@@ -9,6 +9,7 @@
* Michael Davidson, [email protected] * Michael Davidson, [email protected]
* Mikael Eiman, [email protected] * Mikael Eiman, [email protected]
* Pier Luigi Fiorini, [email protected] * Pier Luigi Fiorini, [email protected]
* Brian Hill, [email protected]
*/ */
#include "NotificationWindow.h" #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() NotificationWindow::NotificationWindow()
: :
BWindow(BRect(0, 0, -1, -1), B_TRANSLATE_MARK("Notification"), BWindow(BRect(0, 0, -1, -1), B_TRANSLATE_MARK("Notification"),
B_BORDERED_WINDOW_LOOK, B_FLOATING_ALL_WINDOW_FEEL, B_AVOID_FRONT 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_AVOID_FOCUS | B_NOT_CLOSABLE | B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE
| B_NOT_RESIZABLE | B_NOT_MOVABLE | B_AUTO_UPDATE_SIZE_LIMITS, | 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)); SetLayout(new BGroupLayout(B_VERTICAL, 0));
_LoadSettings(true); _LoadSettings(true);
@@ -126,62 +129,38 @@ NotificationWindow::MessageReceived(BMessage* message)
_LoadSettings(); _LoadSettings();
break; 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: case kNotificationMessage:
{ {
if (!fShouldRun)
break;
BMessage reply(B_REPLY); BMessage reply(B_REPLY);
BNotification* notification = new BNotification(message); BNotification* notification = new BNotification(message);
if (notification->InitCheck() == B_OK) { if (notification->InitCheck() == B_OK) {
bigtime_t timeout; bigtime_t timeout;
if (message->FindInt64("timeout", &timeout) != B_OK) if (message->FindInt64("timeout", &timeout) != B_OK)
timeout = -1; timeout = fTimeout;
BMessenger messenger = message->ReturnAddress(); BString sourceSignature(notification->SourceSignature());
app_info info; BString sourceName(notification->SourceName());
if (messenger.IsValid())
be_roster->GetRunningAppInfo(messenger.Team(), &info);
else
be_roster->GetAppInfo("application/x-vnd.Be-SHEL", &info);
bool allow = false; 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()) { if (it == fAppFilters.end()) {
AppUsage* appUsage = new AppUsage(notification->Group(), if (sourceSignature.Length() > 0
true); && sourceName.Length() > 0) {
appUsage = new AppUsage(sourceName.String(),
appUsage->Allowed(notification->Title(), sourceSignature.String(), true);
notification->Type()); fAppFilters[sourceSignature.String()] = appUsage;
fAppFilters[info.signature] = appUsage; // TODO save back to settings file
}
allow = true; allow = true;
} else { } else {
allow = it->second->Allowed(notification->Title(), appUsage = it->second;
notification->Type()); allow = appUsage->Allowed();
} }
if (allow) { if (allow) {
@@ -196,8 +175,8 @@ NotificationWindow::MessageReceived(BMessage* message)
} else } else
group = aIt->second; group = aIt->second;
NotificationView* view = new NotificationView(this, NotificationView* view = new NotificationView(notification,
notification, timeout); timeout, fIconSize);
group->AddInfo(view); group->AddInfo(view);
@@ -214,18 +193,6 @@ NotificationWindow::MessageReceived(BMessage* message)
message->SendReply(&reply); message->SendReply(&reply);
break; 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: case kRemoveGroupView:
{ {
AppGroupView* view = NULL; 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 icon_size
NotificationWindow::IconSize() 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 void
NotificationWindow::SetPosition() NotificationWindow::SetPosition()
{ {
@@ -362,7 +272,8 @@ NotificationWindow::SetPosition()
float bottomOffset = bounds.bottom - Frame().bottom; float bottomOffset = bounds.bottom - Frame().bottom;
// Size of the borders around the window // 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... // If we can't guess, don't move...
BDeskbar deskbar; BDeskbar deskbar;
@@ -414,7 +325,7 @@ NotificationWindow::_LoadSettings(bool startMonitor)
path.Append(kSettingsFile); path.Append(kSettingsFile);
BFile file(path.Path(), B_READ_ONLY); BFile file(path.Path(), B_READ_ONLY | B_CREATE_FILE);
settings.Unflatten(&file); settings.Unflatten(&file);
_LoadGeneralSettings(settings); _LoadGeneralSettings(settings);
@@ -428,10 +339,10 @@ NotificationWindow::_LoadSettings(bool startMonitor)
if (watch_node(&nref, B_WATCH_ALL, BMessenger(this)) != B_OK) { if (watch_node(&nref, B_WATCH_ALL, BMessenger(this)) != B_OK) {
BAlert* alert = new BAlert(B_TRANSLATE("Warning"), BAlert* alert = new BAlert(B_TRANSLATE("Warning"),
B_TRANSLATE("Couldn't start general settings monitor.\n" B_TRANSLATE("Couldn't start general settings monitor.\n"
"Live filter changes disabled."), B_TRANSLATE("OK")); "Live filter changes disabled."), B_TRANSLATE("OK"));
alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 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++) { for (int32 i = 0; i < count; i++) {
AppUsage* app = new AppUsage(); AppUsage* app = new AppUsage();
settings.FindFlat("app_usage", i, app); if (settings.FindFlat("app_usage", i, app) == B_OK)
fAppFilters[app->Name()] = app; fAppFilters[app->Signature()] = app;
else
delete app;
} }
} }
@@ -457,22 +370,18 @@ NotificationWindow::_LoadAppFilters(BMessage& settings)
void void
NotificationWindow::_LoadGeneralSettings(BMessage& settings) NotificationWindow::_LoadGeneralSettings(BMessage& settings)
{ {
bool shouldRun; if (settings.FindBool(kAutoStartName, &fShouldRun) == B_OK) {
if (settings.FindBool(kAutoStartName, &shouldRun) == B_OK) { if (fShouldRun == false) {
if (shouldRun == false) {
// We should not start. Quit the app! // We should not start. Quit the app!
be_app_messenger.SendMessage(B_QUIT_REQUESTED); be_app_messenger.SendMessage(B_QUIT_REQUESTED);
} }
} } else
fShouldRun = true;
if (settings.FindInt32(kTimeoutName, &fTimeout) != B_OK) if (settings.FindInt32(kTimeoutName, &fTimeout) != B_OK)
fTimeout = kDefaultTimeout; fTimeout = kDefaultTimeout;
fTimeout *= 1000000;
// Notify the view about the change // Convert from seconds to microseconds
views_t::iterator it;
for (it = fViews.begin(); it != fViews.end(); ++it) {
NotificationView* view = (*it);
view->Invalidate();
}
} }
@@ -480,21 +389,22 @@ void
NotificationWindow::_LoadDisplaySettings(BMessage& settings) NotificationWindow::_LoadDisplaySettings(BMessage& settings)
{ {
int32 setting; int32 setting;
float originalWidth = fWidth;
if (settings.FindFloat(kWidthName, &fWidth) != B_OK) if (settings.FindFloat(kWidthName, &fWidth) != B_OK)
fWidth = kDefaultWidth; fWidth = kDefaultWidth;
GetLayout()->SetExplicitMaxSize(BSize(fWidth, B_SIZE_UNSET)); if (originalWidth != fWidth)
GetLayout()->SetExplicitMinSize(BSize(fWidth, B_SIZE_UNSET)); GetLayout()->SetExplicitSize(BSize(fWidth, B_SIZE_UNSET));
if (settings.FindInt32(kIconSizeName, &setting) != B_OK) if (settings.FindInt32(kIconSizeName, &setting) != B_OK)
fIconSize = kDefaultIconSize; fIconSize = kDefaultIconSize;
else else
fIconSize = (icon_size)setting; fIconSize = (icon_size)setting;
// Notify the view about the change // Notify the views about the change
views_t::iterator it; appview_t::iterator aIt;
for (it = fViews.begin(); it != fViews.end(); ++it) { for (aIt = fAppViews.begin(); aIt != fAppViews.end(); ++aIt) {
NotificationView* view = (*it); AppGroupView* view = aIt->second;
view->Invalidate(); view->Invalidate();
} }
} }
+5 -20
View File
@@ -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 2008-2009, Pier Luigi Fiorini. All Rights Reserved.
* Copyright 2004-2008, Michael Davidson. All Rights Reserved. * Copyright 2004-2008, Michael Davidson. All Rights Reserved.
* Copyright 2004-2007, Mikael Eiman. All Rights Reserved. * Copyright 2004-2007, Mikael Eiman. All Rights Reserved.
@@ -13,6 +13,7 @@
#include <map> #include <map>
#include <AppFileInfo.h> #include <AppFileInfo.h>
#include <Path.h>
#include <String.h> #include <String.h>
#include <Window.h> #include <Window.h>
@@ -26,13 +27,6 @@ struct property_info;
typedef std::map<BString, AppGroupView*> appview_t; typedef std::map<BString, AppGroupView*> appview_t;
typedef std::map<BString, AppUsage*> appfilter_t; typedef std::map<BString, AppUsage*> appfilter_t;
typedef std::vector<NotificationView*> 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'; const uint32 kRemoveGroupView = 'RGVi';
@@ -47,8 +41,6 @@ public:
virtual void WorkspaceActivated(int32, bool); virtual void WorkspaceActivated(int32, bool);
virtual void FrameResized(float width, float height); virtual void FrameResized(float width, float height);
virtual void ScreenChanged(BRect frame, color_space mode); virtual void ScreenChanged(BRect frame, color_space mode);
virtual BHandler* ResolveSpecifier(BMessage*, int32, BMessage*,
int32, const char*);
icon_size IconSize(); icon_size IconSize();
int32 Timeout(); int32 Timeout();
@@ -59,27 +51,20 @@ public:
private: private:
friend class AppGroupView; friend class AppGroupView;
void NotificationViewSwapped(
NotificationView* stale,
NotificationView* fresh);
void SetPosition(); void SetPosition();
void _LoadSettings(bool startMonitor = false); void _LoadSettings(bool startMonitor = false);
void _LoadAppFilters(BMessage& settings); void _LoadAppFilters(BMessage& settings);
void _LoadGeneralSettings(BMessage& settings); void _LoadGeneralSettings(BMessage& settings);
void _LoadDisplaySettings(BMessage& settings); void _LoadDisplaySettings(BMessage& settings);
views_t fViews;
appview_t fAppViews; appview_t fAppViews;
appfilter_t fAppFilters;
BString fStatusText;
BString fMessageText;
float fWidth; float fWidth;
icon_size fIconSize; icon_size fIconSize;
int32 fTimeout; int32 fTimeout;
bool fShouldRun;
appfilter_t fAppFilters; BPath fCachePath;
}; };
extern property_info main_prop_list[]; extern property_info main_prop_list[];