xref: /haiku/src/kits/app/Notification.cpp (revision 02e45e32ae6734100fa1d6f769148e0b551c034b)
1 /*
2  * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Pier Luigi Fiorini, pierluigi.fiorini@gmail.com
7  *		Stephan Aßmus, superstippi@gmx.de
8  *		Brian Hill, supernova@tycho.email
9  */
10 
11 
12 #include <Notification.h>
13 
14 #include <new>
15 
16 #include <stdlib.h>
17 #include <string.h>
18 
19 #include <notification/Notifications.h>
20 
21 #include <Bitmap.h>
22 #include <Message.h>
23 #include <NodeInfo.h>
24 #include <Path.h>
25 #include <Roster.h>
26 
27 
BNotification(notification_type type)28 BNotification::BNotification(notification_type type)
29 	:
30 	BArchivable(),
31 	fInitStatus(B_OK),
32 	fType(type),
33 	fProgress(0.f),
34 	fFile(NULL),
35 	fBitmap(NULL)
36 {
37 	team_info teamInfo;
38 	get_team_info(B_CURRENT_TEAM, &teamInfo);
39 	app_info appInfo;
40 	be_roster->GetRunningAppInfo(teamInfo.team, &appInfo);
41 
42 	int32 iconSize = B_LARGE_ICON;
43 	fBitmap = new BBitmap(BRect(0, 0, iconSize - 1, iconSize - 1), 0, B_RGBA32);
44 	if (fBitmap) {
45 		if (BNodeInfo::GetTrackerIcon(&appInfo.ref, fBitmap,
46 			icon_size(iconSize)) != B_OK) {
47 			delete fBitmap;
48 			fBitmap = NULL;
49 		}
50 	}
51 	fSourceSignature = appInfo.signature;
52 	BPath path(&appInfo.ref);
53 	if (path.InitCheck() == B_OK)
54 		fSourceName = path.Leaf();
55 }
56 
57 
BNotification(BMessage * archive)58 BNotification::BNotification(BMessage* archive)
59 	:
60 	BArchivable(archive),
61 	fInitStatus(B_OK),
62 	fProgress(0.0f),
63 	fFile(NULL),
64 	fBitmap(NULL)
65 {
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 
74 	int32 type;
75 	if (archive->FindInt32("_type", &type) == B_OK)
76 		fType = (notification_type)type;
77 	else
78 		fInitStatus = B_ERROR;
79 
80 	BString group;
81 	if (archive->FindString("_group", &group) == B_OK)
82 		SetGroup(group);
83 
84 	BString title;
85 	if (archive->FindString("_title", &title) == B_OK)
86 		SetTitle(title);
87 
88 	BString content;
89 	if (archive->FindString("_content", &content) == B_OK)
90 		SetContent(content);
91 
92 	BString messageID;
93 	if (archive->FindString("_messageID", &messageID) == B_OK)
94 		SetMessageID(messageID);
95 
96 	float progress;
97 	if (type == B_PROGRESS_NOTIFICATION
98 		&& archive->FindFloat("_progress", &progress) == B_OK)
99 		SetProgress(progress);
100 
101 	BString onClickApp;
102 	if (archive->FindString("_onClickApp", &onClickApp) == B_OK)
103 		SetOnClickApp(onClickApp);
104 
105 	entry_ref onClickFile;
106 	if (archive->FindRef("_onClickFile", &onClickFile) == B_OK)
107 		SetOnClickFile(&onClickFile);
108 
109 	entry_ref onClickRef;
110 	int32 index = 0;
111 	while (archive->FindRef("_onClickRef", index++, &onClickRef) == B_OK)
112 		AddOnClickRef(&onClickRef);
113 
114 	BString onClickArgv;
115 	index = 0;
116 	while (archive->FindString("_onClickArgv", index++, &onClickArgv) == B_OK)
117 		AddOnClickArg(onClickArgv);
118 
119 	status_t ret = B_OK;
120 	BMessage icon;
121 	if ((ret = archive->FindMessage("_icon", &icon)) == B_OK) {
122 		BBitmap bitmap(&icon);
123 		ret = bitmap.InitCheck();
124 		if (ret == B_OK)
125 			ret = SetIcon(&bitmap);
126 	}
127 }
128 
129 
~BNotification()130 BNotification::~BNotification()
131 {
132 	delete fFile;
133 	delete fBitmap;
134 
135 	for (int32 i = fRefs.CountItems() - 1; i >= 0; i--)
136 		delete (entry_ref*)fRefs.ItemAtFast(i);
137 
138 	for (int32 i = fArgv.CountItems() - 1; i >= 0; i--)
139 		free(fArgv.ItemAtFast(i));
140 }
141 
142 
143 status_t
InitCheck() const144 BNotification::InitCheck() const
145 {
146 	return fInitStatus;
147 }
148 
149 
150 BArchivable*
Instantiate(BMessage * archive)151 BNotification::Instantiate(BMessage* archive)
152 {
153 	if (validate_instantiation(archive, "BNotification"))
154 		return new(std::nothrow) BNotification(archive);
155 
156 	return NULL;
157 }
158 
159 
160 status_t
Archive(BMessage * archive,bool deep) const161 BNotification::Archive(BMessage* archive, bool deep) const
162 {
163 	status_t status = BArchivable::Archive(archive, deep);
164 
165 	if (status == B_OK)
166 		status = archive->AddString("_appname", fSourceName);
167 
168 	if (status == B_OK)
169 		status = archive->AddString("_signature", fSourceSignature);
170 
171 	if (status == B_OK)
172 		status = archive->AddInt32("_type", (int32)fType);
173 
174 	if (status == B_OK && Group() != NULL)
175 		status = archive->AddString("_group", Group());
176 
177 	if (status == B_OK && Title() != NULL)
178 		status = archive->AddString("_title", Title());
179 
180 	if (status == B_OK && Content() != NULL)
181 		status = archive->AddString("_content", Content());
182 
183 	if (status == B_OK && MessageID() != NULL)
184 		status = archive->AddString("_messageID", MessageID());
185 
186 	if (status == B_OK && Type() == B_PROGRESS_NOTIFICATION)
187 		status = archive->AddFloat("_progress", Progress());
188 
189 	if (status == B_OK && OnClickApp() != NULL)
190 		status = archive->AddString("_onClickApp", OnClickApp());
191 
192 	if (status == B_OK && OnClickFile() != NULL)
193 		status = archive->AddRef("_onClickFile", OnClickFile());
194 
195 	if (status == B_OK) {
196 		for (int32 i = 0; i < CountOnClickRefs(); i++) {
197 			status = archive->AddRef("_onClickRef", OnClickRefAt(i));
198 			if (status != B_OK)
199 				break;
200 		}
201 	}
202 
203 	if (status == B_OK) {
204 		for (int32 i = 0; i < CountOnClickArgs(); i++) {
205 			status = archive->AddString("_onClickArgv", OnClickArgAt(i));
206 			if (status != B_OK)
207 				break;
208 		}
209 	}
210 
211 	if (status == B_OK) {
212 		const BBitmap* icon = Icon();
213 		if (icon != NULL) {
214 			BMessage iconArchive;
215 			status = icon->Archive(&iconArchive);
216 			if (status == B_OK)
217 				archive->AddMessage("_icon", &iconArchive);
218 		}
219 	}
220 
221 	return status;
222 }
223 
224 
225 const char*
SourceSignature() const226 BNotification::SourceSignature() const
227 {
228 	return fSourceSignature;
229 }
230 
231 
232 const char*
SourceName() const233 BNotification::SourceName() const
234 {
235 	return fSourceName;
236 }
237 
238 
239 notification_type
Type() const240 BNotification::Type() const
241 {
242 	return fType;
243 }
244 
245 
246 const char*
Group() const247 BNotification::Group() const
248 {
249 	if (fGroup == "")
250 		return NULL;
251 	return fGroup;
252 }
253 
254 
255 void
SetGroup(const BString & group)256 BNotification::SetGroup(const BString& group)
257 {
258 	fGroup = group;
259 }
260 
261 
262 const char*
Title() const263 BNotification::Title() const
264 {
265 	if (fTitle == "")
266 		return NULL;
267 	return fTitle;
268 }
269 
270 
271 void
SetTitle(const BString & title)272 BNotification::SetTitle(const BString& title)
273 {
274 	fTitle = title;
275 }
276 
277 
278 const char*
Content() const279 BNotification::Content() const
280 {
281 	if (fContent == "")
282 		return NULL;
283 	return fContent;
284 }
285 
286 
287 void
SetContent(const BString & content)288 BNotification::SetContent(const BString& content)
289 {
290 	fContent = content;
291 }
292 
293 
294 const char*
MessageID() const295 BNotification::MessageID() const
296 {
297 	if (fID == "")
298 		return NULL;
299 	return fID;
300 }
301 
302 
303 void
SetMessageID(const BString & id)304 BNotification::SetMessageID(const BString& id)
305 {
306 	fID = id;
307 }
308 
309 
310 float
Progress() const311 BNotification::Progress() const
312 {
313 	if (fType != B_PROGRESS_NOTIFICATION)
314 		return -1;
315 	return fProgress;
316 }
317 
318 
319 void
SetProgress(float progress)320 BNotification::SetProgress(float progress)
321 {
322 	if (progress < 0)
323 		fProgress = 0;
324 	else if (progress > 1)
325 		fProgress = 1;
326 	else
327 		fProgress = progress;
328 }
329 
330 
331 const char*
OnClickApp() const332 BNotification::OnClickApp() const
333 {
334 	if (fApp == "")
335 		return NULL;
336 	return fApp;
337 }
338 
339 
340 void
SetOnClickApp(const BString & app)341 BNotification::SetOnClickApp(const BString& app)
342 {
343 	fApp = app;
344 }
345 
346 
347 const entry_ref*
OnClickFile() const348 BNotification::OnClickFile() const
349 {
350 	return fFile;
351 }
352 
353 
354 status_t
SetOnClickFile(const entry_ref * file)355 BNotification::SetOnClickFile(const entry_ref* file)
356 {
357 	delete fFile;
358 
359 	if (file != NULL) {
360 		fFile = new(std::nothrow) entry_ref(*file);
361 		if (fFile == NULL)
362 			return B_NO_MEMORY;
363 	} else
364 		fFile = NULL;
365 
366 	return B_OK;
367 }
368 
369 
370 status_t
AddOnClickRef(const entry_ref * ref)371 BNotification::AddOnClickRef(const entry_ref* ref)
372 {
373 	if (ref == NULL)
374 		return B_BAD_VALUE;
375 
376 	entry_ref* clonedRef = new(std::nothrow) entry_ref(*ref);
377 	if (clonedRef == NULL || !fRefs.AddItem(clonedRef))
378 		return B_NO_MEMORY;
379 
380 	return B_OK;
381 }
382 
383 
384 int32
CountOnClickRefs() const385 BNotification::CountOnClickRefs() const
386 {
387 	return fRefs.CountItems();
388 }
389 
390 
391 const entry_ref*
OnClickRefAt(int32 index) const392 BNotification::OnClickRefAt(int32 index) const
393 {
394 	return (entry_ref*)fRefs.ItemAt(index);
395 }
396 
397 
398 status_t
AddOnClickArg(const BString & arg)399 BNotification::AddOnClickArg(const BString& arg)
400 {
401 	char* clonedArg = strdup(arg.String());
402 	if (clonedArg == NULL || !fArgv.AddItem(clonedArg))
403 		return B_NO_MEMORY;
404 
405 	return B_OK;
406 }
407 
408 
409 int32
CountOnClickArgs() const410 BNotification::CountOnClickArgs() const
411 {
412 	return fArgv.CountItems();
413 }
414 
415 
416 const char*
OnClickArgAt(int32 index) const417 BNotification::OnClickArgAt(int32 index) const
418 {
419 	return (char*)fArgv.ItemAt(index);
420 }
421 
422 
423 const BBitmap*
Icon() const424 BNotification::Icon() const
425 {
426 	return fBitmap;
427 }
428 
429 
430 status_t
SetIcon(const BBitmap * icon)431 BNotification::SetIcon(const BBitmap* icon)
432 {
433 	delete fBitmap;
434 
435 	if (icon != NULL) {
436 		fBitmap = new(std::nothrow) BBitmap(icon);
437 		if (fBitmap == NULL)
438 			return B_NO_MEMORY;
439 		return fBitmap->InitCheck();
440 	}
441 
442 	fBitmap = NULL;
443 	return B_OK;
444 }
445 
446 
447 status_t
Send(bigtime_t timeout)448 BNotification::Send(bigtime_t timeout)
449 {
450 	BMessage msg(kNotificationMessage);
451 
452 	// Archive notification
453 	status_t ret = Archive(&msg);
454 
455 	// Custom time out
456 	if (ret == B_OK && timeout > 0)
457 		ret = msg.AddInt64("timeout", timeout);
458 
459 	// Send message
460 	if (ret == B_OK) {
461 		BMessenger server(kNotificationServerSignature);
462 		ret = server.SendMessage(&msg);
463 	}
464 
465 	return ret;
466 }
467 
468 
_ReservedNotification1()469 void BNotification::_ReservedNotification1() {}
_ReservedNotification2()470 void BNotification::_ReservedNotification2() {}
_ReservedNotification3()471 void BNotification::_ReservedNotification3() {}
_ReservedNotification4()472 void BNotification::_ReservedNotification4() {}
_ReservedNotification5()473 void BNotification::_ReservedNotification5() {}
_ReservedNotification6()474 void BNotification::_ReservedNotification6() {}
_ReservedNotification7()475 void BNotification::_ReservedNotification7() {}
_ReservedNotification8()476 void BNotification::_ReservedNotification8() {}
477