xref: /haiku/src/apps/deskbar/BarApp.cpp (revision e36a1b58e6daf3efeec46621114691ef499faafc)
1 /*
2 Open Tracker License
3 
4 Terms and Conditions
5 
6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
7 
8 Permission is hereby granted, free of charge, to any person obtaining a copy of
9 this software and associated documentation files (the "Software"), to deal in
10 the Software without restriction, including without limitation the rights to
11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12 of the Software, and to permit persons to whom the Software is furnished to do
13 so, subject to the following conditions:
14 
15 The above copyright notice and this permission notice applies to all licensees
16 and shall be included in all copies or substantial portions of the Software.
17 
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 
25 Except as contained in this notice, the name of Be Incorporated shall not be
26 used in advertising or otherwise to promote the sale, use or other dealings in
27 this Software without prior written authorization from Be Incorporated.
28 
29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
30 of Be Incorporated in the United States and other countries. Other brand product
31 names are registered trademarks or trademarks of their respective holders.
32 All rights reserved.
33 */
34 
35 #include <Debug.h>
36 #include <stdlib.h>
37 #include <string.h>
38 
39 #include <AppFileInfo.h>
40 #include <Autolock.h>
41 #include <Bitmap.h>
42 #include <Directory.h>
43 #include <Dragger.h>
44 #include <File.h>
45 #include <FindDirectory.h>
46 #include <Mime.h>
47 #include <Path.h>
48 #include <Roster.h>
49 
50 #if __HAIKU__
51 #	include <RosterPrivate.h>
52 #endif
53 
54 #include "icons.h"
55 #include "tracker_private.h"
56 #include "BarApp.h"
57 #include "BarView.h"
58 #include "BarWindow.h"
59 #include "DeskBarUtils.h"
60 #include "FSUtils.h"
61 #include "PublicCommands.h"
62 #include "ResourceSet.h"
63 #include "Switcher.h"
64 #include "TeamMenu.h"
65 #include "WindowMenuItem.h"
66 
67 
68 // private Be API
69 extern void __set_window_decor(int32 theme);
70 
71 BLocker TBarApp::sSubscriberLock;
72 BList TBarApp::sBarTeamInfoList;
73 BList TBarApp::sSubscribers;
74 
75 
76 const uint32 kShowBeMenu = 'BeMn';
77 const uint32 kShowTeamMenu = 'TmMn';
78 
79 const BRect kIconSize(0.0f, 0.0f, 15.0f, 15.0f);
80 
81 #if __HAIKU__
82 	static const color_space kIconFormat = B_RGBA32;
83 #else
84 	static const color_space kIconFormat = B_CMAP8;
85 #endif
86 
87 
88 
89 int
90 main()
91 {
92 	TBarApp app;
93 	app.Run();
94 
95 	return B_OK;
96 }
97 
98 
99 TBarApp::TBarApp()
100 	:	BApplication(kDeskbarSignature),
101 		fSettingsFile(NULL),
102 		fPreferencesWindow(NULL)
103 {
104 	InitSettings();
105 	InitIconPreloader();
106 
107 #ifdef __HAIKU__
108 	be_roster->StartWatching(this);
109 #endif
110 
111 	sBarTeamInfoList.MakeEmpty();
112 
113 	BList teamList;
114 	int32 numTeams;
115 	be_roster->GetAppList(&teamList);
116 	numTeams = teamList.CountItems();
117 	for (int32 i = 0; i < numTeams; i++) {
118 		app_info appInfo;
119 		team_id tID = (team_id)teamList.ItemAt(i);
120 		if (be_roster->GetRunningAppInfo(tID, &appInfo) == B_OK) {
121 			AddTeam(appInfo.team, appInfo.flags, appInfo.signature,
122 				&appInfo.ref);
123 		}
124 	}
125 
126 	sSubscribers.MakeEmpty();
127 
128 	fSwitcherMessenger = BMessenger(new TSwitchManager(fSettings.switcherLoc));
129 
130 	fBarWindow = new TBarWindow();
131 	fBarWindow->Show();
132 
133 	// this messenger now targets the barview instead of the
134 	// statusview so that all additions to the tray
135 	// follow the same path
136 	fStatusViewMessenger = BMessenger(fBarWindow->FindView("BarView"));
137 }
138 
139 
140 TBarApp::~TBarApp()
141 {
142 #ifdef __HAIKU__
143 	be_roster->StopWatching(this);
144 #endif
145 
146 	int32 teamCount = sBarTeamInfoList.CountItems();
147 	for (int32 i = 0; i < teamCount; i++) {
148 		BarTeamInfo *barInfo = (BarTeamInfo *)sBarTeamInfoList.ItemAt(i);
149 		delete barInfo;
150 	}
151 
152 	int32 subsCount = sSubscribers.CountItems();
153 	for (int32 i = 0; i < subsCount; i++) {
154 		BMessenger *messenger = static_cast<BMessenger *>(sSubscribers.ItemAt(i));
155 		delete messenger;
156 	}
157 	SaveSettings();
158 	delete fSettingsFile;
159 }
160 
161 
162 bool
163 TBarApp::QuitRequested()
164 {
165 	// don't allow user quitting
166 	if (CurrentMessage() && CurrentMessage()->FindBool("shortcut")) {
167 		// but allow quitting to hide fPreferencesWindow
168 		int32 index = 0;
169 		BWindow* window = NULL;
170 		while ((window = WindowAt(index++)) != NULL) {
171 			if (window == fPreferencesWindow) {
172 				if (fPreferencesWindow->Lock()) {
173 					if (fPreferencesWindow->IsActive())
174 						fPreferencesWindow->PostMessage(B_QUIT_REQUESTED);
175 					fPreferencesWindow->Unlock();
176 				}
177 				break;
178 			}
179 		}
180 		return false;
181 	}
182 
183 	// system quitting, call inherited to notify all loopers
184 	fBarWindow->SaveSettings();
185 	BApplication::QuitRequested();
186 	return true;
187 }
188 
189 
190 void
191 TBarApp::SaveSettings()
192 {
193 	if (fSettingsFile->InitCheck() == B_OK) {
194 		fSettingsFile->Seek(0, SEEK_SET);
195 		fSettingsFile->Write(&fSettings.vertical, sizeof(bool));
196 		fSettingsFile->Write(&fSettings.left, sizeof(bool));
197 		fSettingsFile->Write(&fSettings.top, sizeof(bool));
198 		fSettingsFile->Write(&fSettings.ampmMode, sizeof(bool));
199 		fSettingsFile->Write(&fSettings.state, sizeof(uint32));
200 		fSettingsFile->Write(&fSettings.width, sizeof(float));
201 		fSettingsFile->Write(&fSettings.showTime, sizeof(bool));
202 		fSettingsFile->Write(&fSettings.switcherLoc, sizeof(BPoint));
203 		fSettingsFile->Write(&fSettings.recentAppsCount, sizeof(int32));
204 		fSettingsFile->Write(&fSettings.recentDocsCount, sizeof(int32));
205 		fSettingsFile->Write(&fSettings.timeShowSeconds, sizeof(bool));
206 		fSettingsFile->Write(&fSettings.timeShowMil, sizeof(bool));
207 		fSettingsFile->Write(&fSettings.recentFoldersCount, sizeof(int32));
208 		fSettingsFile->Write(&fSettings.timeShowEuro, sizeof(bool));
209 		fSettingsFile->Write(&fSettings.alwaysOnTop, sizeof(bool));
210 		fSettingsFile->Write(&fSettings.timeFullDate, sizeof(bool));
211 		fSettingsFile->Write(&fSettings.trackerAlwaysFirst, sizeof(bool));
212 		fSettingsFile->Write(&fSettings.sortRunningApps, sizeof(bool));
213 		fSettingsFile->Write(&fSettings.superExpando, sizeof(bool));
214 		fSettingsFile->Write(&fSettings.expandNewTeams, sizeof(bool));
215 		fSettingsFile->Write(&fSettings.autoRaise, sizeof(bool));
216 	}
217 }
218 
219 
220 void
221 TBarApp::InitSettings()
222 {
223 	desk_settings settings;
224 	settings.vertical = true;
225 	settings.left = false;
226 	settings.top = true;
227 	settings.ampmMode = true;
228 	settings.showTime = true;
229 	settings.state = kExpandoState;
230 	settings.width = 0;
231 	settings.switcherLoc = BPoint(5000, 5000);
232 	settings.recentAppsCount = 10;
233 	settings.recentDocsCount = 10;
234 	settings.timeShowSeconds = false;
235 	settings.timeShowMil = false;
236 	settings.recentFoldersCount = 10;
237 	settings.timeShowEuro = false;
238 	settings.alwaysOnTop = false;
239 	settings.timeFullDate = false;
240 	settings.trackerAlwaysFirst = false;
241 	settings.sortRunningApps = false;
242 	settings.superExpando = false;
243 	settings.expandNewTeams = false;
244 	settings.autoRaise = false;
245 
246 	BPath dirPath;
247 	const char *settingsFileName = "Deskbar_settings";
248 
249 	find_directory(B_USER_DESKBAR_DIRECTORY, &dirPath, true);
250 	// just make it
251 
252 	if (find_directory (B_USER_SETTINGS_DIRECTORY, &dirPath, true) == B_OK) {
253 		BPath filePath = dirPath;
254 		filePath.Append(settingsFileName);
255 		fSettingsFile = new BFile(filePath.Path(), O_RDWR);
256 		if (fSettingsFile->InitCheck() != B_OK) {
257 			BDirectory theDir(dirPath.Path());
258 			if (theDir.InitCheck() == B_OK)
259 				theDir.CreateFile(settingsFileName, fSettingsFile);
260 		}
261 
262 		if (fSettingsFile->InitCheck() == B_OK) {
263 			off_t size = 0;
264 			fSettingsFile->GetSize(&size);
265 
266 			if (size >= kValidSettingsSize1) {
267 				fSettingsFile->Seek(0, SEEK_SET);
268 				fSettingsFile->Read(&settings.vertical, sizeof(bool));
269 				fSettingsFile->Read(&settings.left, sizeof(bool));
270 				fSettingsFile->Read(&settings.top, sizeof(bool));
271 				fSettingsFile->Read(&settings.ampmMode, sizeof(bool));
272 				fSettingsFile->Read(&settings.state, sizeof(uint32));
273 				fSettingsFile->Read(&settings.width, sizeof(float));
274 				fSettingsFile->Read(&settings.showTime, sizeof(bool));
275 			}
276 			if (size >= kValidSettingsSize2)
277 				fSettingsFile->Read(&settings.switcherLoc, sizeof(BPoint));
278 			if (size >= kValidSettingsSize3) {
279 				fSettingsFile->Read(&settings.recentAppsCount, sizeof(int32));
280 				fSettingsFile->Read(&settings.recentDocsCount, sizeof(int32));
281 			}
282 			if (size >= kValidSettingsSize4) {
283 				fSettingsFile->Read(&settings.timeShowSeconds, sizeof(bool));
284 				fSettingsFile->Read(&settings.timeShowMil, sizeof(bool));
285 			}
286 			if (size >= kValidSettingsSize5)
287 				fSettingsFile->Read(&settings.recentFoldersCount, sizeof(int32));
288 			if (size >= kValidSettingsSize6) {
289 				fSettingsFile->Read(&settings.timeShowEuro, sizeof(bool));
290 				fSettingsFile->Read(&settings.alwaysOnTop, sizeof(bool));
291 			}
292 			if (size >= kValidSettingsSize7)
293 				fSettingsFile->Read(&settings.timeFullDate, sizeof(bool));
294 			if (size >= kValidSettingsSize8) {
295 				fSettingsFile->Read(&settings.trackerAlwaysFirst, sizeof(bool));
296 				fSettingsFile->Read(&settings.sortRunningApps, sizeof(bool));
297 			}
298 			if (size >= kValidSettingsSize9) {
299 				fSettingsFile->Read(&settings.superExpando, sizeof(bool));
300 				fSettingsFile->Read(&settings.expandNewTeams, sizeof(bool));
301 			}
302 			if (size >= kValidSettingsSize10)
303 				fSettingsFile->Read(&settings.autoRaise, sizeof(bool));
304 		}
305 	}
306 
307 	fSettings = settings;
308 }
309 
310 
311 void
312 TBarApp::MessageReceived(BMessage *message)
313 {
314 	int32 count;
315 	switch (message->what) {
316 		case 'gloc':
317 		case 'sloc':
318 		case 'gexp':
319 		case 'sexp':
320 		case 'info':
321 		case 'exst':
322 		case 'cwnt':
323 		case 'icon':
324 		case 'remv':
325 		case 'adon':
326 			// pass any BDeskbar originating messages on to the window
327 			fBarWindow->PostMessage(message);
328 			break;
329 
330 		case kConfigShow:
331 			ShowPreferencesWindow();
332 			break;
333 
334 		case kShowBeMenu:
335 			if (fBarWindow->Lock()) {
336 				fBarWindow->ShowBeMenu();
337 				fBarWindow->Unlock();
338 			}
339 			break;
340 
341 		case kShowTeamMenu:
342 			if (fBarWindow->Lock()) {
343 				fBarWindow->ShowTeamMenu();
344 				fBarWindow->Unlock();
345 			}
346 			break;
347 
348 		case kUpdateRecentCounts:
349 			if (message->FindInt32("applications", &count) == B_OK)
350 				fSettings.recentAppsCount = count;
351 			if (message->FindInt32("folders", &count) == B_OK)
352 				fSettings.recentFoldersCount = count;
353 			if (message->FindInt32("documents", &count) == B_OK)
354 				fSettings.recentDocsCount = count;
355 			break;
356 
357 		case kConfigClose:
358 			fPreferencesWindow = NULL;
359 			break;
360 
361 		case B_SOME_APP_LAUNCHED:
362 		{
363 			team_id team = -1;
364 			message->FindInt32("be:team", &team);
365 
366 			uint32 flags = 0;
367 			message->FindInt32("be:flags", (long *)&flags);
368 
369 			const char *sig = NULL;
370 			message->FindString("be:signature", &sig);
371 
372 			entry_ref ref;
373 			message->FindRef("be:ref", &ref);
374 
375 			AddTeam(team, flags, sig, &ref);
376 			break;
377 		}
378 
379 		case B_SOME_APP_QUIT:
380 		{
381 			team_id team = -1;
382 			message->FindInt32("be:team", &team);
383 			RemoveTeam(team);
384 			break;
385 		}
386 
387 		case B_ARCHIVED_OBJECT:
388 			// TODO: what's this???
389 			message->AddString("special", "Alex Osadzinski");
390 			fStatusViewMessenger.SendMessage(message);
391 			break;
392 
393 		case msg_Be:
394 			__set_window_decor(0);
395 			break;
396 
397 		case msg_Win95:
398 			__set_window_decor(2);
399 			break;
400 
401 		case msg_Amiga:
402 			__set_window_decor(1);
403 			break;
404 
405 		case msg_Mac:
406 			__set_window_decor(3);
407 			break;
408 
409 		case msg_ToggleDraggers:
410 			if (BDragger::AreDraggersDrawn())
411 				BDragger::HideAllDraggers();
412 			else
413 				BDragger::ShowAllDraggers();
414 			break;
415 
416 		case msg_AlwaysTop:
417  			fSettings.alwaysOnTop = !fSettings.alwaysOnTop;
418 
419  			fBarWindow->SetFeel(fSettings.alwaysOnTop ?
420  				B_FLOATING_ALL_WINDOW_FEEL : B_NORMAL_WINDOW_FEEL);
421  			break;
422 
423 		case msg_AutoRaise:
424 		{
425 			fSettings.autoRaise = !fSettings.autoRaise;
426 
427 			TBarView *barView = static_cast<TBarApp *>(be_app)->BarView();
428 			fBarWindow->Lock();
429 			barView->UpdateAutoRaise();
430 			fBarWindow->Unlock();
431 			break;
432 		}
433 
434 		case msg_trackerFirst:
435 		{
436 			fSettings.trackerAlwaysFirst = !fSettings.trackerAlwaysFirst;
437 
438 			TBarView *barView = static_cast<TBarApp *>(be_app)->BarView();
439 			fBarWindow->Lock();
440 			barView->UpdatePlacement();
441 			fBarWindow->Unlock();
442 			break;
443 		}
444 
445 		case msg_sortRunningApps:
446 		{
447 			fSettings.sortRunningApps = !fSettings.sortRunningApps;
448 
449 			TBarView *barView = static_cast<TBarApp *>(be_app)->BarView();
450 			fBarWindow->Lock();
451 			barView->UpdatePlacement();
452 			fBarWindow->Unlock();
453 			break;
454 		}
455 
456 		case msg_Unsubscribe:
457 		{
458 			BMessenger messenger;
459 			if (message->FindMessenger("messenger", &messenger) == B_OK)
460 				Unsubscribe(messenger);
461 			break;
462 		}
463 
464 		case msg_superExpando:
465 		{
466 			fSettings.superExpando = !fSettings.superExpando;
467 
468 			TBarView *barView = static_cast<TBarApp *>(be_app)->BarView();
469 			fBarWindow->Lock();
470 			barView->UpdatePlacement();
471 			fBarWindow->Unlock();
472 			break;
473 		}
474 
475 		case msg_expandNewTeams:
476 		{
477 			fSettings.expandNewTeams = !fSettings.expandNewTeams;
478 
479 			TBarView *barView = static_cast<TBarApp *>(be_app)->BarView();
480 			fBarWindow->Lock();
481 			barView->UpdatePlacement();
482 			fBarWindow->Unlock();
483 			break;
484 		}
485 
486 		case 'TASK':
487 			fSwitcherMessenger.SendMessage(message);
488 			break;
489 
490 #if __HAIKU__
491 		case CMD_SUSPEND_SYSTEM:
492 			break;
493 
494 		case CMD_REBOOT_SYSTEM:
495 		case CMD_SHUTDOWN_SYSTEM:
496 		{
497 			bool reboot = (message->what == CMD_REBOOT_SYSTEM);
498 			bool confirm;
499 			message->FindBool("confirm", &confirm);
500 
501 			BRoster roster;
502 			BRoster::Private rosterPrivate(roster);
503 			status_t error = rosterPrivate.ShutDown(reboot, confirm, false);
504 			if (error != B_OK)
505 				fprintf(stderr, "Shutdown failed: %s\n", strerror(error));
506 
507 			break;
508 		}
509 #endif // __HAIKU__
510 
511 		// in case Tracker is not running
512 
513 		case kShowSplash:
514 #ifdef B_BEOS_VERSION_5
515 			run_be_about();
516 #endif
517 			break;
518 
519 		default:
520 			BApplication::MessageReceived(message);
521 			break;
522 	}
523 }
524 
525 
526 /**	In case Tracker is not running, the TBeMenu will use us as a target.
527  *	We'll make sure the user won't be completely confused and take over
528  *	Tracker's duties until it's back.
529  */
530 
531 void
532 TBarApp::RefsReceived(BMessage *refs)
533 {
534 	entry_ref ref;
535 	for (int32 i = 0; refs->FindRef("refs", i, &ref) == B_OK; i++) {
536 		BMessage refsReceived(B_REFS_RECEIVED);
537 		refsReceived.AddRef("refs", &ref);
538 
539 		BEntry entry(&ref);
540 		if (!entry.IsDirectory())
541 			TrackerLaunch(&refsReceived, true);
542 	}
543 }
544 
545 
546 void
547 TBarApp::Subscribe(const BMessenger &subscriber, BList *list)
548 {
549 	// called when ExpandoMenuBar, TeamMenu or Switcher are built/rebuilt
550 	list->MakeEmpty();
551 
552 	BAutolock autolock(sSubscriberLock);
553 	if (!autolock.IsLocked())
554 		return;
555 
556 	int32 numTeams = sBarTeamInfoList.CountItems();
557 	for (int32 i = 0; i < numTeams; i++) {
558 		BarTeamInfo *barInfo = (BarTeamInfo *)sBarTeamInfoList.ItemAt(i);
559 		BarTeamInfo *newBarInfo = new (std::nothrow) BarTeamInfo(*barInfo);
560 		if (newBarInfo != NULL)
561 			list->AddItem(newBarInfo);
562 	}
563 
564 	int32 subsCount = sSubscribers.CountItems();
565 	for (int32 i = 0; i < subsCount; i++) {
566 		BMessenger *messenger = (BMessenger *)sSubscribers.ItemAt(i);
567 		if (*messenger == subscriber)
568 			return;
569 	}
570 
571 	sSubscribers.AddItem(new BMessenger(subscriber));
572 }
573 
574 
575 void
576 TBarApp::Unsubscribe(const BMessenger &subscriber)
577 {
578 	BAutolock autolock(sSubscriberLock);
579 	if (!autolock.IsLocked())
580 		return;
581 
582 	int32 count = sSubscribers.CountItems();
583 	for (int32 i = 0; i < count; i++) {
584 		BMessenger *messenger = (BMessenger *)sSubscribers.ItemAt(i);
585 		if (*messenger == subscriber) {
586 			sSubscribers.RemoveItem(i);
587 			delete messenger;
588 			break;
589 		}
590 	}
591 }
592 
593 
594 void
595 TBarApp::AddTeam(team_id team, uint32 flags, const char *sig, entry_ref *ref)
596 {
597 	BAutolock autolock(sSubscriberLock);
598 	if (!autolock.IsLocked())
599 		return;
600 
601 	// have we already seen this team, is this another instance of
602 	// a known app?
603 	BarTeamInfo *multiLaunchTeam = NULL;
604 	int32 teamCount = sBarTeamInfoList.CountItems();
605 	for (int32 i = 0; i < teamCount; i++) {
606 		BarTeamInfo *barInfo = (BarTeamInfo *)sBarTeamInfoList.ItemAt(i);
607 		if (barInfo->teams->HasItem((void *)team))
608 			return;
609 		if (strcasecmp(barInfo->sig, sig) == 0)
610 			multiLaunchTeam = barInfo;
611 	}
612 
613 	if (multiLaunchTeam != NULL) {
614 		multiLaunchTeam->teams->AddItem((void *)team);
615 
616 		int32 subsCount = sSubscribers.CountItems();
617 		if (subsCount > 0) {
618 			BMessage message(msg_AddTeam);
619 			message.AddInt32("team", team);
620 			message.AddString("sig", multiLaunchTeam->sig);
621 
622 			for (int32 i = 0; i < subsCount; i++)
623 				((BMessenger *)sSubscribers.ItemAt(i))->SendMessage(&message);
624 		}
625 		return;
626 	}
627 
628 	BFile file(ref, B_READ_ONLY);
629 	BAppFileInfo appMime(&file);
630 
631 	BarTeamInfo *barInfo = new BarTeamInfo(new BList(), flags, strdup(sig),
632 		new BBitmap(kIconSize, kIconFormat), strdup(ref->name));
633 
634 	barInfo->teams->AddItem((void *)team);
635 	if (appMime.GetIcon(barInfo->icon, B_MINI_ICON) != B_OK)
636 		appMime.GetTrackerIcon(barInfo->icon, B_MINI_ICON);
637 
638 	sBarTeamInfoList.AddItem(barInfo);
639 
640 	int32 subsCount = sSubscribers.CountItems();
641 	if (subsCount > 0) {
642 		for (int32 i = 0; i < subsCount; i++) {
643 			BMessenger *messenger = (BMessenger *)sSubscribers.ItemAt(i);
644 			BMessage message(B_SOME_APP_LAUNCHED);
645 
646 			BList *tList = new BList(*(barInfo->teams));
647 			message.AddPointer("teams", tList);
648 
649 			BBitmap *icon = new BBitmap(barInfo->icon);
650 			ASSERT(icon);
651 
652 			message.AddPointer("icon", icon);
653 
654 			message.AddInt32("flags", static_cast<int32>(barInfo->flags));
655 			message.AddString("name", barInfo->name);
656 			message.AddString("sig", barInfo->sig);
657 
658 			messenger->SendMessage(&message);
659 		}
660 	}
661 }
662 
663 
664 void
665 TBarApp::RemoveTeam(team_id team)
666 {
667 	BAutolock autolock(sSubscriberLock);
668 	if (!autolock.IsLocked())
669 		return;
670 
671 	int32 teamCount = sBarTeamInfoList.CountItems();
672 	for (int32 i = 0; i < teamCount; i++) {
673 		BarTeamInfo *barInfo = (BarTeamInfo *)sBarTeamInfoList.ItemAt(i);
674 		if (barInfo->teams->HasItem((void *)team)) {
675 			int32 subsCount = sSubscribers.CountItems();
676 			if (subsCount > 0) {
677 				BMessage message((barInfo->teams->CountItems() == 1) ?
678 					 B_SOME_APP_QUIT : msg_RemoveTeam);
679 
680 				message.AddInt32("team", team);
681 				for (int32 i = 0; i < subsCount; i++) {
682 					BMessenger *messenger = (BMessenger *)sSubscribers.ItemAt(i);
683 					messenger->SendMessage(&message);
684 				}
685 			}
686 
687 			barInfo->teams->RemoveItem((void *)team);
688 			if (barInfo->teams->CountItems() < 1) {
689 				delete (BarTeamInfo *)sBarTeamInfoList.RemoveItem(i);
690 				return;
691 			}
692 		}
693 	}
694 }
695 
696 
697 void
698 TBarApp::ShowPreferencesWindow()
699 {
700 	if (fPreferencesWindow)
701 		fPreferencesWindow->Activate();
702  	else {
703 		fPreferencesWindow = new PreferencesWindow(BRect(0, 0, 320, 240));
704 		fPreferencesWindow->Show();
705 	}
706 }
707 
708 
709 //	#pragma mark -
710 
711 
712 BarTeamInfo::BarTeamInfo(BList *teams, uint32 flags, char *sig, BBitmap *icon, char *name)
713 	:	teams(teams),
714 		flags(flags),
715 		sig(sig),
716 		icon(icon),
717 		name(name)
718 {
719 }
720 
721 
722 BarTeamInfo::BarTeamInfo(const BarTeamInfo &info)
723 	:	teams(new BList(*info.teams)),
724 		flags(info.flags),
725 		sig(strdup(info.sig)),
726 		icon(new BBitmap(*info.icon)),
727 		name(strdup(info.name))
728 {
729 }
730 
731 
732 BarTeamInfo::~BarTeamInfo()
733 {
734 	delete teams;
735 	free(sig);
736 	delete icon;
737 	free(name);
738 }
739 
740 
741