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