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 <Roster.h> 16 #include <GroupLayout.h> 17 #include <GroupLayoutBuilder.h> 18 #include <Alert.h> 19 #include <Font.h> 20 #include <Button.h> 21 #include <Catalog.h> 22 #include <StringView.h> 23 #include <TextControl.h> 24 #include <CheckBox.h> 25 #include <String.h> 26 #include <FindDirectory.h> 27 #include <Node.h> 28 #include <notification/Notifications.h> 29 #include <Path.h> 30 #include <File.h> 31 #include <Directory.h> 32 #include <VolumeRoster.h> 33 #include <Volume.h> 34 #include <Query.h> 35 #include <SymLink.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 // Calculate inset 69 float inset = ceilf(be_plain_font->Size() * 0.7f); 70 71 SetLayout(new BGroupLayout(B_VERTICAL)); 72 AddChild(BGroupLayoutBuilder(B_VERTICAL, inset) 73 .AddGroup(B_HORIZONTAL, inset) 74 .Add(fNotificationBox) 75 .AddGlue() 76 .End() 77 78 .AddGroup(B_VERTICAL, inset) 79 .Add(fAutoStart) 80 .AddGroup(B_HORIZONTAL) 81 .AddGroup(B_HORIZONTAL, 2) 82 .Add(fTimeout) 83 .Add(displayTimeLabel) 84 .End() 85 .End() 86 .End() 87 .SetInsets(inset, inset, inset, inset) 88 .AddGlue() 89 ); 90 } 91 92 93 void 94 GeneralView::AttachedToWindow() 95 { 96 fNotificationBox->SetTarget(this); 97 fAutoStart->SetTarget(this); 98 fTimeout->SetTarget(this); 99 } 100 101 102 void 103 GeneralView::MessageReceived(BMessage* msg) 104 { 105 switch (msg->what) { 106 case kToggleNotifications: 107 { 108 entry_ref ref; 109 110 // Check if server is available 111 if (!_CanFindServer(&ref)) { 112 BAlert* alert = new BAlert(B_TRANSLATE("Notifications"), 113 B_TRANSLATE("The notifications server cannot be" 114 " found, this means your InfoPopper installation was" 115 " not successfully completed."), B_TRANSLATE("OK"), 116 NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT); 117 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 118 (void)alert->Go(); 119 return; 120 } 121 122 if (fNotificationBox->Value() == B_CONTROL_OFF) { 123 // Server team 124 team_id team = be_roster->TeamFor(kNotificationServerSignature); 125 126 // Establish a connection to infopopper_server 127 status_t ret = B_ERROR; 128 BMessenger messenger(kNotificationServerSignature, team, &ret); 129 if (ret != B_OK) { 130 BAlert* alert = new BAlert(B_TRANSLATE( 131 "Notifications"), B_TRANSLATE("Notifications " 132 "cannot be stopped, because the server can't be" 133 " reached."), B_TRANSLATE("OK"), NULL, NULL, 134 B_WIDTH_AS_USUAL, B_STOP_ALERT); 135 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 136 (void)alert->Go(); 137 return; 138 } 139 140 // Send quit message 141 if (messenger.SendMessage(B_QUIT_REQUESTED) != B_OK) { 142 BAlert* alert = new BAlert(B_TRANSLATE( 143 "Notifications"), B_TRANSLATE("Cannot disable" 144 " notifications because the server can't be " 145 "reached."), B_TRANSLATE("OK"), 146 NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT); 147 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 148 (void)alert->Go(); 149 return; 150 } 151 } else if (!_IsServerRunning()) { 152 // Start server 153 status_t err = be_roster->Launch(kNotificationServerSignature); 154 if (err != B_OK) { 155 BAlert* alert = new BAlert(B_TRANSLATE( 156 "Notifications"), B_TRANSLATE("Cannot enable" 157 " notifications because the server cannot be " 158 "found.\nThis means your InfoPopper installation" 159 " was not successfully completed."), 160 B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_AS_USUAL, 161 B_STOP_ALERT); 162 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 163 (void)alert->Go(); 164 return; 165 } 166 } 167 break; 168 } 169 case kSettingChanged: 170 SettingsPane::MessageReceived(msg); 171 break; 172 default: 173 BView::MessageReceived(msg); 174 break; 175 } 176 } 177 178 179 status_t 180 GeneralView::Load(BMessage& settings) 181 { 182 char buffer[255]; 183 184 fNotificationBox->SetValue(_IsServerRunning() ? B_CONTROL_ON : B_CONTROL_OFF); 185 186 bool autoStart; 187 if (settings.FindBool(kAutoStartName, &autoStart) != B_OK) 188 autoStart = kDefaultAutoStart; 189 fAutoStart->SetValue(autoStart ? B_CONTROL_ON : B_CONTROL_OFF); 190 191 int32 timeout; 192 if (settings.FindInt32(kTimeoutName, &timeout) != B_OK) 193 timeout = kDefaultTimeout; 194 (void)sprintf(buffer, "%" B_PRId32, timeout); 195 fTimeout->SetText(buffer); 196 197 return B_OK; 198 } 199 200 201 status_t 202 GeneralView::Save(BMessage& settings) 203 { 204 bool autoStart = (fAutoStart->Value() == B_CONTROL_ON); 205 settings.AddBool(kAutoStartName, autoStart); 206 207 int32 timeout = atol(fTimeout->Text()); 208 settings.AddInt32(kTimeoutName, timeout); 209 210 return B_OK; 211 } 212 213 214 status_t 215 GeneralView::Revert() 216 { 217 return B_ERROR; 218 } 219 220 221 bool 222 GeneralView::_CanFindServer(entry_ref* ref) 223 { 224 // Try searching with be_roster 225 if (be_roster->FindApp(kNotificationServerSignature, ref) == B_OK) 226 return true; 227 228 // Try with a query and take the first result 229 BVolumeRoster vroster; 230 BVolume volume; 231 char volName[B_FILE_NAME_LENGTH]; 232 233 vroster.Rewind(); 234 235 while (vroster.GetNextVolume(&volume) == B_OK) { 236 if ((volume.InitCheck() != B_OK) || !volume.KnowsQuery()) 237 continue; 238 239 volume.GetName(volName); 240 241 BQuery *query = new BQuery(); 242 query->SetPredicate("(BEOS:APP_SIG==\""kNotificationServerSignature"\")"); 243 query->SetVolume(&volume); 244 query->Fetch(); 245 246 if (query->GetNextRef(ref) == B_OK) 247 return true; 248 } 249 250 return false; 251 } 252 253 254 bool 255 GeneralView::_IsServerRunning() 256 { 257 return be_roster->IsRunning(kNotificationServerSignature); 258 } 259