xref: /haiku/src/preferences/notifications/GeneralView.cpp (revision 97dfeb96704e5dbc5bec32ad7b21379d0125e031)
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