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 <Alert.h> 11 #include <Catalog.h> 12 #include <CheckBox.h> 13 #include <ColumnListView.h> 14 #include <ColumnTypes.h> 15 #include <Directory.h> 16 #include <FindDirectory.h> 17 #include <LayoutBuilder.h> 18 #include <Notification.h> 19 #include <Path.h> 20 #include <TextControl.h> 21 #include <Window.h> 22 23 #include <notification/Notifications.h> 24 #include <notification/NotificationReceived.h> 25 26 #include "NotificationsView.h" 27 28 #undef B_TRANSLATION_CONTEXT 29 #define B_TRANSLATION_CONTEXT "NotificationView" 30 31 const float kEdgePadding = 5.0; 32 const float kCLVTitlePadding = 8.0; 33 34 const int32 kApplicationSelected = '_ASL'; 35 const int32 kNotificationSelected = '_NSL'; 36 37 const int32 kCLVDeleteRow = 'av02'; 38 39 // Applications column indexes 40 const int32 kAppIndex = 0; 41 const int32 kAppEnabledIndex = 1; 42 43 // Notifications column indexes 44 const int32 kTitleIndex = 0; 45 const int32 kDateIndex = 1; 46 const int32 kTypeIndex = 2; 47 const int32 kAllowIndex = 3; 48 49 50 NotificationsView::NotificationsView(SettingsHost* host) 51 : 52 SettingsPane("apps", host) 53 { 54 BRect rect(0, 0, 100, 100); 55 56 // Search application field 57 fSearch = new BTextControl(B_TRANSLATE("Search:"), NULL, 58 new BMessage(kSettingChanged)); 59 60 // Applications list 61 fApplications = new BColumnListView(B_TRANSLATE("Applications"), 62 0, B_FANCY_BORDER, true); 63 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); 73 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); 99 100 // Add views 101 BLayoutBuilder::Group<>(this, B_VERTICAL) 102 .AddGroup(B_HORIZONTAL) 103 .AddGlue() 104 .Add(fSearch) 105 .End() 106 .Add(fApplications) 107 .Add(fNotifications) 108 .SetInsets(B_USE_WINDOW_SPACING, B_USE_WINDOW_SPACING, 109 B_USE_WINDOW_SPACING, B_USE_DEFAULT_SPACING); 110 } 111 112 113 void 114 NotificationsView::AttachedToWindow() 115 { 116 fApplications->SetTarget(this); 117 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 126 } 127 128 129 void 130 NotificationsView::MessageReceived(BMessage* msg) 131 { 132 switch (msg->what) { 133 case kApplicationSelected: 134 { 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()); 144 if (it != fAppFilters.end()) 145 _Populate(it->second); 146 147 break; 148 } 149 case kNotificationSelected: 150 break; 151 default: 152 BView::MessageReceived(msg); 153 break; 154 } 155 } 156 157 158 status_t 159 NotificationsView::Load(BMessage& settings) 160 { 161 type_code type; 162 int32 count = 0; 163 164 if (settings.GetInfo("app_usage", &type, &count) != B_OK) 165 return B_ERROR; 166 167 // Clean filters 168 appusage_t::iterator auIt; 169 for (auIt = fAppFilters.begin(); auIt != fAppFilters.end(); auIt++) 170 delete auIt->second; 171 fAppFilters.clear(); 172 173 // Add new filters 174 for (int32 i = 0; i < count; i++) { 175 AppUsage* app = new AppUsage(); 176 settings.FindFlat("app_usage", i, app); 177 fAppFilters[app->Name()] = app; 178 } 179 180 // Load the applications list 181 _PopulateApplications(); 182 183 return B_OK; 184 } 185 186 187 status_t 188 NotificationsView::Save(BMessage& storage) 189 { 190 appusage_t::iterator fIt; 191 for (fIt = fAppFilters.begin(); fIt != fAppFilters.end(); fIt++) 192 storage.AddFlat("app_usage", fIt->second); 193 194 return B_OK; 195 } 196 197 198 void 199 NotificationsView::_PopulateApplications() 200 { 201 appusage_t::iterator it; 202 203 fApplications->Clear(); 204 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 } 210 } 211 212 213 void 214 NotificationsView::_Populate(AppUsage* usage) 215 { 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 } 250 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); 256 257 fNotifications->AddRow(row); 258 } 259 } 260