Ticket #13713: notifications.patch

File notifications.patch, 88.8 KB (added by perelandra, 7 years ago)

patch again master branch hrev51425

  • headers/os/app/Notification.h

    From c3981b09a26aac20ffb0b9d9afc6a0cec9936cc0 Mon Sep 17 00:00:00 2001
    From: Brian Hill <supernova@tycho.email>
    Date: Thu, 14 Sep 2017 22:49:47 -0400
    Subject: [PATCH] Proposed notification changes
    
    ---
     headers/os/app/Notification.h                      |   7 +-
     headers/private/notification/AppUsage.h            |  19 +-
     headers/private/notification/Notifications.h       |  17 +-
     src/kits/app/Notification.cpp                      |  53 ++-
     src/preferences/notifications/AppRefFilter.cpp     |  64 ++++
     src/preferences/notifications/AppRefFilter.h       |  21 ++
     src/preferences/notifications/DisplayView.cpp      | 152 ---------
     src/preferences/notifications/DisplayView.h        |  34 --
     src/preferences/notifications/GeneralView.cpp      | 278 ++++++++++++----
     src/preferences/notifications/GeneralView.h        |  35 +-
     src/preferences/notifications/Jamfile              |  11 +-
     src/preferences/notifications/Notifications.cpp    |   2 +-
     .../notifications/NotificationsConstants.h         |  25 ++
     .../notifications/NotificationsView.cpp            | 370 +++++++++++++--------
     src/preferences/notifications/NotificationsView.h  |  50 ++-
     src/preferences/notifications/PrefletView.cpp      |  67 ++--
     src/preferences/notifications/PrefletView.h        |  17 +-
     src/preferences/notifications/PrefletWin.cpp       | 159 +++++++--
     src/preferences/notifications/PrefletWin.h         |  18 +-
     src/preferences/notifications/SettingsHost.h       |   4 +-
     src/preferences/notifications/SettingsPane.cpp     |  13 +-
     src/preferences/notifications/SettingsPane.h       |   9 +-
     src/servers/notification/AppGroupView.cpp          |  58 ++--
     src/servers/notification/AppGroupView.h            |  11 +-
     src/servers/notification/AppUsage.cpp              |  97 ++----
     src/servers/notification/NotificationServer.cpp    |   7 +-
     src/servers/notification/NotificationServer.h      |   2 +-
     src/servers/notification/NotificationView.cpp      |  65 ++--
     src/servers/notification/NotificationView.h        |  17 +-
     src/servers/notification/NotificationWindow.cpp    | 176 +++-------
     src/servers/notification/NotificationWindow.h      |  16 +-
     31 files changed, 1091 insertions(+), 783 deletions(-)
     create mode 100644 src/preferences/notifications/AppRefFilter.cpp
     create mode 100644 src/preferences/notifications/AppRefFilter.h
     delete mode 100644 src/preferences/notifications/DisplayView.cpp
     delete mode 100644 src/preferences/notifications/DisplayView.h
     create mode 100644 src/preferences/notifications/NotificationsConstants.h
    
    diff --git a/headers/os/app/Notification.h b/headers/os/app/Notification.h
    index d11e4b1..0d64505 100644
    a b  
    11/*
    2  * Copyright 2010, Haiku, Inc. All Rights Reserved.
     2 * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
    33 * Distributed under the terms of the MIT License.
    44 */
    55#ifndef _NOTIFICATION_H
    public:  
    3434    static  BArchivable*        Instantiate(BMessage* archive);
    3535    virtual status_t            Archive(BMessage* archive, bool deep = true) const;
    3636
     37            const char*         SourceSignature() const;
     38            const char*         SourceName() const;
     39
    3740            notification_type   Type() const;
    3841
    3942            const char*         Group() const;
    public:  
    7376private:
    7477            status_t            fInitStatus;
    7578
     79            BString             fSourceSignature;
     80            BString             fSourceName;
    7681            notification_type   fType;
    7782            BString             fGroup;
    7883            BString             fTitle;
  • headers/private/notification/AppUsage.h

    diff --git a/headers/private/notification/AppUsage.h b/headers/private/notification/AppUsage.h
    index 2c42961..53b419c 100644
    a b  
    11/*
    2  * Copyright 2010, Haiku, Inc. All Rights Reserved.
     2 * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
    33 * Copyright 2008-2009, Pier Luigi Fiorini. All Rights Reserved.
    44 * Copyright 2004-2008, Michael Davidson. All Rights Reserved.
    55 * Copyright 2004-2007, Mikael Eiman. All Rights Reserved.
     
    1717#include <String.h>
    1818
    1919class BMessage;
    20 class NotificationReceived;
    21 
    22 typedef std::map<BString, NotificationReceived*> notification_t;
    2320
    2421class AppUsage : public BFlattenable {
    2522public:
    2623                                        AppUsage();
    2724                                        AppUsage(const char* name,
     25                                            const char* signature,
    2826                                            bool allow = true);
    29                                         ~AppUsage();
    3027
    3128    virtual bool                        AllowsTypeCode(type_code code) const;
    3229    virtual status_t                    Flatten(void* buffer, ssize_t numBytes) const;
    public:  
    3633    virtual status_t                    Unflatten(type_code code, const void* buffer,
    3734                                            ssize_t numBytes);
    3835
    39             const char*                 Name();
    40             bool                        Allowed(const char* title, notification_type type);
     36            const char*                 AppName();
     37            const char*                 Signature();
    4138            bool                        Allowed();
    42             NotificationReceived*       NotificationAt(int32 index);
    43             int32                       Notifications();
    44             void                        AddNotification(NotificationReceived* notification);
     39            void                        SetAllowed(bool allow);
    4540
    4641private:
    47             BString                     fName;
     42            BString                     fAppName;
     43            BString                     fSignature;
    4844            bool                        fAllow;
    49             notification_t              fNotifications;
    5045};
    5146
    5247#endif  // _APP_USAGE_H
  • headers/private/notification/Notifications.h

    diff --git a/headers/private/notification/Notifications.h b/headers/private/notification/Notifications.h
    index eb4ca73..18298a4 100644
    a b  
    11/*
    2  * Copyright 2010-2014, Haiku, Inc. All Rights Reserved.
     2 * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
    33 * Distributed under the terms of the MIT License.
    44 */
    55#ifndef _NOTIFICATIONS_H
    66#define _NOTIFICATIONS_H
    77
    88#include <Mime.h>
     9#include <String.h>
    910
    1011#define kNotificationServerSignature "application/x-vnd.Haiku-notification_server"
    1112
    extern const char* kSettingsFile;  
    1819// General settings
    1920extern const char* kAutoStartName;
    2021extern const char* kTimeoutName;
     22extern const char* kWidthName;
     23extern const char* kIconSizeName;
    2124
    2225// General default settings
    2326const bool kDefaultAutoStart = true;
    2427const int32 kDefaultTimeout = 10;
    25 
    26 // Display settings
    27 extern const char* kWidthName;
    28 extern const char* kIconSizeName;
    29 extern const char* kLayoutName;
    30 
    31 // Display default settings
     28const int32 kMinimumTimeout = 3;
     29const int32 kMaximumTimeout = 30;
    3230const float kDefaultWidth = 300.0f;
     31const float kMinimumWidth = 300.0f;
     32const float kMaximumWidth = 1000.0f;
     33const int32 kWidthStep = 50;
    3334const icon_size kDefaultIconSize = B_LARGE_ICON;
    3435
    3536#endif  // _NOTIFICATIONS_H
  • src/kits/app/Notification.cpp

    diff --git a/src/kits/app/Notification.cpp b/src/kits/app/Notification.cpp
    index 1a14d5e..266aecd 100644
    a b  
    11/*
    2  * Copyright 2010, Haiku, Inc. All Rights Reserved.
     2 * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
    33 * Distributed under the terms of the MIT License.
    44 *
    55 * Authors:
    66 *      Pier Luigi Fiorini, pierluigi.fiorini@gmail.com
    77 *      Stephan Aßmus, superstippi@gmx.de
     8 *      Brian Hill, supernova@tycho.email
    89 */
    910
    1011
     
    2021#include <Bitmap.h>
    2122#include <Message.h>
    2223#include <NodeInfo.h>
     24#include <Path.h>
    2325#include <Roster.h>
    2426
    2527
    BNotification::BNotification(notification_type type)  
    3234    fFile(NULL),
    3335    fBitmap(NULL)
    3436{
     37    team_info teamInfo;
     38    get_team_info(B_CURRENT_TEAM, &teamInfo);
     39    app_info appInfo;
     40    be_roster->GetRunningAppInfo(teamInfo.team, &appInfo);
     41   
    3542    int32 iconSize = B_LARGE_ICON;
    3643    fBitmap = new BBitmap(BRect(0, 0, iconSize - 1, iconSize - 1), 0, B_RGBA32);
    3744    if (fBitmap) {
    38         team_info teamInfo;
    39         get_team_info(B_CURRENT_TEAM, &teamInfo);
    40         app_info appInfo;
    41         be_roster->GetRunningAppInfo(teamInfo.team, &appInfo);
    4245        if (BNodeInfo::GetTrackerIcon(&appInfo.ref, fBitmap,
    4346            icon_size(iconSize)) != B_OK) {
    4447            delete fBitmap;
    4548            fBitmap = NULL;
    4649        }
    4750    }
     51    fSourceSignature = appInfo.signature;
     52    BPath path(&appInfo.ref);
     53    if (path.InitCheck() == B_OK)
     54        fSourceName = path.Leaf();
    4855}
    4956
    5057
    BNotification::BNotification(BMessage* archive)  
    5663    fFile(NULL),
    5764    fBitmap(NULL)
    5865{
     66    BString appName;
     67    if (archive->FindString("_appname", &appName) == B_OK)
     68        fSourceName = appName;
     69
     70    BString signature;
     71    if (archive->FindString("_signature", &signature) == B_OK)
     72        fSourceSignature = signature;
     73
    5974    int32 type;
    6075    if (archive->FindInt32("_type", &type) == B_OK)
    6176        fType = (notification_type)type;
    BNotification::Archive(BMessage* archive, bool deep) const  
    167182    status_t status = BArchivable::Archive(archive, deep);
    168183
    169184    if (status == B_OK)
     185        status = archive->AddString("_appname", fSourceName);
     186
     187    if (status == B_OK)
     188        status = archive->AddString("_signature", fSourceSignature);
     189
     190    if (status == B_OK)
    170191        status = archive->AddInt32("_type", (int32)fType);
    171192
    172193    if (status == B_OK && Group() != NULL)
    BNotification::Archive(BMessage* archive, bool deep) const  
    220241}
    221242
    222243
     244/*! \brief Returns source application signature.
     245
     246    \return Source application signature.
     247*/
     248const char*
     249BNotification::SourceSignature() const
     250{
     251    return fSourceSignature;
     252}
     253
     254
     255/*! \brief Returns source application name.
     256
     257    \return Source application name.
     258*/
     259const char*
     260BNotification::SourceName() const
     261{
     262    return fSourceName;
     263}
     264
     265
    223266/*! \brief Notification's type.
    224267
    225268    \return A value of the notification_type enum that represents
  • new file src/preferences/notifications/AppRefFilter.cpp

    diff --git a/src/preferences/notifications/AppRefFilter.cpp b/src/preferences/notifications/AppRefFilter.cpp
    new file mode 100644
    index 0000000..43d1eb6
    - +  
     1/*
     2 * Copyright 2017, Haiku, Inc. All Rights Reserved.
     3 * Distributed under the terms of the MIT License.
     4 *
     5 * Authors:
     6 *      Brian Hill, supernova@tycho.email
     7 */
     8
     9#include "AppRefFilter.h"
     10
     11
     12/*  This class filters only applications in an open file panel */
     13AppRefFilter::AppRefFilter()
     14    :
     15    BRefFilter()
     16{
     17}
     18
     19
     20bool
     21AppRefFilter::Filter(const entry_ref *ref, BNode *node,
     22    struct stat_beos *st, const char *filetype)
     23{
     24    char* type = NULL;
     25    const char *constFileType;
     26    // resolve symlinks
     27    bool isSymlink = strcmp("application/x-vnd.Be-symlink", filetype)==0;
     28    if (isSymlink) {
     29        BEntry linkedEntry(ref, true);
     30        if (linkedEntry.InitCheck()!=B_OK)
     31            return false;
     32        BNode linkedNode(&linkedEntry);
     33        if (linkedNode.InitCheck()!=B_OK)
     34            return false;
     35        BNodeInfo linkedNodeInfo(&linkedNode);
     36        if (linkedNodeInfo.InitCheck()!=B_OK)
     37            return false;
     38        type = new char[B_ATTR_NAME_LENGTH];
     39        if (linkedNodeInfo.GetType(type)!=B_OK) {
     40            delete[] type;
     41            return false;
     42        }
     43        constFileType = type;
     44    } else
     45        constFileType = filetype;
     46
     47    bool pass = false;
     48    //folders
     49    if (strcmp("application/x-vnd.Be-directory", constFileType)==0)
     50        pass = true;
     51    //volumes
     52    else if (strcmp("application/x-vnd.Be-volume", constFileType)==0)
     53        pass = true;
     54    //apps
     55    else if (strcmp("application/x-vnd.Be-elfexecutable", constFileType)==0)
     56        pass = true;
     57    //hack for Haiku?  Some apps are defined by MIME this way
     58    else if (strcmp("application/x-vnd.be-elfexecutable", constFileType)==0)
     59        pass = true;
     60
     61    if (isSymlink)
     62        delete[] type;
     63    return pass;
     64}
  • new file src/preferences/notifications/AppRefFilter.h

    diff --git a/src/preferences/notifications/AppRefFilter.h b/src/preferences/notifications/AppRefFilter.h
    new file mode 100644
    index 0000000..df9b4f2
    - +  
     1/*
     2 * Copyright 2017, Haiku, Inc. All Rights Reserved.
     3 * Distributed under the terms of the MIT License.
     4 */
     5#ifndef EP_APPREFFILTER_H
     6#define EP_APPREFFILTER_H
     7
     8#include <FilePanel.h>
     9#include <NodeInfo.h>
     10
     11
     12class AppRefFilter : public BRefFilter {
     13public:
     14                        AppRefFilter();
     15    virtual bool        Filter(const entry_ref *ref,
     16                            BNode *node,
     17                            struct stat_beos *st,
     18                            const char *filetype);
     19};
     20
     21#endif
  • deleted file src/preferences/notifications/DisplayView.cpp

    diff --git a/src/preferences/notifications/DisplayView.cpp b/src/preferences/notifications/DisplayView.cpp
    deleted file mode 100644
    index afe02a0..0000000
    + -  
    1 /*
    2  * Copyright 2010, Haiku, Inc. All Rights Reserved.
    3  * Copyright 2009, Pier Luigi Fiorini.
    4  * Distributed under the terms of the MIT License.
    5  *
    6  * Authors:
    7  *      Pier Luigi Fiorini, pierluigi.fiorini@gmail.com
    8  */
    9 
    10 #include <stdio.h>
    11 #include <stdlib.h>
    12 
    13 #include <Alert.h>
    14 #include <Catalog.h>
    15 #include <Directory.h>
    16 #include <FindDirectory.h>
    17 #include <LayoutBuilder.h>
    18 #include <Menu.h>
    19 #include <MenuItem.h>
    20 #include <MenuField.h>
    21 #include <Message.h>
    22 #include <Mime.h>
    23 #include <Node.h>
    24 #include <Path.h>
    25 #include <SpaceLayoutItem.h>
    26 #include <TextControl.h>
    27 
    28 #include <notification/Notifications.h>
    29 
    30 #include "DisplayView.h"
    31 #include "SettingsHost.h"
    32 
    33 
    34 #undef B_TRANSLATION_CONTEXT
    35 #define B_TRANSLATION_CONTEXT "DisplayView"
    36 
    37 
    38 DisplayView::DisplayView(SettingsHost* host)
    39     :
    40     SettingsPane("display", host)
    41 {
    42     // Window width
    43     fWindowWidth = new BTextControl(B_TRANSLATE("Window width:"), NULL,
    44         new BMessage(kSettingChanged));
    45 
    46     // Icon size
    47     fIconSize = new BMenu("iconSize");
    48     fIconSize->AddItem(new BMenuItem(B_TRANSLATE("Mini icon"),
    49         new BMessage(kSettingChanged)));
    50     fIconSize->AddItem(new BMenuItem(B_TRANSLATE("Large icon"),
    51         new BMessage(kSettingChanged)));
    52     fIconSize->SetLabelFromMarked(true);
    53     fIconSizeField = new BMenuField(B_TRANSLATE("Icon size:"), fIconSize);
    54 
    55     BLayoutBuilder::Grid<>(this, B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING)
    56         .Add(fWindowWidth->CreateLabelLayoutItem(), 0, 0)
    57         .Add(fWindowWidth->CreateTextViewLayoutItem(), 1, 0)
    58         .Add(fIconSizeField->CreateLabelLayoutItem(), 0, 1)
    59         .Add(fIconSizeField->CreateMenuBarLayoutItem(), 1, 1)
    60         .AddGlue(0, 2)
    61         .SetInsets(B_USE_WINDOW_SPACING);
    62 }
    63 
    64 
    65 void
    66 DisplayView::AttachedToWindow()
    67 {
    68     fWindowWidth->SetTarget(this);
    69     fIconSize->SetTargetForItems(this);
    70 }
    71 
    72 
    73 void
    74 DisplayView::MessageReceived(BMessage* msg)
    75 {
    76     switch (msg->what) {
    77         case kSettingChanged:
    78             SettingsPane::MessageReceived(msg);
    79             break;
    80         default:
    81             BView::MessageReceived(msg);
    82     }
    83 }
    84 
    85 
    86 status_t
    87 DisplayView::Load(BMessage& settings)
    88 {
    89 #if 0
    90     BPath path;
    91 
    92     if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
    93         return B_ERROR;
    94 
    95     path.Append(kSettingsFile);
    96 
    97     BFile file(path.Path(), B_READ_ONLY);
    98     BMessage settings;
    99     settings.Unflatten(&file);
    100 #endif
    101 
    102     char buffer[255];
    103     int32 setting;
    104     BMenuItem* item = NULL;
    105 
    106     float width;
    107     if (settings.FindFloat(kWidthName, &width) != B_OK)
    108         width = kDefaultWidth;
    109     (void)sprintf(buffer, "%.2f", width);
    110     fWindowWidth->SetText(buffer);
    111 
    112     icon_size iconSize;
    113     if (settings.FindInt32(kIconSizeName, &setting) != B_OK)
    114         iconSize = kDefaultIconSize;
    115     else
    116         iconSize = (icon_size)setting;
    117     if (iconSize == B_MINI_ICON)
    118         item = fIconSize->ItemAt(0);
    119     else
    120         item = fIconSize->ItemAt(1);
    121     if (item)
    122         item->SetMarked(true);
    123 
    124     return B_OK;
    125 }
    126 
    127 
    128 status_t
    129 DisplayView::Save(BMessage& settings)
    130 {
    131     float width = atof(fWindowWidth->Text());
    132     settings.AddFloat(kWidthName, width);
    133 
    134     icon_size iconSize = kDefaultIconSize;
    135     switch (fIconSize->IndexOf(fIconSize->FindMarked())) {
    136         case 0:
    137             iconSize = B_MINI_ICON;
    138             break;
    139         default:
    140             iconSize = B_LARGE_ICON;
    141     }
    142     settings.AddInt32(kIconSizeName, (int32)iconSize);
    143 
    144     return B_OK;
    145 }
    146 
    147 
    148 status_t
    149 DisplayView::Revert()
    150 {
    151     return B_ERROR;
    152 }
  • deleted file src/preferences/notifications/DisplayView.h

    diff --git a/src/preferences/notifications/DisplayView.h b/src/preferences/notifications/DisplayView.h
    deleted file mode 100644
    index c651865..0000000
    + -  
    1 /*
    2  * Copyright 2010, Haiku, Inc. All Rights Reserved.
    3  * Copyright 2009, Pier Luigi Fiorini.
    4  * Distributed under the terms of the MIT License.
    5  */
    6 #ifndef _DISPLAY_VIEW_H
    7 #define _DISPLAY_VIEW_H
    8 
    9 #include "SettingsPane.h"
    10 
    11 class BTextControl;
    12 class BMenu;
    13 class BMenuField;
    14 
    15 class DisplayView : public SettingsPane {
    16 public:
    17                             DisplayView(SettingsHost* host);
    18 
    19     virtual void            AttachedToWindow();
    20     virtual void            MessageReceived(BMessage* msg);
    21 
    22             // SettingsPane hooks
    23             status_t        Load(BMessage&);
    24             status_t        Save(BMessage&);
    25             status_t        Revert();
    26 
    27 private:
    28             BTextControl*   fWindowWidth;
    29             BMenu*          fIconSize;
    30             BMenuField*     fIconSizeField;
    31 
    32 };
    33 
    34 #endif // _DISPLAY_VIEW_H
  • src/preferences/notifications/GeneralView.cpp

    diff --git a/src/preferences/notifications/GeneralView.cpp b/src/preferences/notifications/GeneralView.cpp
    index a11f4b9..bbd5854 100644
    a b  
    11/*
    2  * Copyright 2010-2013, Haiku, Inc. All Rights Reserved.
     2 * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
    33 * Copyright 2009, Pier Luigi Fiorini.
    44 * Distributed under the terms of the MIT License.
    55 *
    66 * Authors:
    77 *      Pier Luigi Fiorini, pierluigi.fiorini@gmail.com
     8 *      Brian Hill, supernova@tycho.email
    89 */
    910
    1011#include <stdio.h>
     
    1314#include <vector>
    1415
    1516#include <Alert.h>
     17#include <Box.h>
    1618#include <Button.h>
    1719#include <Catalog.h>
    18 #include <CheckBox.h>
    1920#include <Directory.h>
    2021#include <File.h>
    2122#include <FindDirectory.h>
     
    2627#include <Query.h>
    2728#include <Roster.h>
    2829#include <String.h>
    29 #include <StringView.h>
    3030#include <SymLink.h>
    31 #include <TextControl.h>
    3231#include <Volume.h>
    3332#include <VolumeRoster.h>
    3433
    3534#include <notification/Notifications.h>
    3635
    3736#include "GeneralView.h"
     37#include "NotificationsConstants.h"
    3838#include "SettingsHost.h"
    3939
    4040#undef B_TRANSLATION_CONTEXT
    4141#define B_TRANSLATION_CONTEXT "GeneralView"
    42 const int32 kToggleNotifications = '_TSR';
     42
     43const uint32 kToggleNotifications = '_TSR';
     44const uint32 kWidthChanged = '_WIC';
     45const uint32 kTimeoutChanged = '_TIC';
     46const uint32 kServerChangeTriggered = '_SCT';
     47const BString kSampleMessageID("NotificationsSample");
     48
    4349
    4450GeneralView::GeneralView(SettingsHost* host)
    4551    :
    46     SettingsPane("general", host)
     52    SettingsPane("general", host),
     53    fServerChangeTriggered(false)
    4754{
    48     // Notifications
     55    // Notification server
    4956    fNotificationBox = new BCheckBox("server",
    5057        B_TRANSLATE("Enable notifications"),
    5158        new BMessage(kToggleNotifications));
    52 
    53     // Autostart
    54     fAutoStart = new BCheckBox("autostart",
    55         B_TRANSLATE("Enable notifications at startup"),
    56         new BMessage(kSettingChanged));
     59    BBox* box = new BBox("box");
     60    box->SetLabel(fNotificationBox);
     61
     62    // Window width
     63    int32 minWidth = int32(kMinimumWidth / kWidthStep);
     64    int32 maxWidth = int32(kMaximumWidth / kWidthStep);
     65    fWidthSlider = new BSlider("width", B_TRANSLATE("Window width:"),
     66        new BMessage(kWidthChanged), minWidth, maxWidth, B_HORIZONTAL);
     67    fWidthSlider->SetHashMarks(B_HASH_MARKS_BOTTOM);
     68    fWidthSlider->SetHashMarkCount(maxWidth - minWidth + 1);
     69    BString minWidthLabel;
     70    minWidthLabel << int32(kMinimumWidth);
     71    BString maxWidthLabel;
     72    maxWidthLabel << int32(kMaximumWidth);
     73    fWidthSlider->SetLimitLabels(
     74        B_TRANSLATE_COMMENT(minWidthLabel.String(), "Slider low text"),
     75        B_TRANSLATE_COMMENT(maxWidthLabel.String(), "Slider high text"));
    5776
    5877    // Display time
    59     fTimeout = new BTextControl(B_TRANSLATE("Hide notifications from screen"
    60         " after"), NULL, new BMessage(kSettingChanged));
    61     BStringView* displayTimeLabel = new BStringView("dt_label",
    62         B_TRANSLATE("seconds of inactivity"));
    63 
    64     // Default position
    65     // TODO: Here will come a screen representation with the four corners
    66     // clickable
    67 
     78    fDurationSlider = new BSlider("duration", B_TRANSLATE("Duration:"),
     79        new BMessage(kTimeoutChanged), kMinimumTimeout, kMaximumTimeout,
     80        B_HORIZONTAL);
     81    fDurationSlider->SetHashMarks(B_HASH_MARKS_BOTTOM);
     82    fDurationSlider->SetHashMarkCount(kMaximumTimeout - kMinimumTimeout + 1);
     83    BString minLabel;
     84    minLabel << kMinimumTimeout;
     85    BString maxLabel;
     86    maxLabel << kMaximumTimeout;
     87    fDurationSlider->SetLimitLabels(
     88        B_TRANSLATE_COMMENT(minLabel.String(), "Slider low text"),
     89        B_TRANSLATE_COMMENT(maxLabel.String(), "Slider high text"));
     90
     91    box->AddChild(BLayoutBuilder::Group<>(B_VERTICAL)
     92        .SetInsets(B_USE_DEFAULT_SPACING)
     93        .Add(fWidthSlider)
     94        .Add(fDurationSlider)
     95        .AddGlue()
     96        .View());
     97   
    6898    BLayoutBuilder::Group<>(this, B_VERTICAL)
    69         .AddGroup(B_HORIZONTAL, B_USE_WINDOW_SPACING)
    70             .Add(fNotificationBox)
    71             .AddGlue()
    72         .End()
    73         .AddGroup(B_VERTICAL, B_USE_WINDOW_SPACING)
    74             .Add(fAutoStart)
    75             .AddGroup(B_HORIZONTAL)
    76                 .AddGroup(B_HORIZONTAL, 2)
    77                     .Add(fTimeout)
    78                     .Add(displayTimeLabel)
    79                 .End()
    80             .End()
    81         .End()
    8299        .SetInsets(B_USE_WINDOW_SPACING)
    83         .AddGlue();
     100        .Add(box)
     101    .End();
    84102}
    85103
    86104
    87105void
    88106GeneralView::AttachedToWindow()
    89107{
     108    BView::AttachedToWindow();
    90109    fNotificationBox->SetTarget(this);
    91     fAutoStart->SetTarget(this);
    92     fTimeout->SetTarget(this);
     110    fWidthSlider->SetTarget(this);
     111    fDurationSlider->SetTarget(this);
    93112}
    94113
    95114
    void  
    97116GeneralView::MessageReceived(BMessage* msg)
    98117{
    99118    switch (msg->what) {
     119        case B_SOME_APP_QUIT:
     120        case B_SOME_APP_LAUNCHED:
     121        {
     122            //Find the signature and check if it was the notification server
     123            char* sig;
     124            if (msg->FindString("be:signature", (const char**)&sig) == B_OK)
     125            {
     126                BString signature(sig);
     127                if (signature.Compare(kNotificationServerSignature) == 0)
     128                {
     129                    // If this preflet triggered the change then ignore message
     130                    if (fServerChangeTriggered) {
     131                        fServerChangeTriggered = false;
     132                        break;
     133                    }
     134                    BString text;
     135                    if (msg->what == B_SOME_APP_QUIT)
     136                        text.SetTo(B_TRANSLATE("The notification server has quit."));
     137                    else
     138                        text.SetTo(B_TRANSLATE("The notification server started."));
     139                    BAlert* alert = new BAlert("", text.String(),
     140                        B_TRANSLATE("OK"));
     141                    alert->Go(NULL);
     142                    fNotificationBox->SetValue(_IsServerRunning() ?
     143                        B_CONTROL_ON : B_CONTROL_OFF);
     144                    _EnableControls();
     145                }
     146            }
     147            break;
     148        }
    100149        case kToggleNotifications:
    101150        {
    102151            entry_ref ref;
    GeneralView::MessageReceived(BMessage* msg)  
    113162                return;
    114163            }
    115164
    116             if (fNotificationBox->Value() == B_CONTROL_OFF) {
     165            if (fNotificationBox->Value() == B_CONTROL_OFF && _IsServerRunning()) {
    117166                // Server team
    118167                team_id team = be_roster->TeamFor(kNotificationServerSignature);
    119168
    120                 // Establish a connection to infopopper_server
     169                // Establish a connection to server
    121170                status_t ret = B_ERROR;
    122171                BMessenger messenger(kNotificationServerSignature, team, &ret);
    123172                if (ret != B_OK) {
    GeneralView::MessageReceived(BMessage* msg)  
    142191                    (void)alert->Go();
    143192                    return;
    144193                }
    145             } else if (!_IsServerRunning()) {
     194                fServerChangeTriggered = true;
     195            } else if (fNotificationBox->Value() == B_CONTROL_ON && !_IsServerRunning()) {
    146196                // Start server
    147197                status_t err = be_roster->Launch(kNotificationServerSignature);
    148198                if (err != B_OK) {
    GeneralView::MessageReceived(BMessage* msg)  
    157207                    (void)alert->Go();
    158208                    return;
    159209                }
     210                fServerChangeTriggered = true;
    160211            }
     212            _EnableControls();
     213            break;
     214        }
     215        case kWidthChanged: {
     216            int32 value = fWidthSlider->Value() * 50;
     217            _SetWidthLabel(value);
     218            SettingsPane::SettingsChanged(true);
    161219            break;
    162220        }
    163         case kSettingChanged:
    164             SettingsPane::MessageReceived(msg);
     221        case kTimeoutChanged:
     222        {
     223            int32 value = fDurationSlider->Value();
     224            _SetTimeoutLabel(value);
     225            SettingsPane::SettingsChanged(true);
    165226            break;
     227        }
    166228        default:
    167229            BView::MessageReceived(msg);
    168230            break;
    GeneralView::MessageReceived(BMessage* msg)  
    173235status_t
    174236GeneralView::Load(BMessage& settings)
    175237{
    176     char buffer[255];
    177 
    178238    fNotificationBox->SetValue(_IsServerRunning() ? B_CONTROL_ON : B_CONTROL_OFF);
    179239
    180     bool autoStart;
    181     if (settings.FindBool(kAutoStartName, &autoStart) != B_OK)
    182         autoStart = kDefaultAutoStart;
    183     fAutoStart->SetValue(autoStart ? B_CONTROL_ON : B_CONTROL_OFF);
    184 
    185     int32 timeout;
    186     if (settings.FindInt32(kTimeoutName, &timeout) != B_OK)
    187         timeout = kDefaultTimeout;
    188     (void)sprintf(buffer, "%" B_PRId32, timeout);
    189     fTimeout->SetText(buffer);
    190 
    191     return B_OK;
     240    if (settings.FindFloat(kWidthName, &fOriginalWidth) != B_OK
     241        || fOriginalWidth > kMaximumWidth
     242        || fOriginalWidth < kMinimumWidth)
     243        fOriginalWidth = kDefaultWidth;
     244
     245    if (settings.FindInt32(kTimeoutName, &fOriginalTimeout) != B_OK
     246        || fOriginalTimeout > kMaximumTimeout
     247        || fOriginalTimeout < kMinimumTimeout)
     248        fOriginalTimeout = kDefaultTimeout;
     249// TODO need to save again if values outside of expected range
     250    int32 setting;
     251    if (settings.FindInt32(kIconSizeName, &setting) != B_OK)
     252        fOriginalIconSize = kDefaultIconSize;
     253    else
     254        fOriginalIconSize = (icon_size)setting;
     255
     256    _EnableControls();
     257   
     258    return Revert();
    192259}
    193260
    194261
    195262status_t
    196263GeneralView::Save(BMessage& settings)
    197264{
    198     bool autoStart = (fAutoStart->Value() == B_CONTROL_ON);
     265    bool autoStart = (fNotificationBox->Value() == B_CONTROL_ON);
    199266    settings.AddBool(kAutoStartName, autoStart);
    200267
    201     int32 timeout = atol(fTimeout->Text());
     268    int32 timeout = fDurationSlider->Value();
    202269    settings.AddInt32(kTimeoutName, timeout);
    203270
     271    float width = fWidthSlider->Value() * 50;
     272    settings.AddFloat(kWidthName, width);
     273
     274    icon_size iconSize = B_LARGE_ICON;
     275    settings.AddInt32(kIconSizeName, (int32)iconSize);
     276
    204277    return B_OK;
    205278}
    206279
    GeneralView::Save(BMessage& settings)  
    208281status_t
    209282GeneralView::Revert()
    210283{
    211     return B_ERROR;
     284    fDurationSlider->SetValue(fOriginalTimeout);
     285    _SetTimeoutLabel(fOriginalTimeout);
     286   
     287    fWidthSlider->SetValue(fOriginalWidth / 50);
     288    _SetWidthLabel(fOriginalWidth);
     289   
     290    return B_OK;
     291}
     292
     293
     294bool
     295GeneralView::RevertPossible()
     296{
     297    int32 timeout = fDurationSlider->Value();
     298    if (fOriginalTimeout != timeout)
     299        return true;
     300   
     301    int32 width = fWidthSlider->Value() * 50;
     302    if (fOriginalWidth != width)
     303        return true;
     304
     305    return false;
     306}
     307
     308
     309status_t
     310GeneralView::Defaults()
     311{
     312    fDurationSlider->SetValue(kDefaultTimeout);
     313    _SetTimeoutLabel(kDefaultTimeout);
     314
     315    fWidthSlider->SetValue(kDefaultWidth / 50);
     316    _SetWidthLabel(kDefaultWidth);
     317
     318    return B_OK;
     319}
     320
     321
     322bool
     323GeneralView::DefaultsPossible()
     324{
     325    int32 timeout = fDurationSlider->Value();
     326    if (kDefaultTimeout != timeout)
     327        return true;
     328
     329    int32 width = fWidthSlider->Value() * 50;
     330    if (kDefaultWidth != width)
     331        return true;
     332   
     333    return false;
     334}
     335
     336
     337bool
     338GeneralView::UseDefaultRevertButtons()
     339{
     340    return true;
     341}
     342
     343
     344void
     345GeneralView::_EnableControls()
     346{
     347    bool enabled = fNotificationBox->Value() == B_CONTROL_ON;
     348    fWidthSlider->SetEnabled(enabled);
     349    fDurationSlider->SetEnabled(enabled);
     350}
     351
     352
     353void
     354GeneralView::_SetTimeoutLabel(int32 value)
     355{
     356    BString label(B_TRANSLATE("Timeout:"));
     357    label.Append(" ");
     358    label << value;
     359    label.Append(" ").Append(B_TRANSLATE("seconds"));
     360    fDurationSlider->SetLabel(label.String());
     361}
     362
     363
     364void
     365GeneralView::_SetWidthLabel(int32 value)
     366{
     367    BString label(B_TRANSLATE("Width:"));
     368    label.Append(" ");
     369    label << value;
     370    label.Append(" ").Append(B_TRANSLATE("pixels"));
     371    fWidthSlider->SetLabel(label.String());
    212372}
    213373
    214374
  • src/preferences/notifications/GeneralView.h

    diff --git a/src/preferences/notifications/GeneralView.h b/src/preferences/notifications/GeneralView.h
    index 909fbd8..5f3f20b 100644
    a b  
    11/*
    2  * Copyright 2010, Haiku, Inc. All Rights Reserved.
     2 * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
    33 * Copyright 2009, Pier Luigi Fiorini.
    44 * Distributed under the terms of the MIT License.
    55 */
    66#ifndef _GENERAL_VIEW_H
    77#define _GENERAL_VIEW_H
    88
     9
     10#include <Button.h>
     11#include <CheckBox.h>
     12#include <Menu.h>
     13#include <MenuField.h>
     14#include <Mime.h>
     15#include <RadioButton.h>
     16#include <Slider.h>
     17#include <StringView.h>
     18#include <TextControl.h>
     19
    920#include "SettingsPane.h"
    1021
    11 class BCheckBox;
    12 class BStringView;
    13 class BTextControl;
    1422
    1523class GeneralView : public SettingsPane {
    1624public:
    public:  
    2331            status_t        Load(BMessage&);
    2432            status_t        Save(BMessage&);
    2533            status_t        Revert();
     34            bool            RevertPossible();
     35            status_t        Defaults();
     36            bool            DefaultsPossible();
     37            bool            UseDefaultRevertButtons();
    2638
    2739private:
    2840        BCheckBox*          fNotificationBox;
    29         BCheckBox*          fAutoStart;
    30         BTextControl*       fTimeout;
    31         BCheckBox*          fHideAll;
    32 
     41        BSlider*            fDurationSlider;
     42        BSlider*            fWidthSlider;
     43       
     44        int32               fOriginalTimeout;
     45        float               fOriginalWidth;
     46        icon_size           fOriginalIconSize;
     47        bool                fServerChangeTriggered;
     48
     49        void                _EnableControls();
     50        void                _SetWidthLabel(int32 value);
     51        void                _SetTimeoutLabel(int32 value);
    3352        bool                _CanFindServer(entry_ref* ref);
    3453        bool                _IsServerRunning();
    3554};
  • src/preferences/notifications/Jamfile

    diff --git a/src/preferences/notifications/Jamfile b/src/preferences/notifications/Jamfile
    index fe980ae..c44f1be 100644
    a b  
    11SubDir HAIKU_TOP src preferences notifications ;
    22
    3 UsePrivateHeaders shared ;
     3UseHeaders [ FDirName $(HAIKU_TOP) src servers notification ] : true ;
    44
    5 UsePrivateHeaders interface ;
     5UsePrivateHeaders interface notification ;
    66
    77Application Notifications :
     8    AppRefFilter.cpp
    89    Notifications.cpp
    910    PrefletWin.cpp
    1011    PrefletView.cpp
    1112    SettingsPane.cpp
    1213    GeneralView.cpp
    13     DisplayView.cpp
    1414    NotificationsView.cpp
    15     : be translation libcolumnlistview.a libnotification.a [ TargetLibstdc++ ] localestub
     15    ../../servers/notification/NotificationView.cpp
     16    ../../servers/notification/AppGroupView.cpp
     17    : be translation tracker libcolumnlistview.a libnotification.a [ TargetLibstdc++ ] localestub
    1618    : Notifications.rdef
    1719;
    1820
    Depends Notifications : libnotification.a ;  
    2224DoCatalogs Notifications :
    2325    x-vnd.Haiku-Notifications
    2426    :
    25     DisplayView.cpp
    2627    GeneralView.cpp
    2728    PrefletWin.cpp
    2829    PrefletView.cpp
  • src/preferences/notifications/Notifications.cpp

    diff --git a/src/preferences/notifications/Notifications.cpp b/src/preferences/notifications/Notifications.cpp
    index 208e72a..555bb2d 100644
    a b  
    11/*
    2  * Copyright 2010, Haiku, Inc. All Rights Reserved.
     2 * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
    33 * Copyright 2009, Pier Luigi Fiorini.
    44 * Distributed under the terms of the MIT License.
    55 *
  • new file src/preferences/notifications/NotificationsConstants.h

    diff --git a/src/preferences/notifications/NotificationsConstants.h b/src/preferences/notifications/NotificationsConstants.h
    new file mode 100644
    index 0000000..a02fbcb
    - +  
     1/*
     2 * Copyright 2017 Haiku Inc. All rights reserved.
     3 * Distributed under the terms of the MIT License.
     4 */
     5#ifndef NOTIFICATIONS_CONSTANTS_H
     6#define NOTIFICATIONS_CONSTANTS_H
     7
     8
     9// interface messages
     10const uint32 kDefaults = '_DFT';
     11const uint32 kRevert = '_RVT';
     12const uint32 kApply = '_APY';
     13const uint32 kApplyWithExample = '_APE';
     14const uint32 kApplicationSelected = '_ASL';
     15const uint32 kAddApplication = '_AAP';
     16const uint32 kAddApplicationRef = '_AAR';
     17const uint32 kRemoveApplication = '_RAP';
     18const uint32 kMuteChanged = '_MCH';
     19
     20// user interface
     21const float kEdgePadding = 5.0;
     22const float kCLVTitlePadding = 8.0;
     23
     24
     25#endif  /* NOTIFICATIONS_CONSTANTS_H */
  • src/preferences/notifications/NotificationsView.cpp

    diff --git a/src/preferences/notifications/NotificationsView.cpp b/src/preferences/notifications/NotificationsView.cpp
    index b5fecbd..0d8bbcd 100644
    a b  
    11/*
    2  * Copyright 2010, Haiku, Inc. All Rights Reserved.
     2 * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
    33 * Copyright 2009, Pier Luigi Fiorini.
    44 * Distributed under the terms of the MIT License.
    55 *
    66 * Authors:
    77 *      Pier Luigi Fiorini, pierluigi.fiorini@gmail.com
     8 *      Brian Hill, supernova@tycho.email
    89 */
    910
    1011#include <Alert.h>
     12#include <Button.h>
    1113#include <Catalog.h>
    1214#include <CheckBox.h>
    1315#include <ColumnListView.h>
     
    2325#include <notification/Notifications.h>
    2426#include <notification/NotificationReceived.h>
    2527
     28#include "NotificationsConstants.h"
    2629#include "NotificationsView.h"
    2730
    2831#undef B_TRANSLATION_CONTEXT
    2932#define B_TRANSLATION_CONTEXT "NotificationView"
    3033
    31 const float kEdgePadding = 5.0;
    32 const float kCLVTitlePadding = 8.0;
     34// Applications column indexes
     35const int32 kAppNameIndex = 0;
     36const int32 kAppEnabledIndex = 1;
    3337
    34 const int32 kApplicationSelected = '_ASL';
    35 const int32 kNotificationSelected = '_NSL';
    3638
    37 const int32 kCLVDeleteRow = 'av02';
     39AppRow::AppRow(const char* name, const char* signature, bool allowed)
     40    :
     41    BRow(),
     42    fName(name),
     43    fSignature(signature),
     44    fAllowed(allowed)
     45{
     46    SetField(new BStringField(fName.String()), kAppNameIndex);
     47    BString text = fAllowed ? B_TRANSLATE("Allowed") : B_TRANSLATE("Muted");
     48    SetField(new BStringField(text.String()), kAppEnabledIndex);
     49}
    3850
    39 // Applications column indexes
    40 const int32 kAppIndex = 0;
    41 const int32 kAppEnabledIndex = 1;
    4251
    43 // Notifications column indexes
    44 const int32 kTitleIndex = 0;
    45 const int32 kDateIndex = 1;
    46 const int32 kTypeIndex = 2;
    47 const int32 kAllowIndex = 3;
     52void
     53AppRow::SetAllowed(bool allowed)
     54{
     55    fAllowed = allowed;
     56    RefreshEnabledField();
     57}
    4858
    4959
    50 NotificationsView::NotificationsView(SettingsHost* host)
    51     :
    52     SettingsPane("apps", host)
     60void
     61AppRow::RefreshEnabledField()
    5362{
    54     BRect rect(0, 0, 100, 100);
     63    BStringField* field = (BStringField*)GetField(kAppEnabledIndex);
     64    BString text = fAllowed ? B_TRANSLATE("Allowed") : B_TRANSLATE("Muted");
     65    field->SetString(text.String());
     66    Invalidate();
     67}
    5568
    56     // Search application field
    57     fSearch = new BTextControl(B_TRANSLATE("Search:"), NULL,
    58         new BMessage(kSettingChanged));
    5969
     70NotificationsView::NotificationsView(SettingsHost* host)
     71    :
     72    SettingsPane("apps", host),
     73    fSelectedRow(NULL)
     74{
    6075    // Applications list
    6176    fApplications = new BColumnListView(B_TRANSLATE("Applications"),
    62         0, B_FANCY_BORDER, true);
     77        0, B_FANCY_BORDER, false);
    6378    fApplications->SetSelectionMode(B_SINGLE_SELECTION_LIST);
    64 
    65     fAppCol = new BStringColumn(B_TRANSLATE("Application"), 200,
    66         be_plain_font->StringWidth(B_TRANSLATE("Application")) +
    67         (kCLVTitlePadding * 2), rect.Width(), B_TRUNCATE_END, B_ALIGN_LEFT);
    68     fApplications->AddColumn(fAppCol, kAppIndex);
    69 
    70     fAppEnabledCol = new BStringColumn(B_TRANSLATE("Enabled"), 10,
    71         be_plain_font->StringWidth(B_TRANSLATE("Enabled")) +
    72         (kCLVTitlePadding * 2), rect.Width(), B_TRUNCATE_END, B_ALIGN_LEFT);
     79    fApplications->SetSelectionMessage(new BMessage(kApplicationSelected));
     80
     81    float colWidth = be_plain_font->StringWidth(B_TRANSLATE("Application"))
     82        + (kCLVTitlePadding * 2);
     83    fAppCol = new BStringColumn(B_TRANSLATE("Application"), colWidth * 2,
     84        colWidth, colWidth * 4, B_TRUNCATE_END, B_ALIGN_LEFT);
     85    fApplications->AddColumn(fAppCol, kAppNameIndex);
     86
     87    colWidth = be_plain_font->StringWidth(B_TRANSLATE("Status"))
     88        + (kCLVTitlePadding * 2);
     89    fAppEnabledCol = new BStringColumn(B_TRANSLATE("Status"), colWidth * 1.5,
     90        colWidth, colWidth * 3, B_TRUNCATE_END, B_ALIGN_LEFT);
    7391    fApplications->AddColumn(fAppEnabledCol, kAppEnabledIndex);
    74 
    75     // Notifications list
    76     fNotifications = new BColumnListView(B_TRANSLATE("Notifications"),
    77         0, B_FANCY_BORDER, true);
    78     fNotifications->SetSelectionMode(B_SINGLE_SELECTION_LIST);
    79 
    80     fTitleCol = new BStringColumn(B_TRANSLATE("Title"), 100,
    81         be_plain_font->StringWidth(B_TRANSLATE("Title")) +
    82         (kCLVTitlePadding * 2), rect.Width(), B_TRUNCATE_END, B_ALIGN_LEFT);
    83     fNotifications->AddColumn(fTitleCol, kTitleIndex);
    84 
    85     fDateCol = new BDateColumn(B_TRANSLATE("Last received"), 100,
    86         be_plain_font->StringWidth(B_TRANSLATE("Last received")) +
    87         (kCLVTitlePadding * 2), rect.Width(), B_ALIGN_LEFT);
    88     fNotifications->AddColumn(fDateCol, kDateIndex);
    89 
    90     fTypeCol = new BStringColumn(B_TRANSLATE("Type"), 100,
    91         be_plain_font->StringWidth(B_TRANSLATE("Type")) +
    92         (kCLVTitlePadding * 2), rect.Width(), B_TRUNCATE_END, B_ALIGN_LEFT);
    93     fNotifications->AddColumn(fTypeCol, kTypeIndex);
    94 
    95     fAllowCol = new BStringColumn(B_TRANSLATE("Allowed"), 100,
    96         be_plain_font->StringWidth(B_TRANSLATE("Allowed")) +
    97         (kCLVTitlePadding * 2), rect.Width(), B_TRUNCATE_END, B_ALIGN_LEFT);
    98     fNotifications->AddColumn(fAllowCol, kAllowIndex);
     92    fApplications->SetSortColumn(fAppCol, true, true);
     93   
     94    fAddButton = new BButton("add_app", B_TRANSLATE("Add" B_UTF8_ELLIPSIS),
     95        new BMessage(kAddApplication));
     96    fRemoveButton = new BButton("add_app", B_TRANSLATE("Remove"),
     97        new BMessage(kRemoveApplication));
     98    fRemoveButton->SetEnabled(false);
     99   
     100    fMuteAll = new BCheckBox("block", B_TRANSLATE("Mute notifications"),
     101        new BMessage(kMuteChanged));
    99102
    100103    // Add views
    101104    BLayoutBuilder::Group<>(this, B_VERTICAL)
    102105        .AddGroup(B_HORIZONTAL)
    103             .AddGlue()
    104             .Add(fSearch)
     106            .Add(fApplications)
     107            .AddGroup(B_VERTICAL)
     108                .Add(fAddButton)
     109                .Add(fRemoveButton)
     110                .AddGlue()
     111            .End()
    105112        .End()
    106         .Add(fApplications)
    107         .Add(fNotifications)
     113        .Add(fMuteAll)
    108114        .SetInsets(B_USE_WINDOW_SPACING, B_USE_WINDOW_SPACING,
    109115            B_USE_WINDOW_SPACING, B_USE_DEFAULT_SPACING);
     116
     117    // File Panel
     118    fPanelFilter = new AppRefFilter();
     119    fAddAppPanel = new BFilePanel(B_OPEN_PANEL, NULL, NULL, B_FILE_NODE, false,
     120        NULL, fPanelFilter);
     121}
     122
     123
     124NotificationsView::~NotificationsView()
     125{
     126    delete fAddAppPanel;
     127    delete fPanelFilter;
    110128}
    111129
    112130
    NotificationsView::AttachedToWindow()  
    115133{
    116134    fApplications->SetTarget(this);
    117135    fApplications->SetInvocationMessage(new BMessage(kApplicationSelected));
    118 
    119     fNotifications->SetTarget(this);
    120     fNotifications->SetInvocationMessage(new BMessage(kNotificationSelected));
    121 
    122 #if 0
    123     fNotifications->AddFilter(new BMessageFilter(B_ANY_DELIVERY,
    124         B_ANY_SOURCE, B_KEY_DOWN, CatchDelete));
    125 #endif
     136    fAddButton->SetTarget(this);
     137    fRemoveButton->SetTarget(this);
     138    fMuteAll->SetTarget(this);
     139    fAddAppPanel->SetTarget(this);
     140    _RecallItemSettings();
    126141}
    127142
    128143
    NotificationsView::MessageReceived(BMessage* msg)  
    132147    switch (msg->what) {
    133148        case kApplicationSelected:
    134149        {
    135             BRow* row = fApplications->CurrentSelection();
    136             if (row == NULL)
    137                 return;
    138             BStringField* appName
    139                 = dynamic_cast<BStringField*>(row->GetField(kAppIndex));
    140             if (appName == NULL)
    141                 break;
    142 
    143             appusage_t::iterator it = fAppFilters.find(appName->String());
     150            Window()->Lock();
     151            _ClearItemSettings();
     152            _UpdateSelectedItem();
     153            _RecallItemSettings();
     154            Window()->Unlock();
     155            break;
     156        }
     157        case kMuteChanged:
     158        {
     159            bool allowed = fMuteAll->Value() == B_CONTROL_OFF;
     160            fSelectedRow->SetAllowed(allowed);
     161            appusage_t::iterator it = fAppFilters.find(fSelectedRow->Signature());
    144162            if (it != fAppFilters.end())
    145                 _Populate(it->second);
    146 
     163                it->second->SetAllowed(allowed);
     164            Window()->PostMessage(kApply);
     165            break;
     166        }
     167        case kAddApplication:
     168        {
     169            BMessage addmsg(kAddApplicationRef);
     170            fAddAppPanel->SetMessage(&addmsg);
     171            fAddAppPanel->Show();
    147172            break;
    148173        }
    149         case kNotificationSelected:
     174        case kAddApplicationRef:
     175        {
     176            entry_ref srcRef;
     177            msg->FindRef("refs", &srcRef);
     178            BEntry srcEntry(&srcRef, true);
     179            BPath path(&srcEntry);
     180            BNode node(&srcEntry);
     181            char *buf = new char[B_ATTR_NAME_LENGTH];
     182            ssize_t size;
     183            if ( (size = node.ReadAttr("BEOS:APP_SIG", 0, 0, buf,
     184                B_ATTR_NAME_LENGTH)) > 0 )
     185            {
     186                // Search for already existing app
     187                appusage_t::iterator it = fAppFilters.find(buf);
     188                if (it != fAppFilters.end()) {
     189                    BString text(path.Leaf());
     190                    text.Append(B_TRANSLATE_COMMENT(" is already listed",
     191                            "Alert message"));
     192                    BAlert* alert = new BAlert("", text.String(),
     193                        B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_AS_USUAL,
     194                        B_WARNING_ALERT);
     195                    alert->Go(NULL);
     196                } else {
     197                    AppUsage* appUsage = new AppUsage(path.Leaf(), buf, true);
     198                    fAppFilters[appUsage->Signature()] = appUsage;
     199                    AppRow* row = new AppRow(appUsage->AppName(),
     200                        appUsage->Signature(), appUsage->Allowed());
     201                    fApplications->AddRow(row);
     202                    fApplications->DeselectAll();
     203                    fApplications->AddToSelection(row);
     204                    fApplications->ScrollTo(row);
     205                    _UpdateSelectedItem();
     206                    _RecallItemSettings();
     207                    //row->Invalidate();
     208                    //fApplications->InvalidateRow(row);
     209                    // TODO redraw row properly
     210                    Window()->PostMessage(kApply);
     211                }
     212            } else {
     213                BAlert* alert = new BAlert("",
     214                    B_TRANSLATE_COMMENT("Application does not have "
     215                        "a valid signature", "Alert message"),
     216                    B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_AS_USUAL,
     217                    B_WARNING_ALERT);
     218                alert->Go(NULL);
     219            }
     220            delete[] buf;
    150221            break;
     222        }
     223        case kRemoveApplication:
     224        {
     225            if (fSelectedRow) {
     226                appusage_t::iterator it = fAppFilters.find(fSelectedRow->Signature());
     227                if (it != fAppFilters.end()) {
     228                    delete it->second;
     229                    fAppFilters.erase(it);
     230                }
     231                fApplications->RemoveRow(fSelectedRow);
     232                delete fSelectedRow;
     233                fSelectedRow = NULL;
     234                _ClearItemSettings();
     235                _UpdateSelectedItem();
     236                _RecallItemSettings();
     237                Window()->PostMessage(kApply);
     238            }
     239            break;
     240        }
    151241        default:
    152242            BView::MessageReceived(msg);
    153243            break;
    NotificationsView::Load(BMessage& settings)  
    174264    for (int32 i = 0; i < count; i++) {
    175265        AppUsage* app = new AppUsage();
    176266        settings.FindFlat("app_usage", i, app);
    177         fAppFilters[app->Name()] = app;
     267        fAppFilters[app->Signature()] = app;
    178268    }
    179269
    180270    // Load the applications list
    NotificationsView::Save(BMessage& storage)  
    196286
    197287
    198288void
    199 NotificationsView::_PopulateApplications()
     289NotificationsView::_ClearItemSettings()
    200290{
    201     appusage_t::iterator it;
     291    fMuteAll->SetValue(B_CONTROL_OFF);
     292}
    202293
    203     fApplications->Clear();
    204294
    205     for (it = fAppFilters.begin(); it != fAppFilters.end(); ++it) {
    206         BRow* row = new BRow();
    207         row->SetField(new BStringField(it->first.String()), kAppIndex);
    208         fApplications->AddRow(row);
    209     }
     295void
     296NotificationsView::_UpdateSelectedItem()
     297{
     298    fSelectedRow = dynamic_cast<AppRow*>(fApplications->CurrentSelection());
     299   
    210300}
    211301
    212302
    213303void
    214 NotificationsView::_Populate(AppUsage* usage)
     304NotificationsView::_RecallItemSettings()
    215305{
    216     // Sanity check
    217     if (!usage)
    218         return;
    219 
    220     int32 size = usage->Notifications();
    221 
    222     if (usage->Allowed() == false)
    223         fBlockAll->SetValue(B_CONTROL_ON);
    224 
    225     fNotifications->Clear();
    226 
    227     for (int32 i = 0; i < size; i++) {
    228         NotificationReceived* notification = usage->NotificationAt(i);
    229         time_t updated = notification->LastReceived();
    230         const char* allow = notification->Allowed() ? B_TRANSLATE("Yes")
    231             : B_TRANSLATE("No");
    232         const char* type = "";
    233 
    234         switch (notification->Type()) {
    235             case B_INFORMATION_NOTIFICATION:
    236                 type = B_TRANSLATE("Information");
    237                 break;
    238             case B_IMPORTANT_NOTIFICATION:
    239                 type = B_TRANSLATE("Important");
    240                 break;
    241             case B_ERROR_NOTIFICATION:
    242                 type = B_TRANSLATE("Error");
    243                 break;
    244             case B_PROGRESS_NOTIFICATION:
    245                 type = B_TRANSLATE("Progress");
    246                 break;
    247             default:
    248                 type = B_TRANSLATE("Unknown");
    249         }
     306    // No selected item
     307    if(fSelectedRow == NULL)
     308    {
     309        fMuteAll->SetValue(B_CONTROL_OFF);
     310        fMuteAll->SetEnabled(false);
     311        fRemoveButton->SetEnabled(false);
     312    } else {
     313        fMuteAll->SetEnabled(true);
     314        fRemoveButton->SetEnabled(true);
     315        appusage_t::iterator it = fAppFilters.find(fSelectedRow->Signature());
     316        if (it != fAppFilters.end())
     317            fMuteAll->SetValue(!(it->second->Allowed()));
     318    }
     319}
    250320
    251         BRow* row = new BRow();
    252         row->SetField(new BStringField(notification->Title()), kTitleIndex);
    253         row->SetField(new BDateField(&updated), kDateIndex);
    254         row->SetField(new BStringField(type), kTypeIndex);
    255         row->SetField(new BStringField(allow), kAllowIndex);
    256321
    257         fNotifications->AddRow(row);
     322status_t
     323NotificationsView::Revert()
     324{
     325    return B_OK;
     326}
     327
     328
     329bool
     330NotificationsView::RevertPossible()
     331{
     332    return false;
     333}
     334
     335
     336status_t
     337NotificationsView::Defaults()
     338{
     339    return B_OK;
     340}
     341
     342
     343bool
     344NotificationsView::DefaultsPossible()
     345{
     346    return false;
     347}
     348
     349
     350bool
     351NotificationsView::UseDefaultRevertButtons()
     352{
     353    return false;
     354}
     355
     356
     357void
     358NotificationsView::_PopulateApplications()
     359{
     360    fApplications->Clear();
     361
     362    appusage_t::iterator it;
     363    for (it = fAppFilters.begin(); it != fAppFilters.end(); ++it) {
     364        AppUsage* appUsage = it->second;
     365        AppRow* row = new AppRow(appUsage->AppName(),
     366            appUsage->Signature(), appUsage->Allowed());
     367        fApplications->AddRow(row);
    258368    }
    259369}
  • src/preferences/notifications/NotificationsView.h

    diff --git a/src/preferences/notifications/NotificationsView.h b/src/preferences/notifications/NotificationsView.h
    index b44c737..1eec7b1 100644
    a b  
    11/*
    2  * Copyright 2010, Haiku, Inc. All Rights Reserved.
     2 * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
    33 * Copyright 2009, Pier Luigi Fiorini.
    44 * Distributed under the terms of the MIT License.
    55 */
    66#ifndef _APPS_VIEW_H
    77#define _APPS_VIEW_H
    88
     9#include <FilePanel.h>
     10#include <ColumnListView.h>
    911#include <View.h>
    1012
    1113#include <notification/AppUsage.h>
    1214
     15#include "AppRefFilter.h"
    1316#include "SettingsPane.h"
    1417
    1518typedef std::map<BString, AppUsage *> appusage_t;
    1619
     20class BButton;
    1721class BCheckBox;
    1822class BTextControl;
    19 class BColumnListView;
    2023class BStringColumn;
    2124class BDateColumn;
    2225
     26
     27class AppRow : public BRow {
     28public:
     29                                AppRow(const char* name,
     30                                    const char* signature, bool allowed);
     31
     32            const char*         Name() const { return fName.String(); }
     33            const char*         Signature() { return fSignature.String(); };
     34            void                SetAllowed(bool allowed);
     35            bool                Allowed() { return fAllowed; };
     36            void                RefreshEnabledField();
     37
     38private:
     39            BString             fName;
     40            BString             fSignature;
     41            bool                fAllowed;
     42};
     43
     44
    2345class NotificationsView : public SettingsPane {
    2446public:
    2547                                NotificationsView(SettingsHost* host);
     48                                ~NotificationsView();
    2649
    2750    virtual void                AttachedToWindow();
    2851    virtual void                MessageReceived(BMessage* msg);
     52            status_t            Revert();
     53            bool                RevertPossible();
     54            status_t            Defaults();
     55            bool                DefaultsPossible();
     56            bool                UseDefaultRevertButtons();
    2957
    3058private:
    3159            status_t            Load(BMessage&);
    3260            status_t            Save(BMessage&);
    33             status_t            Revert() {return B_OK;} // FIXME implement this
     61            void                _ClearItemSettings();
     62            void                _UpdateSelectedItem();
     63            void                _RecallItemSettings();
    3464            void                _PopulateApplications();
    35             void                _Populate(AppUsage* usage);
    3665
    3766            appusage_t          fAppFilters;
    38             BCheckBox*          fBlockAll;
    39             BTextControl*       fSearch;
     67            AppRefFilter*       fPanelFilter;
     68            BFilePanel*         fAddAppPanel;
     69            BButton*            fAddButton;
     70            BButton*            fRemoveButton;
     71            BCheckBox*          fMuteAll;
    4072            BColumnListView*    fApplications;
     73            AppRow*             fSelectedRow;
    4174            BStringColumn*      fAppCol;
    4275            BStringColumn*      fAppEnabledCol;
    43             BColumnListView*    fNotifications;
    44             BStringColumn*      fTitleCol;
    45             BDateColumn*        fDateCol;
    46             BStringColumn*      fTypeCol;
    47             BStringColumn*      fAllowCol;
    4876};
    4977
    5078#endif // _APPS_VIEW_H
  • src/preferences/notifications/PrefletView.cpp

    diff --git a/src/preferences/notifications/PrefletView.cpp b/src/preferences/notifications/PrefletView.cpp
    index 1527121..a309397 100644
    a b  
    11/*
    2  * Copyright 2010, Haiku, Inc. All Rights Reserved.
     2 * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
    33 * Copyright 2009, Pier Luigi Fiorini.
    44 * Distributed under the terms of the MIT License.
    55 *
    66 * Authors:
    77 *      Pier Luigi Fiorini, pierluigi.fiorini@gmail.com
     8 *      Brian Hill, supernova@tycho.email
    89 */
    910
    1011#include <Catalog.h>
     
    1314#include <GroupLayoutBuilder.h>
    1415#include <LayoutItem.h>
    1516#include <Message.h>
     17#include <Window.h>
    1618
    17 #include "DisplayView.h"
    18 #include "GeneralView.h"
    1919#include "NotificationsView.h"
    2020#include "PrefletView.h"
    2121#include "SettingsHost.h"
     
    2525#define B_TRANSLATION_CONTEXT "PrefletView"
    2626
    2727
    28 const int32 kPageSelected = '_LCH';
    29 
    30 
    3128PrefletView::PrefletView(SettingsHost* host)
    3229    :
    33     BTabView("pages", B_WIDTH_FROM_WIDEST)
     30    BTabView("pages", B_WIDTH_FROM_WIDEST),
     31    fWatchingRoster(false)
    3432{
    3533    // Pages
    36     GeneralView* general = new GeneralView(host);
    37     DisplayView* display = new DisplayView(host);
     34    fGeneralView = new GeneralView(host);
    3835    NotificationsView* apps = new NotificationsView(host);
    3936
    4037    // Page selector
    4138    BTab* tab = new BTab();
    42     AddTab(general, tab);
    43     tab->SetLabel(B_TRANSLATE("General"));
    44 
    45     tab = new BTab();
    46     AddTab(display, tab);
    47     tab->SetLabel(B_TRANSLATE("Display"));
     39    AddTab(fGeneralView, tab);
     40    tab->SetLabel(B_TRANSLATE("Settings"));
    4841
    4942    tab = new BTab();
    5043    AddTab(apps, tab);
    51     tab->SetLabel(B_TRANSLATE("Notifications"));
     44    tab->SetLabel(B_TRANSLATE("Applications"));
    5245}
    5346
    5447
    55 BView*
    56 PrefletView::CurrentPage()
     48PrefletView::~PrefletView()
    5749{
    58     return PageAt(FocusTab());
     50    //Need to stop watching the roster
     51    if (fWatchingRoster) {
     52        be_roster->StopWatching(fMessenger);
     53        fWatchingRoster = false;
     54    }
    5955}
    6056
    6157
    62 int32
    63 PrefletView::CountPages() const
     58BView*
     59PrefletView::CurrentPage()
    6460{
    65     return 3;
     61    return PageAt(FocusTab());
    6662}
    6763
    6864
    PrefletView::PageAt(int32 index)  
    7167{
    7268    return TabAt(index)->View();
    7369}
     70
     71
     72void
     73PrefletView::Select(int32 index)
     74{
     75    if (index == Selection())
     76        return;
     77
     78    BTabView::Select(index);
     79
     80    SettingsPane* pane = dynamic_cast<SettingsPane*>(PageAt(index));
     81    bool showButtons = (pane != NULL) && pane->UseDefaultRevertButtons();
     82    BMessage showMessage(kShowButtons);
     83    showMessage.AddBool(kShowButtonsKey, showButtons);
     84    Window()->PostMessage(&showMessage);
     85}
     86
     87
     88void
     89PrefletView::StartWatchingRoster()
     90{
     91    //Start watching the application roster for launches/quits
     92    fMessenger.SetTo(fGeneralView);
     93    status_t result = be_roster->StartWatching(fMessenger);
     94    if (result == B_OK)
     95        fWatchingRoster = true;
     96}
  • src/preferences/notifications/PrefletView.h

    diff --git a/src/preferences/notifications/PrefletView.h b/src/preferences/notifications/PrefletView.h
    index 404b261..d7d7a89 100644
    a b  
    11/*
    2  * Copyright 2010, Haiku, Inc. All Rights Reserved.
     2 * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
    33 * Copyright 2009, Pier Luigi Fiorini.
    44 * Distributed under the terms of the MIT License.
    55 */
    66#ifndef _PREFLET_VIEW_H
    77#define _PREFLET_VIEW_H
    88
     9#include <Messenger.h>
    910#include <TabView.h>
    1011
    11 class BIconRule;
     12#include "GeneralView.h"
    1213
    1314class SettingsHost;
    1415
     16const int32 kShowButtons = '_SHB';
     17#define kShowButtonsKey "showButtons"
     18
    1519class PrefletView : public BTabView {
    1620public:
    1721                        PrefletView(SettingsHost* host);
     22                        ~PrefletView();
    1823
    1924            BView*      CurrentPage();
    20             int32       CountPages() const;
    2125            BView*      PageAt(int32 index);
     26    virtual void        Select(int32 index);
     27            void        StartWatchingRoster();
     28
     29private:
     30            GeneralView*    fGeneralView;
     31            BMessenger      fMessenger;
     32            bool            fWatchingRoster;
    2233};
    2334
    2435#endif // PREFLETVIEW_H
  • src/preferences/notifications/PrefletWin.cpp

    diff --git a/src/preferences/notifications/PrefletWin.cpp b/src/preferences/notifications/PrefletWin.cpp
    index b269bb8..e74974c 100644
    a b  
    11/*
    2  * Copyright 2010-2014, Haiku, Inc. All Rights Reserved.
     2 * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
    33 * Copyright 2009, Pier Luigi Fiorini.
    44 * Distributed under the terms of the MIT License.
    55 *
    66 * Authors:
    77 *      Pier Luigi Fiorini, pierluigi.fiorini@gmail.com
     8 *      Brian Hill, supernova@tycho.email
    89 */
    910
    1011#include "PrefletWin.h"
     
    1415#include <Button.h>
    1516#include <Catalog.h>
    1617#include <FindDirectory.h>
    17 #include <LayoutBuilder.h>
     18#include <Notification.h>
    1819#include <Path.h>
    1920#include <SeparatorView.h>
    2021
    2122#include <notification/Notifications.h>
    2223
     24#include "NotificationsConstants.h"
    2325#include "PrefletView.h"
    2426
    2527
    2628#undef B_TRANSLATION_CONTEXT
    2729#define B_TRANSLATION_CONTEXT "PrefletWin"
    2830
    29 
    30 const int32 kRevert = '_RVT';
    31 const int32 kApply = '_APY';
     31const BString kSampleMessageID("NotificationsSample");
    3232
    3333
    3434PrefletWin::PrefletWin()
    3535    :
    36     BWindow(BRect(0, 0, 500, 400), B_TRANSLATE_SYSTEM_NAME("Notifications"),
     36    BWindow(BRect(0, 0, 160 + 20 * be_plain_font->Size(), 300),
     37        B_TRANSLATE_SYSTEM_NAME("Notifications"),
    3738        B_TITLED_WINDOW, B_NOT_ZOOMABLE | B_ASYNCHRONOUS_CONTROLS
    3839        | B_AUTO_UPDATE_SIZE_LIMITS)
    3940{
    4041    // Preflet container view
    4142    fMainView = new PrefletView(this);
    4243    fMainView->SetBorder(B_NO_BORDER);
    43     fMainView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
     44    fMainView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED));
     45
     46    // Defaults button
     47    fDefaults = new BButton("defaults", B_TRANSLATE("Defaults"),
     48        new BMessage(kDefaults));
     49    fDefaults->SetEnabled(false);
    4450
    45     // Apply and revert buttons
     51    // Revert button
    4652    fRevert = new BButton("revert", B_TRANSLATE("Revert"),
    4753        new BMessage(kRevert));
    4854    fRevert->SetEnabled(false);
    49     fApply = new BButton("apply", B_TRANSLATE("Apply"), new BMessage(kApply));
    50     fApply->SetEnabled(false);
    5155
    5256    // Build the layout
    53     BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
    54         .SetInsets(0, B_USE_DEFAULT_SPACING, 0, 0)
    55         .Add(fMainView)
    56         .Add(new BSeparatorView(B_HORIZONTAL))
     57    fButtonsView = new BGroupView();
     58    BLayoutBuilder::Group<>(fButtonsView, B_VERTICAL, 0)
    5759        .AddGroup(B_HORIZONTAL)
     60            .Add(fDefaults)
    5861            .Add(fRevert)
    5962            .AddGlue()
    60             .Add(fApply)
    61             .SetInsets(B_USE_WINDOW_SPACING, B_USE_DEFAULT_SPACING,
    62                 B_USE_WINDOW_SPACING, B_USE_WINDOW_SPACING);
     63            .SetInsets(B_USE_WINDOW_SPACING, 0, B_USE_WINDOW_SPACING,
     64                B_USE_WINDOW_SPACING)
     65        .End();
     66    fButtonsLayout = fButtonsView->GroupLayout();
     67   
     68    BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
     69        .SetInsets(0, B_USE_DEFAULT_SPACING, 0, 0)
     70        .Add(fMainView)
     71        .Add(fButtonsView)
     72    .End();
     73    fMainView->SetExplicitMinSize(BSize(Frame().Width(), B_SIZE_UNSET));
    6374
    6475    ReloadSettings();
    6576
    6677    // Center this window on screen and show it
    6778    CenterOnScreen();
    6879    Show();
     80   
     81    fMainView->StartWatchingRoster();
    6982}
    7083
    7184
    PrefletWin::MessageReceived(BMessage* msg)  
    7487{
    7588    switch (msg->what) {
    7689        case kApply:
     90        case kApplyWithExample:
    7791        {
    7892            BPath path;
    7993
    PrefletWin::MessageReceived(BMessage* msg)  
    8599            path.Append(kSettingsFile);
    86100
    87101            BMessage settingsStore;
    88             for (int32 i = 0; i < fMainView->CountPages(); i++) {
     102            int32 count = fMainView->CountTabs();
     103            for (int32 i = 0; i < count; i++) {
    89104                SettingsPane* pane =
    90105                    dynamic_cast<SettingsPane*>(fMainView->PageAt(i));
    91106                if (pane) {
    92107                    if (pane->Save(settingsStore) == B_OK) {
    93                         fApply->SetEnabled(false);
    94                         fRevert->SetEnabled(true);
     108                        fDefaults->SetEnabled(_DefaultsPossible());
     109                        fRevert->SetEnabled(_RevertPossible());
    95110                    } else
    96111                        break;
    97112                }
    PrefletWin::MessageReceived(BMessage* msg)  
    109124                alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
    110125                (void)alert->Go();
    111126            }
     127            file.Unset();
     128
     129            if (msg->what == kApplyWithExample)
     130                _SendExampleNotification();
    112131
    113132            break;
    114133        }
     134        case kDefaults:
     135            fDefaults->SetEnabled(false);
     136            _Defaults();
     137            PostMessage(kApply);
     138            break;
    115139        case kRevert:
    116             for (int32 i = 0; i < fMainView->CountPages(); i++) {
    117                 SettingsPane* pane =
    118                     dynamic_cast<SettingsPane*>(fMainView->PageAt(i));
    119                 if (pane) {
    120                     if (pane->Revert() == B_OK)
    121                         fRevert->SetEnabled(false);
    122                 }
    123             }
     140            fRevert->SetEnabled(false);
     141            _Revert();
     142            PostMessage(kApply);
     143            break;
     144        case kShowButtons: {
     145            bool show = msg->GetBool(kShowButtonsKey, true);
     146            fButtonsLayout->SetVisible(show);
    124147            break;
     148        }
    125149        default:
    126150            BWindow::MessageReceived(msg);
    127151    }
    PrefletWin::QuitRequested()  
    137161
    138162
    139163void
    140 PrefletWin::SettingChanged()
     164PrefletWin::SettingChanged(bool showExample)
    141165{
    142     fApply->SetEnabled(true);
     166    if (showExample)
     167        PostMessage(kApplyWithExample);
     168    else
     169        PostMessage(kApply);
    143170}
    144171
    145172
    PrefletWin::ReloadSettings()  
    158185    BFile file(path.Path(), B_READ_ONLY);
    159186    settings.Unflatten(&file);
    160187
    161     for (int32 i = 0; i < fMainView->CountPages(); i++) {
     188    int32 count = fMainView->CountTabs();
     189    for (int32 i = 0; i < count; i++) {
    162190        SettingsPane* pane =
    163191            dynamic_cast<SettingsPane*>(fMainView->PageAt(i));
    164192        if (pane)
    165193            pane->Load(settings);
    166194    }
     195    fDefaults->SetEnabled(_DefaultsPossible());
     196}
     197
     198
     199status_t
     200PrefletWin::_Revert()
     201{
     202    int32 count = fMainView->CountTabs();
     203    for (int32 i = 0; i < count; i++) {
     204        SettingsPane* pane =
     205            dynamic_cast<SettingsPane*>(fMainView->PageAt(i));
     206        if (pane)
     207            pane->Revert();
     208    }
     209    return B_OK;
     210}
     211
     212
     213bool
     214PrefletWin::_RevertPossible()
     215{
     216    int32 count = fMainView->CountTabs();
     217    for (int32 i = 0; i < count; i++) {
     218        SettingsPane* pane =
     219            dynamic_cast<SettingsPane*>(fMainView->PageAt(i));
     220        if (pane && pane->RevertPossible())
     221            return true;
     222    }
     223    return false;
     224}
     225
     226
     227status_t
     228PrefletWin::_Defaults()
     229{
     230    int32 count = fMainView->CountTabs();
     231    for (int32 i = 0; i < count; i++) {
     232        SettingsPane* pane =
     233            dynamic_cast<SettingsPane*>(fMainView->PageAt(i));
     234        if (pane)
     235            pane->Defaults();
     236    }
     237    return B_OK;
     238}
     239
     240
     241bool
     242PrefletWin::_DefaultsPossible()
     243{
     244    int32 count = fMainView->CountTabs();
     245    for (int32 i = 0; i < count; i++) {
     246        SettingsPane* pane =
     247            dynamic_cast<SettingsPane*>(fMainView->PageAt(i));
     248        if (pane && pane->DefaultsPossible())
     249            return true;
     250    }
     251    return false;
     252}
     253
     254
     255void
     256PrefletWin::_SendExampleNotification()
     257{
     258    BNotification notification(B_INFORMATION_NOTIFICATION);
     259    notification.SetMessageID(kSampleMessageID);
     260    notification.SetGroup(B_TRANSLATE("Notifications"));
     261    notification.SetTitle(B_TRANSLATE("Notifications preflet sample"));
     262    notification.SetContent(B_TRANSLATE("This is a test notification message"));
     263    notification.Send();
    167264}
  • src/preferences/notifications/PrefletWin.h

    diff --git a/src/preferences/notifications/PrefletWin.h b/src/preferences/notifications/PrefletWin.h
    index 561c1fb..95175ca 100644
    a b  
    11/*
    2  * Copyright 2010, Haiku, Inc. All Rights Reserved.
     2 * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
    33 * Copyright 2009, Pier Luigi Fiorini.
    44 * Distributed under the terms of the MIT License.
    55 */
    66#ifndef _PREFLET_WIN_H
    77#define _PREFLET_WIN_H
    88
     9
     10#include <GroupView.h>
     11#include <LayoutBuilder.h>
     12#include <Message.h>
    913#include <Window.h>
    1014
    1115#include "SettingsHost.h"
    public:  
    2125    virtual bool            QuitRequested();
    2226    virtual void            MessageReceived(BMessage* msg);
    2327
    24     virtual void            SettingChanged();
     28    virtual void            SettingChanged(bool showExample);
    2529            void            ReloadSettings();
    2630
    2731private:
     32            status_t        _Revert();
     33            bool            _RevertPossible();
     34            status_t        _Defaults();
     35            bool            _DefaultsPossible();
     36            void            _SendExampleNotification();
     37           
    2838            PrefletView*    fMainView;
    29             BButton*        fApply;
     39            BGroupView*     fButtonsView;
     40            BButton*        fDefaults;
    3041            BButton*        fRevert;
     42            BGroupLayout*   fButtonsLayout;
    3143};
    3244
    3345#endif // _PREFLET_WIN_H
  • src/preferences/notifications/SettingsHost.h

    diff --git a/src/preferences/notifications/SettingsHost.h b/src/preferences/notifications/SettingsHost.h
    index 3774d7d..ca09a8d 100644
    a b  
    11/*
    2  * Copyright 2010, Haiku, Inc. All Rights Reserved.
     2 * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
    33 * Copyright 2009, Pier Luigi Fiorini.
    44 * Distributed under the terms of the MIT License.
    55 */
    class SettingsHost {  
    1414public:
    1515                    SettingsHost() {}
    1616
    17     virtual void    SettingChanged() = 0;
     17    virtual void    SettingChanged(bool showExample = false) = 0;
    1818};
    1919
    2020#endif // _SETTINGS_HOST_H
  • src/preferences/notifications/SettingsPane.cpp

    diff --git a/src/preferences/notifications/SettingsPane.cpp b/src/preferences/notifications/SettingsPane.cpp
    index 128e7a5..457200e 100644
    a b  
    11/*
    2  * Copyright 2010, Haiku, Inc. All Rights Reserved.
     2 * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
    33 * Copyright 2009, Pier Luigi Fiorini.
    44 * Distributed under the terms of the MIT License.
    55 *
    66 * Authors:
    77 *      Pier Luigi Fiorini, pierluigi.fiorini@gmail.com
     8 *      Brian Hill, supernova@tycho.email
    89 */
    910
    1011#include <Message.h>
    SettingsPane::SettingsPane(const char* name, SettingsHost* host)  
    2223
    2324
    2425void
    25 SettingsPane::MessageReceived(BMessage* msg)
     26SettingsPane::SettingsChanged(bool showExample)
    2627{
    27     switch (msg->what) {
    28         case kSettingChanged:
    29             fHost->SettingChanged();
    30             break;
    31         default:
    32             BView::MessageReceived(msg);
    33     }
     28    fHost->SettingChanged(showExample);
    3429}
  • src/preferences/notifications/SettingsPane.h

    diff --git a/src/preferences/notifications/SettingsPane.h b/src/preferences/notifications/SettingsPane.h
    index a14fd62..b8cd77e 100644
    a b  
    11/*
    2  * Copyright 2010, Haiku, Inc. All Rights Reserved.
     2 * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
    33 * Copyright 2009, Pier Luigi Fiorini.
    44 * Distributed under the terms of the MIT License.
    55 */
    class BNode;  
    1212
    1313class SettingsHost;
    1414
    15 const int32 kSettingChanged = '_STC';
    1615
    1716class SettingsPane : public BView {
    1817public:
    1918                            SettingsPane(const char* name, SettingsHost* host);
    2019
    21     virtual void            MessageReceived(BMessage* msg);
     20    void                    SettingsChanged(bool showExample);
    2221
    2322    virtual status_t        Load(BMessage&) = 0;
    2423    virtual status_t        Save(BMessage&) = 0;
    2524    virtual status_t        Revert() = 0;
     25    virtual bool            RevertPossible() = 0;
     26    virtual status_t        Defaults() = 0;
     27    virtual bool            DefaultsPossible() = 0;
     28    virtual bool            UseDefaultRevertButtons() = 0;
    2629
    2730protected:
    2831            SettingsHost*   fHost;
  • src/servers/notification/AppGroupView.cpp

    diff --git a/src/servers/notification/AppGroupView.cpp b/src/servers/notification/AppGroupView.cpp
    index 38fec70..f0d87c3 100644
    a b  
    11/*
    2  * Copyright 2010, Haiku, Inc. All Rights Reserved.
     2 * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
    33 * Copyright 2008-2009, Pier Luigi Fiorini. All Rights Reserved.
    44 * Copyright 2004-2008, Michael Davidson. All Rights Reserved.
    55 * Copyright 2004-2007, Mikael Eiman. All Rights Reserved.
     
    99 *      Michael Davidson, slaad@bong.com.au
    1010 *      Mikael Eiman, mikael@eiman.tv
    1111 *      Pier Luigi Fiorini, pierluigi.fiorini@gmail.com
     12 *      Brian Hill, supernova@tycho.email
    1213 */
    1314
    1415#include <algorithm>
     
    2223#include "NotificationWindow.h"
    2324#include "NotificationView.h"
    2425
     26const float kCloseSize              = 6;
     27const float kEdgePadding            = 2;
    2528
    26 static const int kHeaderSize = 23;
    2729
    28 
    29 AppGroupView::AppGroupView(NotificationWindow* win, const char* label)
     30AppGroupView::AppGroupView(const BMessenger& messenger, const char* label)
    3031    :
    3132    BGroupView("appGroup", B_VERTICAL, 0),
    3233    fLabel(label),
    33     fParent(win),
     34    fMessenger(messenger),
    3435    fCollapsed(false),
    35     fCloseClicked(false)
     36    fCloseClicked(false),
     37    fPreviewModeOn(false)
    3638{
    3739    SetFlags(Flags() | B_WILL_DRAW);
    3840
    39     static_cast<BGroupLayout*>(GetLayout())->SetInsets(0, kHeaderSize, 0, 0);
     41    fHeaderSize = be_plain_font->Size()
     42        + be_control_look->ComposeSpacing(B_USE_ITEM_SPACING);
     43    static_cast<BGroupLayout*>(GetLayout())->SetInsets(0, fHeaderSize, 0, 0);
    4044}
    4145
    4246
    AppGroupView::Draw(BRect updateRect)  
    4751    BRect bounds = Bounds();
    4852    rgb_color hilite = tint_color(menuColor, B_DARKEN_1_TINT);
    4953    rgb_color vlight = tint_color(menuColor, B_LIGHTEN_2_TINT);
    50     bounds.bottom = bounds.top + kHeaderSize;
     54    bounds.bottom = bounds.top + fHeaderSize;
    5155
    5256    // Draw the header background
    5357    SetHighColor(tint_color(menuColor, 1.22));
    AppGroupView::Draw(BRect updateRect)  
    5559    StrokeLine(bounds.LeftTop(), bounds.LeftBottom());
    5660    uint32 borders = BControlLook::B_TOP_BORDER
    5761        | BControlLook::B_BOTTOM_BORDER | BControlLook::B_RIGHT_BORDER;
    58 
    5962    be_control_look->DrawButtonBackground(this, bounds, bounds, menuColor,
    6063        0, borders);
    6164
    6265    // Draw the buttons
    63     fCollapseRect.top = (kHeaderSize - kExpandSize) / 2;
     66    fCollapseRect.top = (fHeaderSize - kExpandSize) / 2;
    6467    fCollapseRect.left = kEdgePadding * 3;
    6568    fCollapseRect.right = fCollapseRect.left + 1.5 * kExpandSize;
    6669    fCollapseRect.bottom = fCollapseRect.top + kExpandSize;
    6770
    6871    fCloseRect = bounds;
    69     fCloseRect.top = (kHeaderSize - kCloseSize) / 2;
     72    fCloseRect.top = (fHeaderSize - kCloseSize) / 2;
    7073    // Take off the 1 to line this up with the close button on the
    7174    // notification view
    7275    fCloseRect.right -= kEdgePadding * 3 - 1;
    AppGroupView::Draw(BRect updateRect)  
    8992    if (fCollapsed)
    9093        label << " (" << fInfo.size() << ")";
    9194
    92     SetFont(be_bold_font);
     95    BFont boldFont(be_plain_font);
     96    boldFont.SetFace(B_BOLD_FACE);
     97    SetFont(&boldFont);
    9398    font_height fontHeight;
    9499    GetFontHeight(&fontHeight);
    95100    float y = (bounds.top + bounds.bottom - ceilf(fontHeight.ascent)
    AppGroupView::_DrawCloseButton(const BRect& updateRect)  
    132137void
    133138AppGroupView::MouseDown(BPoint point)
    134139{
     140    // Preview Mode ignores any mouse clicks
     141    if (fPreviewModeOn)
     142        return;
     143
    135144    if (BRect(fCloseRect).InsetBySelf(-5, -5).Contains(point)) {
    136145        int32 children = fInfo.size();
    137146        for (int32 i = 0; i < children; i++) {
    AppGroupView::MouseDown(BPoint point)  
    144153        // Remove ourselves from the parent view
    145154        BMessage message(kRemoveGroupView);
    146155        message.AddPointer("view", this);
    147         fParent->PostMessage(&message);
     156        fMessenger.SendMessage(&message);
    148157    } else if (BRect(fCollapseRect).InsetBySelf(-5, -5).Contains(point)) {
    149158        fCollapsed = !fCollapsed;
    150159        int32 children = fInfo.size();
    AppGroupView::MessageReceived(BMessage* msg)  
    186195            view->RemoveSelf();
    187196            delete view;
    188197
    189             fParent->PostMessage(msg);
     198            fMessenger.SendMessage(msg);
    190199
    191200            if (!this->HasChildren()) {
    192201                Hide();
    193202                BMessage removeSelfMessage(kRemoveGroupView);
    194203                removeSelfMessage.AddPointer("view", this);
    195                 fParent->PostMessage(&removeSelfMessage);
     204                fMessenger.SendMessage(&removeSelfMessage);
    196205            }
    197206           
    198207            break;
    AppGroupView::AddInfo(NotificationView* view)  
    211220
    212221    if (id.Length() > 0) {
    213222        int32 children = fInfo.size();
    214 
    215223        for (int32 i = 0; i < children; i++) {
    216224            if (id == fInfo[i]->MessageID()) {
    217225                NotificationView* oldView = fInfo[i];
    218                 fParent->NotificationViewSwapped(oldView, view);
    219226                oldView->RemoveSelf();
    220227                delete oldView;
    221                
    222228                fInfo[i] = view;
    223229                found = true;
    224                
    225230                break;
    226231            }
    227232        }
    AppGroupView::AddInfo(NotificationView* view)  
    246251}
    247252
    248253
     254void
     255AppGroupView::SetPreviewModeOn(bool enabled)
     256{
     257    fPreviewModeOn = enabled;
     258}
     259
     260
    249261const BString&
    250262AppGroupView::Group() const
    251263{
    AppGroupView::Group() const  
    253265}
    254266
    255267
     268void
     269AppGroupView::SetGroup(const char* group)
     270{
     271    fLabel.SetTo(group);
     272    Invalidate();
     273}
     274
     275
    256276bool
    257277AppGroupView::HasChildren()
    258278{
  • src/servers/notification/AppGroupView.h

    diff --git a/src/servers/notification/AppGroupView.h b/src/servers/notification/AppGroupView.h
    index c3cbeac..ea10fce 100644
    a b  
    11/*
    2  * Copyright 2010, Haiku, Inc. All Rights Reserved.
     2 * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
    33 * Copyright 2008-2009, Pier Luigi Fiorini. All Rights Reserved.
    44 * Copyright 2004-2008, Michael Davidson. All Rights Reserved.
    55 * Copyright 2004-2007, Mikael Eiman. All Rights Reserved.
     
    1111#include <vector>
    1212
    1313#include <GroupView.h>
     14#include <Messenger.h>
    1415#include <String.h>
    1516
    1617class BGroupView;
    typedef std::vector<NotificationView*> infoview_t;  
    2223
    2324class AppGroupView : public BGroupView {
    2425public:
    25                                 AppGroupView(NotificationWindow* win, const char* label);
     26                                AppGroupView(const BMessenger& messenger, const char* label);
    2627
    2728    virtual void                MouseDown(BPoint point);
    2829    virtual void                MessageReceived(BMessage* msg);
    public:  
    3233            int32               ChildrenCount();
    3334
    3435            void                AddInfo(NotificationView* view);
     36            void                SetPreviewModeOn(bool enabled);
    3537
    3638            const BString&      Group() const;
     39            void                SetGroup(const char* group);
    3740
    3841private:
    3942            void                _DrawCloseButton(const BRect& updateRect);
    4043
    4144            BString             fLabel;
    42             NotificationWindow* fParent;
     45            BMessenger          fMessenger;
    4346            infoview_t          fInfo;
    4447            bool                fCollapsed;
    4548            BRect               fCloseRect;
    4649            BRect               fCollapseRect;
     50            float               fHeaderSize;
    4751            bool                fCloseClicked;
     52            bool                fPreviewModeOn;
    4853};
    4954
    5055#endif  // _APP_GROUP_VIEW_H
  • src/servers/notification/AppUsage.cpp

    diff --git a/src/servers/notification/AppUsage.cpp b/src/servers/notification/AppUsage.cpp
    index 2e1cb72..6599c87 100644
    a b  
    11/*
    2  * Copyright 2010, Haiku, Inc. All Rights Reserved.
     2 * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
    33 * Copyright 2008-2009, Pier Luigi Fiorini. All Rights Reserved.
    44 * Copyright 2004-2008, Michael Davidson. All Rights Reserved.
    55 * Copyright 2004-2007, Mikael Eiman. All Rights Reserved.
     
    99 *      Michael Davidson, slaad@bong.com.au
    1010 *      Mikael Eiman, mikael@eiman.tv
    1111 *      Pier Luigi Fiorini, pierluigi.fiorini@gmail.com
     12 *      Brian Hill, supernova@tycho.email
    1213 */
    1314
    1415#include <Message.h>
    const type_code kTypeCode = 'ipau';  
    2122
    2223AppUsage::AppUsage()
    2324    :
    24     fName(""),
     25    fAppName(""),
     26    fSignature(""),
    2527    fAllow(true)
    2628{
    2729}
    2830
    2931
    30 AppUsage::AppUsage(const char* name, bool allow)
     32AppUsage::AppUsage(const char* name, const char* signature, bool allow)
    3133    :
    32     fName(name),
     34    fAppName(name),
     35    fSignature(signature),
    3336    fAllow(allow)
    3437{   
    3538}
    3639
    3740
    38 AppUsage::~AppUsage()
    39 {
    40     notification_t::iterator nIt;
    41     for (nIt = fNotifications.begin(); nIt != fNotifications.end(); nIt++)
    42         delete nIt->second;
    43 }
    44 
    45 
    4641bool
    4742AppUsage::AllowsTypeCode(type_code code) const
    4843{
    status_t  
    5449AppUsage::Flatten(void* buffer, ssize_t numBytes) const
    5550{
    5651    BMessage msg;
    57     msg.AddString("signature", fName);
     52    msg.AddString("name", fAppName);
     53    msg.AddString("signature", fSignature);
    5854    msg.AddBool("allow", fAllow);
    5955
    60     notification_t::const_iterator nIt;
    61     for (nIt = fNotifications.begin(); nIt != fNotifications.end(); nIt++)
    62         msg.AddFlat("notification", nIt->second);
    63 
    6456    if (numBytes < msg.FlattenedSize())
    6557        return B_ERROR;
    6658
    ssize_t  
    7264AppUsage::FlattenedSize() const
    7365{
    7466    BMessage msg;
    75     msg.AddString("signature", fName);
     67    msg.AddString("name", fAppName);
     68    msg.AddString("signature", fSignature);
    7669    msg.AddBool("allow", fAllow);
    7770
    78     notification_t::const_iterator nIt;
    79     for (nIt = fNotifications.begin(); nIt != fNotifications.end(); nIt++)
    80         msg.AddFlat("notification", nIt->second);
    81 
    8271    return msg.FlattenedSize();
    8372}
    8473
    AppUsage::Unflatten(type_code code, const void* buffer,  
    11099    status = msg.Unflatten((const char*)buffer);
    111100
    112101    if (status == B_OK) {
    113         msg.FindString("signature", &fName);
     102        msg.FindString("name", &fAppName);
     103        msg.FindString("signature", &fSignature);
    114104        msg.FindBool("allow", &fAllow);
    115 
    116         type_code type;
    117         int32 count = 0;
    118 
    119         status = msg.GetInfo("notification", &type, &count);
    120         if (status != B_OK)
    121             return status;
    122 
    123         for (int32 i = 0; i < count; i++) {
    124             NotificationReceived *notification = new NotificationReceived();
    125             msg.FindFlat("notification", i, notification);
    126             fNotifications[notification->Title()] = notification;
    127         }
    128 
    129         status = B_OK;
    130105    }
    131106   
    132107    return status;
    AppUsage::Unflatten(type_code code, const void* buffer,  
    134109
    135110                       
    136111const char*
    137 AppUsage::Name()
     112AppUsage::AppName()
    138113{
    139     return fName.String();
     114    return fAppName.String();
    140115}
    141116
    142117
    143 bool
    144 AppUsage::Allowed(const char* title, notification_type type)
     118const char*
     119AppUsage::Signature()
    145120{
    146     bool allowed = fAllow;
    147 
    148     if (allowed) {
    149         notification_t::iterator nIt = fNotifications.find(title);
    150         if (nIt == fNotifications.end()) {
    151             allowed = true;     
    152             fNotifications[title] = new NotificationReceived(title, type);
    153         } else {
    154             allowed = nIt->second->Allowed();
    155             nIt->second->UpdateTimeStamp();
    156             nIt->second->SetType(type);
    157         }
    158     }
    159 
    160     return allowed;
     121    return fSignature.String();
    161122}
    162123
    163124
    AppUsage::Allowed()  
    168129}
    169130
    170131
    171 NotificationReceived*
    172 AppUsage::NotificationAt(int32 index)
    173 {
    174     notification_t::iterator nIt = fNotifications.begin();
    175     for (int32 i = 0; i < index; i++)
    176         nIt++;
    177 
    178     return nIt->second;
    179 }
    180 
    181 
    182 int32
    183 AppUsage::Notifications()
    184 {
    185     return fNotifications.size();
    186 }
    187 
    188 
    189132void
    190 AppUsage::AddNotification(NotificationReceived* notification)
     133AppUsage::SetAllowed(bool allow)
    191134{
    192     fNotifications[notification->Title()] = notification;
     135    fAllow = allow;
    193136}
  • src/servers/notification/NotificationServer.cpp

    diff --git a/src/servers/notification/NotificationServer.cpp b/src/servers/notification/NotificationServer.cpp
    index 27cf979..23eef11 100644
    a b  
    11/*
    2  * Copyright 2010-2015, Haiku, Inc. All Rights Reserved.
     2 * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
    33 * Distributed under the terms of the MIT License.
    44 *
    55 * Authors:
     
    1111
    1212#include <stdlib.h>
    1313
     14#include <Alert.h>
    1415#include <Beep.h>
    1516#include <Notifications.h>
    1617#include <PropertyInfo.h>
     18#include <Roster.h>
    1719
    1820#include "NotificationWindow.h"
    1921
    NotificationServer::MessageReceived(BMessage* message)  
    5658            if (!fWindow)
    5759                return;
    5860
    59             int32 type = 0;
    60 
    6161            // Emit a sound for this event
     62            int32 type = 0;
    6263            if (message->FindInt32("type", &type) == B_OK) {
    6364                if (type < (int32)(sizeof(kSoundNames) / sizeof(const char*)))
    6465                    system_beep(kSoundNames[type]);
  • src/servers/notification/NotificationServer.h

    diff --git a/src/servers/notification/NotificationServer.h b/src/servers/notification/NotificationServer.h
    index 50122f5..091c877 100644
    a b  
    11/*
    2  * Copyright 2010-2015, Haiku, Inc. All Rights Reserved.
     2 * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
    33 * Distributed under the terms of the MIT License.
    44 */
    55#ifndef _NOTIFICATION_SERVER_H
  • src/servers/notification/NotificationView.cpp

    diff --git a/src/servers/notification/NotificationView.cpp b/src/servers/notification/NotificationView.cpp
    index 2856b42..0f5f98e 100644
    a b  
    11/*
    2  * Copyright 2010-2011, Haiku, Inc. All Rights Reserved.
     2 * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
    33 * Copyright 2008-2009, Pier Luigi Fiorini. All Rights Reserved.
    44 * Copyright 2004-2008, Michael Davidson. All Rights Reserved.
    55 * Copyright 2004-2007, Mikael Eiman. All Rights Reserved.
     
    1111 *      Pier Luigi Fiorini, pierluigi.fiorini@gmail.com
    1212 *      Stephan Aßmus <superstippi@gmx.de>
    1313 *      Adrien Destugues <pulkomandy@pulkomandy.ath.cx>
     14 *      Brian Hill, supernova@tycho.email
    1415 */
    1516
    1617
     
    3536#include "NotificationWindow.h"
    3637
    3738
    38 static const int kIconStripeWidth = 32;
     39const int kIconStripeWidth          = 32;
     40const float kCloseSize              = 6;
     41const float kEdgePadding            = 2;
     42const float kSmallPadding           = 2;
    3943
    4044property_info message_prop_list[] = {
    4145    { "type", {B_GET_PROPERTY, B_SET_PROPERTY, 0},
    property_info message_prop_list[] = {  
    5458};
    5559
    5660
    57 NotificationView::NotificationView(NotificationWindow* win,
    58     BNotification* notification, bigtime_t timeout)
     61NotificationView::NotificationView(BNotification* notification, bigtime_t timeout,
     62    float iconSize, bool disableTimeout)
    5963    :
    6064    BView("NotificationView", B_WILL_DRAW),
    61     fParent(win),
    6265    fNotification(notification),
    6366    fTimeout(timeout),
     67    fIconSize(iconSize),
     68    fDisableTimeout(disableTimeout),
    6469    fRunner(NULL),
    6570    fBitmap(NULL),
    66     fCloseClicked(false)
     71    fCloseClicked(false),
     72    fPreviewModeOn(false)
    6773{
    6874    if (fNotification->Icon() != NULL)
    6975        fBitmap = new BBitmap(fNotification->Icon());
    7076
    71     if (fTimeout <= 0)
    72         fTimeout = fParent->Timeout() * 1000000;
    73 
    7477    BGroupLayout* layout = new BGroupLayout(B_VERTICAL);
    7578    SetLayout(layout);
    7679
    void  
    122125NotificationView::AttachedToWindow()
    123126{
    124127    SetText();
    125 
    126     BMessage msg(kRemoveView);
    127     msg.AddPointer("view", this);
    128 
    129     fRunner = new BMessageRunner(BMessenger(Parent()), &msg, fTimeout, 1);
     128   
     129    if (!fDisableTimeout) {
     130        BMessage msg(kRemoveView);
     131        msg.AddPointer("view", this);
     132        fRunner = new BMessageRunner(BMessenger(Parent()), &msg, fTimeout, 1);
     133    }
    130134}
    131135
    132136
    NotificationView::Draw(BRect updateRect)  
    238242    SetDrawingMode(B_OP_ALPHA);
    239243    SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
    240244
    241     // Icon size
    242     float iconSize = (float)fParent->IconSize();
    243 
    244245    BRect stripeRect = Bounds();
    245246    stripeRect.right = kIconStripeWidth;
    246247    SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR),
    NotificationView::Draw(BRect updateRect)  
    258259    // Draw icon
    259260    if (fBitmap) {
    260261        float ix = 18;
    261         float iy = (Bounds().Height() - iconSize) / 4.0;
     262        float iy = (Bounds().Height() - fIconSize) / 4.0;
    262263            // Icon is vertically centered in view
    263264
    264265        if (fNotification->Type() == B_PROGRESS_NOTIFICATION)
    NotificationView::Draw(BRect updateRect)  
    267268            iy -= (progRect.Height() + kEdgePadding);
    268269        }
    269270
    270         iconRect.Set(ix, iy, ix + iconSize - 1.0, iy + iconSize - 1.0);
     271        iconRect.Set(ix, iy, ix + fIconSize - 1.0, iy + fIconSize - 1.0);
    271272        DrawBitmapAsync(fBitmap, fBitmap->Bounds(), iconRect);
    272273    }
    273274
    NotificationView::Draw(BRect updateRect)  
    279280        SetFont(&l->font);
    280281        // Truncate the string. We have already line-wrapped the text but if
    281282        // there is a very long 'word' we can only truncate it.
    282         TruncateString(&(l->text), B_TRUNCATE_END,
     283        BString text(l->text);
     284        TruncateString(&text, B_TRUNCATE_END,
    283285            Bounds().Width() - l->location.x);
    284         DrawString(l->text.String(), l->text.Length(), l->location);
     286        DrawString(text.String(), text.Length(), l->location);
    285287    }
    286288
    287289    AppGroupView* groupView = dynamic_cast<AppGroupView*>(Parent());
    NotificationView::_DrawCloseButton(const BRect& updateRect)  
    333335void
    334336NotificationView::MouseDown(BPoint point)
    335337{
     338    // Preview Mode ignores any mouse clicks
     339    if (fPreviewModeOn)
     340        return;
     341
    336342    int32 buttons;
    337343    Window()->CurrentMessage()->FindInt32("buttons", &buttons);
    338344
    NotificationView::SetText(float newMaxWidth)  
    447453
    448454    float iconRight = kIconStripeWidth;
    449455    if (fBitmap != NULL)
    450         iconRight += fParent->IconSize();
     456        iconRight += fIconSize;
    451457    else
    452458        iconRight += 32;
    453459
     460    BFont boldFont(be_plain_font);
     461    boldFont.SetFace(B_BOLD_FACE);
    454462    font_height fh;
    455     be_bold_font->GetHeight(&fh);
     463    boldFont.GetHeight(&fh);
    456464    float fontHeight = ceilf(fh.leading) + ceilf(fh.descent)
    457465        + ceilf(fh.ascent);
    458     float y = 2 * fontHeight;
     466    float y = fontHeight + kEdgePadding * 2;
    459467
    460468    // Title
    461469    LineInfo* titleLine = new LineInfo;
    462470    titleLine->text = fNotification->Title();
    463     titleLine->font = *be_bold_font;
     471    titleLine->font = boldFont;
    464472
    465473    titleLine->location = BPoint(iconRight + kEdgePadding, y);
    466474
    NotificationView::SetText(float newMaxWidth)  
    548556}
    549557
    550558
     559void
     560NotificationView::SetPreviewModeOn(bool enabled)
     561{
     562    fPreviewModeOn = enabled;
     563}
     564
     565
    551566const char*
    552567NotificationView::MessageID() const
    553568{
  • src/servers/notification/NotificationView.h

    diff --git a/src/servers/notification/NotificationView.h b/src/servers/notification/NotificationView.h
    index da851cd..41b7acb 100644
    a b  
    11/*
    2  * Copyright 2010, Haiku, Inc. All Rights Reserved.
     2 * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
    33 * Copyright 2008-2009, Pier Luigi Fiorini. All Rights Reserved.
    44 * Copyright 2004-2008, Michael Davidson. All Rights Reserved.
    55 * Copyright 2004-2007, Mikael Eiman. All Rights Reserved.
    class BBitmap;  
    1818class BMessageRunner;
    1919class BNotification;
    2020
    21 class NotificationWindow;
    22 
    2321const uint32 kRemoveView = 'ReVi';
     22const float kExpandSize             = 8;
     23const float kPenSize                = 1;
    2424
    2525
    2626class NotificationView : public BView {
    2727public:
    28                                 NotificationView(NotificationWindow* win,
    29                                     BNotification* notification,
    30                                     bigtime_t timeout = -1);
     28                                NotificationView(BNotification* notification,
     29                                    bigtime_t timeout, float iconSize,
     30                                    bool disableTimeout = false);
    3131    virtual                     ~NotificationView();
    3232
    3333    virtual void                AttachedToWindow();
    public:  
    4747    virtual status_t            GetSupportedSuites(BMessage* msg);
    4848
    4949            void                SetText(float newMaxWidth = -1);
     50            void                SetPreviewModeOn(bool enabled);
    5051
    5152            const char*         MessageID() const;
    5253
    private:  
    6263
    6364            typedef std::list<LineInfo*> LineInfoList;
    6465
    65             NotificationWindow* fParent;
    6666            BNotification*      fNotification;
    6767            bigtime_t           fTimeout;
     68            float               fIconSize;
     69            bool                fDisableTimeout;
    6870
    6971            BMessageRunner*     fRunner;
    7072
    private:  
    7375            float               fHeight;
    7476            rgb_color           fStripeColor;
    7577            bool                fCloseClicked;
     78            bool                fPreviewModeOn;
    7679};
    7780
    7881#endif  // _NOTIFICATION_VIEW_H
  • src/servers/notification/NotificationWindow.cpp

    diff --git a/src/servers/notification/NotificationWindow.cpp b/src/servers/notification/NotificationWindow.cpp
    index 7a9d9aa..7a224c2 100644
    a b  
    11/*
    2  * Copyright 2010, Haiku, Inc. All Rights Reserved.
     2 * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
    33 * Copyright 2008-2009, Pier Luigi Fiorini. All Rights Reserved.
    44 * Copyright 2004-2008, Michael Davidson. All Rights Reserved.
    55 * Copyright 2004-2007, Mikael Eiman. All Rights Reserved.
     
    99 *      Michael Davidson, slaad@bong.com.au
    1010 *      Mikael Eiman, mikael@eiman.tv
    1111 *      Pier Luigi Fiorini, pierluigi.fiorini@gmail.com
     12 *      Brian Hill, supernova@tycho.email
    1213 */
    1314#include "NotificationWindow.h"
    1415
    property_info main_prop_list[] = {  
    4849};
    4950
    5051
    51 const float kCloseSize              = 6;
    52 const float kExpandSize             = 8;
    53 const float kPenSize                = 1;
    54 const float kEdgePadding            = 2;
    55 const float kSmallPadding           = 2;
    56 
    5752NotificationWindow::NotificationWindow()
    5853    :
    5954    BWindow(BRect(0, 0, -1, -1), B_TRANSLATE_MARK("Notification"),
    NotificationWindow::NotificationWindow()  
    6257        | B_NOT_RESIZABLE | B_NOT_MOVABLE | B_AUTO_UPDATE_SIZE_LIMITS,
    6358        B_ALL_WORKSPACES)
    6459{
     60    status_t result = find_directory(B_USER_CACHE_DIRECTORY, &fCachePath);
     61    fCachePath.Append("Notifications");
     62    BDirectory cacheDir;
     63    result = cacheDir.SetTo(fCachePath.Path());
     64    if(result == B_ENTRY_NOT_FOUND)
     65        cacheDir.CreateDirectory(fCachePath.Path(), NULL);
     66   
    6567    SetLayout(new BGroupLayout(B_VERTICAL, 0));
    6668
    6769    _LoadSettings(true);
    NotificationWindow::MessageReceived(BMessage* message)  
    126128            _LoadSettings();
    127129            break;
    128130        }
    129         case B_COUNT_PROPERTIES:
    130         {
    131             BMessage reply(B_REPLY);
    132             BMessage specifier;
    133             const char* property = NULL;
    134             bool messageOkay = true;
    135 
    136             if (message->FindMessage("specifiers", 0, &specifier) != B_OK)
    137                 messageOkay = false;
    138             if (specifier.FindString("property", &property) != B_OK)
    139                 messageOkay = false;
    140             if (strcmp(property, "message") != 0)
    141                 messageOkay = false;
    142 
    143             if (messageOkay)
    144                 reply.AddInt32("result", fViews.size());
    145             else {
    146                 reply.what = B_MESSAGE_NOT_UNDERSTOOD;
    147                 reply.AddInt32("error", B_ERROR);
    148             }
    149 
    150             message->SendReply(&reply);
    151             break;
    152         }
    153         case B_CREATE_PROPERTY:
    154131        case kNotificationMessage:
    155132        {
    156133            BMessage reply(B_REPLY);
    NotificationWindow::MessageReceived(BMessage* message)  
    159136            if (notification->InitCheck() == B_OK) {
    160137                bigtime_t timeout;
    161138                if (message->FindInt64("timeout", &timeout) != B_OK)
    162                     timeout = -1;
    163                 BMessenger messenger = message->ReturnAddress();
    164                 app_info info;
    165 
    166                 if (messenger.IsValid())
    167                     be_roster->GetRunningAppInfo(messenger.Team(), &info);
    168                 else
    169                     be_roster->GetAppInfo("application/x-vnd.Be-SHEL", &info);
     139                    timeout = fTimeout;
     140                BString sourceSignature(notification->SourceSignature());
     141                BString sourceName(notification->SourceName());
    170142
    171143                bool allow = false;
    172                 appfilter_t::iterator it = fAppFilters.find(info.signature);
    173 
     144                appfilter_t::iterator it =
     145                    fAppFilters.find(sourceSignature.String());
     146               
     147                AppUsage* appUsage = NULL;
    174148                if (it == fAppFilters.end()) {
    175                     AppUsage* appUsage = new AppUsage(notification->Group(),
    176                         true);
    177 
    178                     appUsage->Allowed(notification->Title(),
    179                             notification->Type());
    180                     fAppFilters[info.signature] = appUsage;
     149                    if (sourceSignature.Length() > 0
     150                        && sourceName.Length() > 0) {
     151                        appUsage = new AppUsage(sourceName.String(),
     152                            sourceSignature.String(), true);
     153                        fAppFilters[sourceSignature.String()] = appUsage;
     154                        // TODO save back to settings file
     155                    }
    181156                    allow = true;
    182157                } else {
    183                     allow = it->second->Allowed(notification->Title(),
    184                         notification->Type());
     158                    appUsage = it->second;
     159                    allow = appUsage->Allowed();
    185160                }
    186161
    187162                if (allow) {
    NotificationWindow::MessageReceived(BMessage* message)  
    196171                    } else
    197172                        group = aIt->second;
    198173
    199                     NotificationView* view = new NotificationView(this,
    200                         notification, timeout);
     174                    NotificationView* view = new NotificationView(notification,
     175                        timeout, fIconSize);
    201176
    202177                    group->AddInfo(view);
    203178
    NotificationWindow::MessageReceived(BMessage* message)  
    214189            message->SendReply(&reply);
    215190            break;
    216191        }
    217         case kRemoveView:
    218         {
    219             NotificationView* view = NULL;
    220             if (message->FindPointer("view", (void**)&view) != B_OK)
    221                 return;
    222 
    223             views_t::iterator it = find(fViews.begin(), fViews.end(), view);
    224 
    225             if (it != fViews.end())
    226                 fViews.erase(it);
    227             break;
    228         }
    229192        case kRemoveGroupView:
    230193        {
    231194            AppGroupView* view = NULL;
    NotificationWindow::MessageReceived(BMessage* message)  
    254217}
    255218
    256219
    257 BHandler*
    258 NotificationWindow::ResolveSpecifier(BMessage* msg, int32 index,
    259     BMessage* spec, int32 form, const char* prop)
    260 {
    261     BPropertyInfo prop_info(main_prop_list);
    262     BHandler* handler = NULL;
    263 
    264     if (strcmp(prop,"message") == 0) {
    265         switch (msg->what) {
    266             case B_CREATE_PROPERTY:
    267             {
    268                 msg->PopSpecifier();
    269                 handler = this;
    270                 break;
    271             }
    272             case B_SET_PROPERTY:
    273             case B_GET_PROPERTY:
    274             {
    275                 int32 i;
    276 
    277                 if (spec->FindInt32("index", &i) != B_OK)
    278                     i = -1;
    279 
    280                 if (i >= 0 && i < (int32)fViews.size()) {
    281                     msg->PopSpecifier();
    282                     handler = fViews[i];
    283                 } else
    284                     handler = NULL;
    285                 break;
    286             }
    287             case B_COUNT_PROPERTIES:
    288                 msg->PopSpecifier();
    289                 handler = this;
    290                 break;
    291             default:
    292                 break;
    293         }
    294     }
    295 
    296     if (!handler)
    297         handler = BWindow::ResolveSpecifier(msg, index, spec, form, prop);
    298 
    299     return handler;
    300 }
    301 
    302 
    303220icon_size
    304221NotificationWindow::IconSize()
    305222{
    NotificationWindow::_ShowHide()  
    337254
    338255
    339256void
    340 NotificationWindow::NotificationViewSwapped(NotificationView* stale,
    341     NotificationView* fresh)
    342 {
    343     views_t::iterator it = find(fViews.begin(), fViews.end(), stale);
    344 
    345     if (it != fViews.end())
    346         *it = fresh;
    347 }
    348 
    349 
    350 void
    351257NotificationWindow::SetPosition()
    352258{
    353259    Layout(true);
    NotificationWindow::_LoadAppFilters(BMessage& settings)  
    448354
    449355    for (int32 i = 0; i < count; i++) {
    450356        AppUsage* app = new AppUsage();
    451         settings.FindFlat("app_usage", i, app);
    452         fAppFilters[app->Name()] = app;
     357        if (settings.FindFlat("app_usage", i, app) == B_OK)
     358            fAppFilters[app->Signature()] = app;
     359        else
     360            delete app;
    453361    }
    454362}
    455363
    NotificationWindow::_LoadGeneralSettings(BMessage& settings)  
    466374    }
    467375    if (settings.FindInt32(kTimeoutName, &fTimeout) != B_OK)
    468376        fTimeout = kDefaultTimeout;
    469 
    470     // Notify the view about the change
    471     views_t::iterator it;
    472     for (it = fViews.begin(); it != fViews.end(); ++it) {
    473         NotificationView* view = (*it);
    474         view->Invalidate();
    475     }
     377    fTimeout *= 1000000;
     378        // Convert from seconds to microseconds
    476379}
    477380
    478381
    void  
    480383NotificationWindow::_LoadDisplaySettings(BMessage& settings)
    481384{
    482385    int32 setting;
     386    float originalWidth = fWidth;
    483387
    484388    if (settings.FindFloat(kWidthName, &fWidth) != B_OK)
    485389        fWidth = kDefaultWidth;
    486     GetLayout()->SetExplicitMaxSize(BSize(fWidth, B_SIZE_UNSET));
    487     GetLayout()->SetExplicitMinSize(BSize(fWidth, B_SIZE_UNSET));
     390    if (originalWidth != fWidth)
     391        GetLayout()->SetExplicitSize(BSize(fWidth, B_SIZE_UNSET));
    488392
    489393    if (settings.FindInt32(kIconSizeName, &setting) != B_OK)
    490394        fIconSize = kDefaultIconSize;
    491395    else
    492396        fIconSize = (icon_size)setting;
    493397
    494     // Notify the view about the change
    495     views_t::iterator it;
    496     for (it = fViews.begin(); it != fViews.end(); ++it) {
    497         NotificationView* view = (*it);
     398    // Notify the views about the change
     399    appview_t::iterator aIt;
     400    for (aIt = fAppViews.begin(); aIt != fAppViews.end(); ++aIt) {
     401        AppGroupView* view = aIt->second;
    498402        view->Invalidate();
    499403    }
    500404}
  • src/servers/notification/NotificationWindow.h

    diff --git a/src/servers/notification/NotificationWindow.h b/src/servers/notification/NotificationWindow.h
    index a28dd64..b296039 100644
    a b  
    11/*
    2  * Copyright 2010, Haiku, Inc. All Rights Reserved.
     2 * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
    33 * Copyright 2008-2009, Pier Luigi Fiorini. All Rights Reserved.
    44 * Copyright 2004-2008, Michael Davidson. All Rights Reserved.
    55 * Copyright 2004-2007, Mikael Eiman. All Rights Reserved.
     
    1313#include <map>
    1414
    1515#include <AppFileInfo.h>
     16#include <Path.h>
    1617#include <String.h>
    1718#include <Window.h>
    1819
    typedef std::map<BString, AppGroupView*> appview_t;  
    2829typedef std::map<BString, AppUsage*> appfilter_t;
    2930typedef std::vector<NotificationView*> views_t;
    3031
    31 extern const float kEdgePadding;
    32 extern const float kSmallPadding;
    33 extern const float kCloseSize;
    34 extern const float kExpandSize;
    35 extern const float kPenSize;
    36 
    3732const uint32 kRemoveGroupView = 'RGVi';
    3833
    3934
    public:  
    4742    virtual void                    WorkspaceActivated(int32, bool);
    4843    virtual void                    FrameResized(float width, float height);
    4944    virtual void                    ScreenChanged(BRect frame, color_space mode);
    50     virtual BHandler*               ResolveSpecifier(BMessage*, int32, BMessage*,
    51                                         int32, const char*);
    5245                                       
    5346            icon_size               IconSize();
    5447            int32                   Timeout();
    public:  
    5952private:
    6053    friend class AppGroupView;
    6154
    62             void                    NotificationViewSwapped(
    63                                         NotificationView* stale,
    64                                         NotificationView* fresh);
    65 
    6655            void                    SetPosition();
    6756            void                    _LoadSettings(bool startMonitor = false);
    6857            void                    _LoadAppFilters(BMessage& settings);
    private:  
    8069            int32                   fTimeout;
    8170
    8271            appfilter_t             fAppFilters;
     72            BPath                   fCachePath;
    8373};
    8474
    8575extern property_info main_prop_list[];