1 /* 2 * Copyright 2010-2013, 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 <vector> 14 15 #include <Alert.h> 16 #include <Button.h> 17 #include <Catalog.h> 18 #include <CheckBox.h> 19 #include <Directory.h> 20 #include <File.h> 21 #include <FindDirectory.h> 22 #include <Font.h> 23 #include <LayoutBuilder.h> 24 #include <Node.h> 25 #include <Path.h> 26 #include <Query.h> 27 #include <Roster.h> 28 #include <String.h> 29 #include <StringView.h> 30 #include <SymLink.h> 31 #include <TextControl.h> 32 #include <Volume.h> 33 #include <VolumeRoster.h> 34 35 #include <notification/Notifications.h> 36 37 #include "GeneralView.h" 38 #include "SettingsHost.h" 39 40 #undef B_TRANSLATION_CONTEXT 41 #define B_TRANSLATION_CONTEXT "GeneralView" 42 const int32 kToggleNotifications = '_TSR'; 43 44 GeneralView::GeneralView(SettingsHost* host) 45 : 46 SettingsPane("general", host) 47 { 48 // Notifications 49 fNotificationBox = new BCheckBox("server", 50 B_TRANSLATE("Enable notifications"), 51 new BMessage(kToggleNotifications)); 52 53 // Autostart 54 fAutoStart = new BCheckBox("autostart", 55 B_TRANSLATE("Enable notifications at startup"), 56 new BMessage(kSettingChanged)); 57 58 // 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 68 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() 82 .SetInsets(B_USE_WINDOW_SPACING) 83 .AddGlue(); 84 } 85 86 87 void 88 GeneralView::AttachedToWindow() 89 { 90 fNotificationBox->SetTarget(this); 91 fAutoStart->SetTarget(this); 92 fTimeout->SetTarget(this); 93 } 94 95 96 void 97 GeneralView::MessageReceived(BMessage* msg) 98 { 99 switch (msg->what) { 100 case kToggleNotifications: 101 { 102 entry_ref ref; 103 104 // Check if server is available 105 if (!_CanFindServer(&ref)) { 106 BAlert* alert = new BAlert(B_TRANSLATE("Notifications"), 107 B_TRANSLATE("The notifications server cannot be" 108 " found, this means your InfoPopper installation was" 109 " not successfully completed."), B_TRANSLATE("OK"), 110 NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT); 111 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 112 (void)alert->Go(); 113 return; 114 } 115 116 if (fNotificationBox->Value() == B_CONTROL_OFF) { 117 // Server team 118 team_id team = be_roster->TeamFor(kNotificationServerSignature); 119 120 // Establish a connection to infopopper_server 121 status_t ret = B_ERROR; 122 BMessenger messenger(kNotificationServerSignature, team, &ret); 123 if (ret != B_OK) { 124 BAlert* alert = new BAlert(B_TRANSLATE( 125 "Notifications"), B_TRANSLATE("Notifications " 126 "cannot be stopped, because the server can't be" 127 " reached."), B_TRANSLATE("OK"), NULL, NULL, 128 B_WIDTH_AS_USUAL, B_STOP_ALERT); 129 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 130 (void)alert->Go(); 131 return; 132 } 133 134 // Send quit message 135 if (messenger.SendMessage(B_QUIT_REQUESTED) != B_OK) { 136 BAlert* alert = new BAlert(B_TRANSLATE( 137 "Notifications"), B_TRANSLATE("Cannot disable" 138 " notifications because the server can't be " 139 "reached."), B_TRANSLATE("OK"), 140 NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT); 141 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 142 (void)alert->Go(); 143 return; 144 } 145 } else if (!_IsServerRunning()) { 146 // Start server 147 status_t err = be_roster->Launch(kNotificationServerSignature); 148 if (err != B_OK) { 149 BAlert* alert = new BAlert(B_TRANSLATE( 150 "Notifications"), B_TRANSLATE("Cannot enable" 151 " notifications because the server cannot be " 152 "found.\nThis means your InfoPopper installation" 153 " was not successfully completed."), 154 B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_AS_USUAL, 155 B_STOP_ALERT); 156 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 157 (void)alert->Go(); 158 return; 159 } 160 } 161 break; 162 } 163 case kSettingChanged: 164 SettingsPane::MessageReceived(msg); 165 break; 166 default: 167 BView::MessageReceived(msg); 168 break; 169 } 170 } 171 172 173 status_t 174 GeneralView::Load(BMessage& settings) 175 { 176 char buffer[255]; 177 178 fNotificationBox->SetValue(_IsServerRunning() ? B_CONTROL_ON : B_CONTROL_OFF); 179 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; 192 } 193 194 195 status_t 196 GeneralView::Save(BMessage& settings) 197 { 198 bool autoStart = (fAutoStart->Value() == B_CONTROL_ON); 199 settings.AddBool(kAutoStartName, autoStart); 200 201 int32 timeout = atol(fTimeout->Text()); 202 settings.AddInt32(kTimeoutName, timeout); 203 204 return B_OK; 205 } 206 207 208 status_t 209 GeneralView::Revert() 210 { 211 return B_ERROR; 212 } 213 214 215 bool 216 GeneralView::_CanFindServer(entry_ref* ref) 217 { 218 // Try searching with be_roster 219 if (be_roster->FindApp(kNotificationServerSignature, ref) == B_OK) 220 return true; 221 222 // Try with a query and take the first result 223 BVolumeRoster vroster; 224 BVolume volume; 225 char volName[B_FILE_NAME_LENGTH]; 226 227 vroster.Rewind(); 228 229 while (vroster.GetNextVolume(&volume) == B_OK) { 230 if ((volume.InitCheck() != B_OK) || !volume.KnowsQuery()) 231 continue; 232 233 volume.GetName(volName); 234 235 BQuery *query = new BQuery(); 236 query->SetPredicate("(BEOS:APP_SIG==\"" kNotificationServerSignature 237 "\")"); 238 query->SetVolume(&volume); 239 query->Fetch(); 240 241 if (query->GetNextRef(ref) == B_OK) 242 return true; 243 } 244 245 return false; 246 } 247 248 249 bool 250 GeneralView::_IsServerRunning() 251 { 252 return be_roster->IsRunning(kNotificationServerSignature); 253 } 254