xref: /haiku/src/apps/haikudepot/ui/MainWindow.cpp (revision 779ab335dd81d47f9aa7ef06822de37c8fec1c6e)
104c9d578SStephan Aßmus /*
2f7c2983eSAxel Dörfler  * Copyright 2015, Axel Dörfler, <axeld@pinc-software.de>.
304c9d578SStephan Aßmus  * Copyright 2013-2014, Stephan Aßmus <superstippi@gmx.de>.
404c9d578SStephan Aßmus  * Copyright 2013, Rene Gollent, rene@gollent.com.
504c9d578SStephan Aßmus  * Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
610cd325cSAndrew Lindesay  * Copyright 2016-2020, Andrew Lindesay <apl@lindesay.co.nz>.
7125d42d9SJulian Harnath  * Copyright 2017, Julian Harnath <julian.harnath@rwth-aachen.de>.
804c9d578SStephan Aßmus  * All rights reserved. Distributed under the terms of the MIT License.
904c9d578SStephan Aßmus  */
1004c9d578SStephan Aßmus 
11f7c2983eSAxel Dörfler 
1204c9d578SStephan Aßmus #include "MainWindow.h"
1304c9d578SStephan Aßmus 
1404c9d578SStephan Aßmus #include <map>
153b17d8ddSAndrew Lindesay #include <vector>
1604c9d578SStephan Aßmus 
1704c9d578SStephan Aßmus #include <stdio.h>
1804c9d578SStephan Aßmus #include <Alert.h>
1904c9d578SStephan Aßmus #include <Autolock.h>
2004c9d578SStephan Aßmus #include <Application.h>
2104c9d578SStephan Aßmus #include <Button.h>
2204c9d578SStephan Aßmus #include <Catalog.h>
234b930ccaSStephan Aßmus #include <CardLayout.h>
2404c9d578SStephan Aßmus #include <LayoutBuilder.h>
2504c9d578SStephan Aßmus #include <MenuBar.h>
2604c9d578SStephan Aßmus #include <MenuItem.h>
2704c9d578SStephan Aßmus #include <Messenger.h>
285bf2b6ebSBrian Hill #include <Roster.h>
29f7c2983eSAxel Dörfler #include <Screen.h>
3004c9d578SStephan Aßmus #include <ScrollView.h>
3104c9d578SStephan Aßmus #include <StringList.h>
320a9c9029SStephan Aßmus #include <StringView.h>
3304c9d578SStephan Aßmus #include <TabView.h>
3404c9d578SStephan Aßmus 
353369e03dSAndrew Lindesay #include "AppUtils.h"
3604c9d578SStephan Aßmus #include "AutoDeleter.h"
3704c9d578SStephan Aßmus #include "AutoLocker.h"
3804c9d578SStephan Aßmus #include "DecisionProvider.h"
394b930ccaSStephan Aßmus #include "FeaturedPackagesView.h"
4004c9d578SStephan Aßmus #include "FilterView.h"
41d13c3d89SAndrew Lindesay #include "Logger.h"
4204c9d578SStephan Aßmus #include "PackageInfoView.h"
4304c9d578SStephan Aßmus #include "PackageListView.h"
4404c9d578SStephan Aßmus #include "PackageManager.h"
453369e03dSAndrew Lindesay #include "ProcessCoordinator.h"
463369e03dSAndrew Lindesay #include "ProcessCoordinatorFactory.h"
4704c9d578SStephan Aßmus #include "RatePackageWindow.h"
48e0a26dceSStephan Aßmus #include "support.h"
49d5ef985eSStephan Aßmus #include "ScreenshotWindow.h"
5010cd325cSAndrew Lindesay #include "ToLatestUserUsageConditionsWindow.h"
5104c9d578SStephan Aßmus #include "UserLoginWindow.h"
5201339a54SAndrew Lindesay #include "UserUsageConditionsWindow.h"
53125d42d9SJulian Harnath #include "WorkStatusView.h"
5404c9d578SStephan Aßmus 
5504c9d578SStephan Aßmus 
5604c9d578SStephan Aßmus #undef B_TRANSLATION_CONTEXT
5704c9d578SStephan Aßmus #define B_TRANSLATION_CONTEXT "MainWindow"
5804c9d578SStephan Aßmus 
5904c9d578SStephan Aßmus 
6004c9d578SStephan Aßmus enum {
615bf2b6ebSBrian Hill 	MSG_REFRESH_REPOS						= 'mrrp',
625bf2b6ebSBrian Hill 	MSG_MANAGE_REPOS						= 'mmrp',
63d144f952SAugustin Cavalier 	MSG_SOFTWARE_UPDATER					= 'mswu',
6404c9d578SStephan Aßmus 	MSG_LOG_IN								= 'lgin',
658f03a0f9SStephan Aßmus 	MSG_AUTHORIZATION_CHANGED				= 'athc',
6689b16bb4SAndrew Lindesay 	MSG_CATEGORIES_LIST_CHANGED				= 'clic',
67da651104SStephan Aßmus 	MSG_PACKAGE_CHANGED						= 'pchd',
683369e03dSAndrew Lindesay 	MSG_WORK_STATUS_CHANGE					= 'wsch',
693369e03dSAndrew Lindesay 	MSG_WORK_STATUS_CLEAR					= 'wscl',
70fdec4227SStephan Aßmus 
71ccf707d0SAndrew Lindesay 	MSG_CHANGE_PACKAGE_LIST_VIEW_MODE		= 'cplm',
72fdec4227SStephan Aßmus 	MSG_SHOW_AVAILABLE_PACKAGES				= 'savl',
73fdec4227SStephan Aßmus 	MSG_SHOW_INSTALLED_PACKAGES				= 'sins',
7404c9d578SStephan Aßmus 	MSG_SHOW_SOURCE_PACKAGES				= 'ssrc',
7504c9d578SStephan Aßmus 	MSG_SHOW_DEVELOP_PACKAGES				= 'sdvl'
7604c9d578SStephan Aßmus };
7704c9d578SStephan Aßmus 
7810cd325cSAndrew Lindesay #define KEY_ERROR_STATUS				"errorStatus"
79ccf707d0SAndrew Lindesay #define KEY_PACKAGE_LIST_VIEW_MODE		"packageListViewMode"
80ccf707d0SAndrew Lindesay 
81ccf707d0SAndrew Lindesay #define TAB_PROMINENT_PACKAGES	0
82ccf707d0SAndrew Lindesay #define TAB_ALL_PACKAGES		1
8304c9d578SStephan Aßmus 
8404c9d578SStephan Aßmus using namespace BPackageKit;
8504c9d578SStephan Aßmus using namespace BPackageKit::BManager::BPrivate;
8604c9d578SStephan Aßmus 
8704c9d578SStephan Aßmus 
8804c9d578SStephan Aßmus typedef std::map<BString, PackageInfoRef> PackageInfoMap;
8904c9d578SStephan Aßmus 
9004c9d578SStephan Aßmus 
9104c9d578SStephan Aßmus struct RefreshWorkerParameters {
9204c9d578SStephan Aßmus 	MainWindow* window;
9304c9d578SStephan Aßmus 	bool forceRefresh;
9404c9d578SStephan Aßmus 
9504c9d578SStephan Aßmus 	RefreshWorkerParameters(MainWindow* window, bool forceRefresh)
9604c9d578SStephan Aßmus 		:
9704c9d578SStephan Aßmus 		window(window),
9804c9d578SStephan Aßmus 		forceRefresh(forceRefresh)
9904c9d578SStephan Aßmus 	{
10004c9d578SStephan Aßmus 	}
10104c9d578SStephan Aßmus };
10204c9d578SStephan Aßmus 
10304c9d578SStephan Aßmus 
10489b16bb4SAndrew Lindesay class MainWindowModelListener : public ModelListener {
1058f03a0f9SStephan Aßmus public:
10689b16bb4SAndrew Lindesay 	MainWindowModelListener(const BMessenger& messenger)
1078f03a0f9SStephan Aßmus 		:
1088f03a0f9SStephan Aßmus 		fMessenger(messenger)
1098f03a0f9SStephan Aßmus 	{
1108f03a0f9SStephan Aßmus 	}
1118f03a0f9SStephan Aßmus 
1128f03a0f9SStephan Aßmus 	virtual void AuthorizationChanged()
1138f03a0f9SStephan Aßmus 	{
1148f03a0f9SStephan Aßmus 		if (fMessenger.IsValid())
1158f03a0f9SStephan Aßmus 			fMessenger.SendMessage(MSG_AUTHORIZATION_CHANGED);
1168f03a0f9SStephan Aßmus 	}
1178f03a0f9SStephan Aßmus 
11889b16bb4SAndrew Lindesay 	virtual void CategoryListChanged()
11989b16bb4SAndrew Lindesay 	{
12089b16bb4SAndrew Lindesay 		if (fMessenger.IsValid())
12189b16bb4SAndrew Lindesay 			fMessenger.SendMessage(MSG_CATEGORIES_LIST_CHANGED);
12289b16bb4SAndrew Lindesay 	}
12389b16bb4SAndrew Lindesay 
1248f03a0f9SStephan Aßmus private:
1258f03a0f9SStephan Aßmus 	BMessenger	fMessenger;
1268f03a0f9SStephan Aßmus };
1278f03a0f9SStephan Aßmus 
1288f03a0f9SStephan Aßmus 
129f7c2983eSAxel Dörfler MainWindow::MainWindow(const BMessage& settings)
13004c9d578SStephan Aßmus 	:
131f7c2983eSAxel Dörfler 	BWindow(BRect(50, 50, 650, 550), B_TRANSLATE_SYSTEM_NAME("HaikuDepot"),
13204c9d578SStephan Aßmus 		B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
13304c9d578SStephan Aßmus 		B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS),
134d5ef985eSStephan Aßmus 	fScreenshotWindow(NULL),
135e0a26dceSStephan Aßmus 	fUserMenu(NULL),
136e0a26dceSStephan Aßmus 	fLogInItem(NULL),
137e0a26dceSStephan Aßmus 	fLogOutItem(NULL),
138976cadf1SAndrew Lindesay 	fUsersUserUsageConditionsMenuItem(NULL),
13989b16bb4SAndrew Lindesay 	fModelListener(new MainWindowModelListener(BMessenger(this)), true),
14010cd325cSAndrew Lindesay 	fCoordinator(NULL),
1413369e03dSAndrew Lindesay 	fSinglePackageMode(false)
14204c9d578SStephan Aßmus {
14310cd325cSAndrew Lindesay 	if ((fCoordinatorRunningSem = create_sem(1, "ProcessCoordinatorSem")) < B_OK)
14410cd325cSAndrew Lindesay 		debugger("unable to create the process coordinator semaphore");
14510cd325cSAndrew Lindesay 
146cbadcae1SHumdinger 	BMenuBar* menuBar = new BMenuBar("Main Menu");
14704c9d578SStephan Aßmus 	_BuildMenu(menuBar);
14804c9d578SStephan Aßmus 
149cbadcae1SHumdinger 	BMenuBar* userMenuBar = new BMenuBar("User Menu");
150e0a26dceSStephan Aßmus 	_BuildUserMenu(userMenuBar);
151e0a26dceSStephan Aßmus 	set_small_font(userMenuBar);
152e0a26dceSStephan Aßmus 	userMenuBar->SetExplicitMaxSize(BSize(B_SIZE_UNSET,
153e0a26dceSStephan Aßmus 		menuBar->MaxSize().height));
154e0a26dceSStephan Aßmus 
15504c9d578SStephan Aßmus 	fFilterView = new FilterView();
156f0e491d3SAndrew Lindesay 	fFeaturedPackagesView = new FeaturedPackagesView(fModel);
157f0e491d3SAndrew Lindesay 	fPackageListView = new PackageListView(&fModel);
158f0e491d3SAndrew Lindesay 	fPackageInfoView = new PackageInfoView(&fModel, this);
15904c9d578SStephan Aßmus 
16004c9d578SStephan Aßmus 	fSplitView = new BSplitView(B_VERTICAL, 5.0f);
16104c9d578SStephan Aßmus 
162125d42d9SJulian Harnath 	fWorkStatusView = new WorkStatusView("work status");
163125d42d9SJulian Harnath 	fPackageListView->AttachWorkStatusView(fWorkStatusView);
164125d42d9SJulian Harnath 
165e00a489bSAugustin Cavalier 	fListTabs = new TabView(BMessenger(this),
166ccf707d0SAndrew Lindesay 		BMessage(MSG_CHANGE_PACKAGE_LIST_VIEW_MODE), "list tabs");
167e00a489bSAugustin Cavalier 	fListTabs->AddTab(fFeaturedPackagesView);
168e00a489bSAugustin Cavalier 	fListTabs->AddTab(fPackageListView);
1694b930ccaSStephan Aßmus 
17004c9d578SStephan Aßmus 	BLayoutBuilder::Group<>(this, B_VERTICAL, 0.0f)
171e0a26dceSStephan Aßmus 		.AddGroup(B_HORIZONTAL, 0.0f)
172e0a26dceSStephan Aßmus 			.Add(menuBar, 1.0f)
173e0a26dceSStephan Aßmus 			.Add(userMenuBar, 0.0f)
174e0a26dceSStephan Aßmus 		.End()
17504c9d578SStephan Aßmus 		.Add(fFilterView)
17604c9d578SStephan Aßmus 		.AddSplit(fSplitView)
17704c9d578SStephan Aßmus 			.AddGroup(B_VERTICAL)
178e00a489bSAugustin Cavalier 				.Add(fListTabs)
17904c9d578SStephan Aßmus 				.SetInsets(
18004c9d578SStephan Aßmus 					B_USE_DEFAULT_SPACING, 0.0f,
18104c9d578SStephan Aßmus 					B_USE_DEFAULT_SPACING, 0.0f)
18204c9d578SStephan Aßmus 			.End()
18304c9d578SStephan Aßmus 			.Add(fPackageInfoView)
18404c9d578SStephan Aßmus 		.End()
185125d42d9SJulian Harnath 		.Add(fWorkStatusView)
18604c9d578SStephan Aßmus 	;
18704c9d578SStephan Aßmus 
18804c9d578SStephan Aßmus 	fSplitView->SetCollapsible(0, false);
18904c9d578SStephan Aßmus 	fSplitView->SetCollapsible(1, false);
19004c9d578SStephan Aßmus 
1918f03a0f9SStephan Aßmus 	fModel.AddListener(fModelListener);
1928f03a0f9SStephan Aßmus 
19304c9d578SStephan Aßmus 	BMessage columnSettings;
19404c9d578SStephan Aßmus 	if (settings.FindMessage("column settings", &columnSettings) == B_OK)
19504c9d578SStephan Aßmus 		fPackageListView->LoadState(&columnSettings);
19604c9d578SStephan Aßmus 
197ccf707d0SAndrew Lindesay 	_RestoreModelSettings(settings);
19804c9d578SStephan Aßmus 
199ccf707d0SAndrew Lindesay 	if (fModel.PackageListViewMode() == PROMINENT)
200ccf707d0SAndrew Lindesay 		fListTabs->Select(TAB_PROMINENT_PACKAGES);
2012997e05bSStephan Aßmus 	else
202ccf707d0SAndrew Lindesay 		fListTabs->Select(TAB_ALL_PACKAGES);
2032997e05bSStephan Aßmus 
204d2d4866dSAndrew Lindesay 	_RestoreNickname(settings);
20510cd325cSAndrew Lindesay 	_UpdateAuthorization();
206f7c2983eSAxel Dörfler 	_RestoreWindowFrame(settings);
207f7c2983eSAxel Dörfler 
2088f03a0f9SStephan Aßmus 	// start worker threads
20904c9d578SStephan Aßmus 	BPackageRoster().StartWatching(this,
21004c9d578SStephan Aßmus 		B_WATCH_PACKAGE_INSTALLATION_LOCATIONS);
21104c9d578SStephan Aßmus 
21263975654SStephan Aßmus 	_InitWorkerThreads();
2139883929bSAndrew Lindesay 	_AdoptModel();
2149883929bSAndrew Lindesay 	_StartBulkLoad();
21504c9d578SStephan Aßmus }
21604c9d578SStephan Aßmus 
21704c9d578SStephan Aßmus 
218f7c2983eSAxel Dörfler MainWindow::MainWindow(const BMessage& settings, const PackageInfoRef& package)
2196d519fd1SStephan Aßmus 	:
220f7c2983eSAxel Dörfler 	BWindow(BRect(50, 50, 650, 350), B_TRANSLATE_SYSTEM_NAME("HaikuDepot"),
2216d519fd1SStephan Aßmus 		B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
2226d519fd1SStephan Aßmus 		B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS),
2239883929bSAndrew Lindesay 	fFeaturedPackagesView(NULL),
2249883929bSAndrew Lindesay 	fPackageListView(NULL),
225d78bfd8dSJulian Harnath 	fWorkStatusView(NULL),
226d5ef985eSStephan Aßmus 	fScreenshotWindow(NULL),
227e0a26dceSStephan Aßmus 	fUserMenu(NULL),
228e0a26dceSStephan Aßmus 	fLogInItem(NULL),
2296d519fd1SStephan Aßmus 	fLogOutItem(NULL),
230976cadf1SAndrew Lindesay 	fUsersUserUsageConditionsMenuItem(NULL),
23189b16bb4SAndrew Lindesay 	fModelListener(new MainWindowModelListener(BMessenger(this)), true),
23210cd325cSAndrew Lindesay 	fCoordinator(NULL),
2333369e03dSAndrew Lindesay 	fSinglePackageMode(true)
2346d519fd1SStephan Aßmus {
23510cd325cSAndrew Lindesay 	if ((fCoordinatorRunningSem = create_sem(1, "ProcessCoordinatorSem")) < B_OK)
23610cd325cSAndrew Lindesay 		debugger("unable to create the process coordinator semaphore");
23710cd325cSAndrew Lindesay 
2386d519fd1SStephan Aßmus 	fFilterView = new FilterView();
239f0e491d3SAndrew Lindesay 	fPackageInfoView = new PackageInfoView(&fModel, this);
24087016f8fSAndrew Lindesay 	fWorkStatusView = new WorkStatusView("work status");
2416d519fd1SStephan Aßmus 
2426d519fd1SStephan Aßmus 	BLayoutBuilder::Group<>(this, B_VERTICAL)
2436d519fd1SStephan Aßmus 		.Add(fPackageInfoView)
24487016f8fSAndrew Lindesay 		.Add(fWorkStatusView)
2456d519fd1SStephan Aßmus 		.SetInsets(0, B_USE_WINDOW_INSETS, 0, 0)
2466d519fd1SStephan Aßmus 	;
2476d519fd1SStephan Aßmus 
2486d519fd1SStephan Aßmus 	fModel.AddListener(fModelListener);
2496d519fd1SStephan Aßmus 
2506d519fd1SStephan Aßmus 	// Restore settings
251d2d4866dSAndrew Lindesay 	_RestoreNickname(settings);
252ccf707d0SAndrew Lindesay 	_UpdateAuthorization();
253f7c2983eSAxel Dörfler 	_RestoreWindowFrame(settings);
2546d519fd1SStephan Aßmus 
2556d519fd1SStephan Aßmus 	fPackageInfoView->SetPackage(package);
25663975654SStephan Aßmus 
25763975654SStephan Aßmus 	_InitWorkerThreads();
2586d519fd1SStephan Aßmus }
2596d519fd1SStephan Aßmus 
2606d519fd1SStephan Aßmus 
26104c9d578SStephan Aßmus MainWindow::~MainWindow()
26204c9d578SStephan Aßmus {
26310cd325cSAndrew Lindesay 	_SpinUntilProcessCoordinatorComplete();
26410cd325cSAndrew Lindesay 	delete_sem(fCoordinatorRunningSem);
26510cd325cSAndrew Lindesay 	fCoordinatorRunningSem = 0;
26610cd325cSAndrew Lindesay 
26704c9d578SStephan Aßmus 	BPackageRoster().StopWatching(this);
26804c9d578SStephan Aßmus 
26904c9d578SStephan Aßmus 	delete_sem(fPendingActionsSem);
27005bffa62SStephan Aßmus 	if (fPendingActionsWorker >= 0)
27104c9d578SStephan Aßmus 		wait_for_thread(fPendingActionsWorker, NULL);
27204c9d578SStephan Aßmus 
273d5ef985eSStephan Aßmus 	if (fScreenshotWindow != NULL && fScreenshotWindow->Lock())
274d5ef985eSStephan Aßmus 		fScreenshotWindow->Quit();
27504c9d578SStephan Aßmus }
27604c9d578SStephan Aßmus 
27704c9d578SStephan Aßmus 
27804c9d578SStephan Aßmus bool
27904c9d578SStephan Aßmus MainWindow::QuitRequested()
28004c9d578SStephan Aßmus {
28104c9d578SStephan Aßmus 	BMessage settings;
28204c9d578SStephan Aßmus 	StoreSettings(settings);
28304c9d578SStephan Aßmus 
28404c9d578SStephan Aßmus 	BMessage message(MSG_MAIN_WINDOW_CLOSED);
2853369e03dSAndrew Lindesay 	message.AddMessage(KEY_WINDOW_SETTINGS, &settings);
28604c9d578SStephan Aßmus 
28704c9d578SStephan Aßmus 	be_app->PostMessage(&message);
28804c9d578SStephan Aßmus 
28910cd325cSAndrew Lindesay 	_StopProcessCoordinators();
2903369e03dSAndrew Lindesay 
29104c9d578SStephan Aßmus 	return true;
29204c9d578SStephan Aßmus }
29304c9d578SStephan Aßmus 
29404c9d578SStephan Aßmus 
29504c9d578SStephan Aßmus void
29604c9d578SStephan Aßmus MainWindow::MessageReceived(BMessage* message)
29704c9d578SStephan Aßmus {
29804c9d578SStephan Aßmus 	switch (message->what) {
2993369e03dSAndrew Lindesay 		case MSG_BULK_LOAD_DONE:
30010cd325cSAndrew Lindesay 		{
30110cd325cSAndrew Lindesay 			int64 errorStatus64;
30210cd325cSAndrew Lindesay 			if (message->FindInt64(KEY_ERROR_STATUS, &errorStatus64) == B_OK)
30310cd325cSAndrew Lindesay 				_BulkLoadCompleteReceived((status_t) errorStatus64);
30410cd325cSAndrew Lindesay 			else
305fa5c8097SAndrew Lindesay 				HDERROR("expected [%s] value in message", KEY_ERROR_STATUS);
30604c9d578SStephan Aßmus 			break;
30710cd325cSAndrew Lindesay 		}
30804c9d578SStephan Aßmus 		case B_SIMPLE_DATA:
30904c9d578SStephan Aßmus 		case B_REFS_RECEIVED:
31004c9d578SStephan Aßmus 			// TODO: ?
31104c9d578SStephan Aßmus 			break;
31204c9d578SStephan Aßmus 
31304c9d578SStephan Aßmus 		case B_PACKAGE_UPDATE:
3145ad01608SAndrew Lindesay 			// TODO: see ticket #15879
3155ad01608SAndrew Lindesay 			// work needs to be done here to selectively update package data in
3165ad01608SAndrew Lindesay 			// the running HaikuDepot application when there are changes on the
3175ad01608SAndrew Lindesay 			// system.  There is now too much data to just load everything when
3185ad01608SAndrew Lindesay 			// there is a change.
3195ad01608SAndrew Lindesay 			//_StartBulkLoad(false);
32004c9d578SStephan Aßmus 			break;
32104c9d578SStephan Aßmus 
3225bf2b6ebSBrian Hill 		case MSG_REFRESH_REPOS:
3233369e03dSAndrew Lindesay 			_StartBulkLoad(true);
3243369e03dSAndrew Lindesay 			break;
3253369e03dSAndrew Lindesay 
32610cd325cSAndrew Lindesay 		case MSG_WORK_STATUS_CLEAR:
32710cd325cSAndrew Lindesay 			_HandleWorkStatusClear();
32810cd325cSAndrew Lindesay 			break;
32910cd325cSAndrew Lindesay 
3303369e03dSAndrew Lindesay 		case MSG_WORK_STATUS_CHANGE:
3313369e03dSAndrew Lindesay 			_HandleWorkStatusChangeMessageReceived(message);
33204c9d578SStephan Aßmus 			break;
33304c9d578SStephan Aßmus 
3345bf2b6ebSBrian Hill 		case MSG_MANAGE_REPOS:
3355bf2b6ebSBrian Hill 			be_roster->Launch("application/x-vnd.Haiku-Repositories");
3365bf2b6ebSBrian Hill 			break;
3375bf2b6ebSBrian Hill 
338d144f952SAugustin Cavalier 		case MSG_SOFTWARE_UPDATER:
339d144f952SAugustin Cavalier 			be_roster->Launch("application/x-vnd.haiku-softwareupdater");
340d144f952SAugustin Cavalier 			break;
341d144f952SAugustin Cavalier 
34204c9d578SStephan Aßmus 		case MSG_LOG_IN:
3431bbda92dSStephan Aßmus 			_OpenLoginWindow(BMessage());
34404c9d578SStephan Aßmus 			break;
34504c9d578SStephan Aßmus 
3468f03a0f9SStephan Aßmus 		case MSG_LOG_OUT:
347d2d4866dSAndrew Lindesay 			fModel.SetNickname("");
3488f03a0f9SStephan Aßmus 			break;
3498f03a0f9SStephan Aßmus 
35001339a54SAndrew Lindesay 		case MSG_VIEW_LATEST_USER_USAGE_CONDITIONS:
351d2d4866dSAndrew Lindesay 			_ViewUserUsageConditions(LATEST);
352d2d4866dSAndrew Lindesay 			break;
353d2d4866dSAndrew Lindesay 
354d2d4866dSAndrew Lindesay 		case MSG_VIEW_USERS_USER_USAGE_CONDITIONS:
355d2d4866dSAndrew Lindesay 			_ViewUserUsageConditions(USER);
35601339a54SAndrew Lindesay 			break;
35701339a54SAndrew Lindesay 
3588f03a0f9SStephan Aßmus 		case MSG_AUTHORIZATION_CHANGED:
35910cd325cSAndrew Lindesay 			_StartUserVerify();
3608f03a0f9SStephan Aßmus 			_UpdateAuthorization();
3618f03a0f9SStephan Aßmus 			break;
3628f03a0f9SStephan Aßmus 
36389b16bb4SAndrew Lindesay 		case MSG_CATEGORIES_LIST_CHANGED:
36489b16bb4SAndrew Lindesay 			fFilterView->AdoptModel(fModel);
36589b16bb4SAndrew Lindesay 			break;
36689b16bb4SAndrew Lindesay 
367ccf707d0SAndrew Lindesay 		case MSG_CHANGE_PACKAGE_LIST_VIEW_MODE:
368ccf707d0SAndrew Lindesay 			_HandleChangePackageListViewMode();
3694fade61fSStephan Aßmus 			break;
3704fade61fSStephan Aßmus 
371fdec4227SStephan Aßmus 		case MSG_SHOW_AVAILABLE_PACKAGES:
372fdec4227SStephan Aßmus 			{
373fdec4227SStephan Aßmus 				BAutolock locker(fModel.Lock());
374fdec4227SStephan Aßmus 				fModel.SetShowAvailablePackages(
375fdec4227SStephan Aßmus 					!fModel.ShowAvailablePackages());
376fdec4227SStephan Aßmus 			}
377fdec4227SStephan Aßmus 			_AdoptModel();
378fdec4227SStephan Aßmus 			break;
379fdec4227SStephan Aßmus 
380fdec4227SStephan Aßmus 		case MSG_SHOW_INSTALLED_PACKAGES:
381fdec4227SStephan Aßmus 			{
382fdec4227SStephan Aßmus 				BAutolock locker(fModel.Lock());
383fdec4227SStephan Aßmus 				fModel.SetShowInstalledPackages(
384fdec4227SStephan Aßmus 					!fModel.ShowInstalledPackages());
385fdec4227SStephan Aßmus 			}
386fdec4227SStephan Aßmus 			_AdoptModel();
387fdec4227SStephan Aßmus 			break;
388fdec4227SStephan Aßmus 
38904c9d578SStephan Aßmus 		case MSG_SHOW_SOURCE_PACKAGES:
39004c9d578SStephan Aßmus 			{
39104c9d578SStephan Aßmus 				BAutolock locker(fModel.Lock());
39204c9d578SStephan Aßmus 				fModel.SetShowSourcePackages(!fModel.ShowSourcePackages());
39304c9d578SStephan Aßmus 			}
39404c9d578SStephan Aßmus 			_AdoptModel();
39504c9d578SStephan Aßmus 			break;
39604c9d578SStephan Aßmus 
39704c9d578SStephan Aßmus 		case MSG_SHOW_DEVELOP_PACKAGES:
39804c9d578SStephan Aßmus 			{
39904c9d578SStephan Aßmus 				BAutolock locker(fModel.Lock());
40004c9d578SStephan Aßmus 				fModel.SetShowDevelopPackages(!fModel.ShowDevelopPackages());
40104c9d578SStephan Aßmus 			}
40204c9d578SStephan Aßmus 			_AdoptModel();
40304c9d578SStephan Aßmus 			break;
40404c9d578SStephan Aßmus 
405a9edb9bfSAndrew Lindesay 			// this may be triggered by, for example, a user rating being added
406a9edb9bfSAndrew Lindesay 			// or having been altered.
407a9edb9bfSAndrew Lindesay 		case MSG_SERVER_DATA_CHANGED:
408a9edb9bfSAndrew Lindesay 		{
409a9edb9bfSAndrew Lindesay 			BString name;
410a9edb9bfSAndrew Lindesay 			if (message->FindString("name", &name) == B_OK) {
411a9edb9bfSAndrew Lindesay 				BAutolock locker(fModel.Lock());
412a9edb9bfSAndrew Lindesay 				if (fPackageInfoView->Package()->Name() == name) {
413a9edb9bfSAndrew Lindesay 					_PopulatePackageAsync(true);
414a9edb9bfSAndrew Lindesay 				} else {
415f96d1f4dSAndrew Lindesay 					HDDEBUG("pkg [%s] is updated on the server, but is "
416f96d1f4dSAndrew Lindesay 						"not selected so will not be updated.",
417fa5c8097SAndrew Lindesay 						name.String());
418a9edb9bfSAndrew Lindesay 				}
419a9edb9bfSAndrew Lindesay 			}
420a9edb9bfSAndrew Lindesay         	break;
421a9edb9bfSAndrew Lindesay         }
422a9edb9bfSAndrew Lindesay 
42304c9d578SStephan Aßmus 		case MSG_PACKAGE_SELECTED:
42404c9d578SStephan Aßmus 		{
42572992391SStephan Aßmus 			BString name;
42672992391SStephan Aßmus 			if (message->FindString("name", &name) == B_OK) {
427c4199192SAndrew Lindesay 				PackageInfoRef package;
428c4199192SAndrew Lindesay 				{
42975ba9dbfSStephan Aßmus 					BAutolock locker(fModel.Lock());
430c4199192SAndrew Lindesay 					package = fModel.PackageForName(name);
431c4199192SAndrew Lindesay 				}
432*779ab335SX512 				if (!package.IsSet())
433c4199192SAndrew Lindesay 					debugger("unable to find the named package");
434c4199192SAndrew Lindesay 				else
43504c9d578SStephan Aßmus 					_AdoptPackage(package);
43604c9d578SStephan Aßmus 			} else {
43704c9d578SStephan Aßmus 				_ClearPackage();
43804c9d578SStephan Aßmus 			}
43904c9d578SStephan Aßmus 			break;
44004c9d578SStephan Aßmus 		}
44104c9d578SStephan Aßmus 
44204c9d578SStephan Aßmus 		case MSG_CATEGORY_SELECTED:
44304c9d578SStephan Aßmus 		{
44489b16bb4SAndrew Lindesay 			BString code;
44589b16bb4SAndrew Lindesay 			if (message->FindString("code", &code) != B_OK)
44689b16bb4SAndrew Lindesay 				code = "";
44704c9d578SStephan Aßmus 			{
44804c9d578SStephan Aßmus 				BAutolock locker(fModel.Lock());
44989b16bb4SAndrew Lindesay 				fModel.SetCategory(code);
45004c9d578SStephan Aßmus 			}
45104c9d578SStephan Aßmus 			_AdoptModel();
45204c9d578SStephan Aßmus 			break;
45304c9d578SStephan Aßmus 		}
45404c9d578SStephan Aßmus 
45504c9d578SStephan Aßmus 		case MSG_DEPOT_SELECTED:
45604c9d578SStephan Aßmus 		{
45704c9d578SStephan Aßmus 			BString name;
45804c9d578SStephan Aßmus 			if (message->FindString("name", &name) != B_OK)
45904c9d578SStephan Aßmus 				name = "";
46004c9d578SStephan Aßmus 			{
46104c9d578SStephan Aßmus 				BAutolock locker(fModel.Lock());
46204c9d578SStephan Aßmus 				fModel.SetDepot(name);
46304c9d578SStephan Aßmus 			}
46404c9d578SStephan Aßmus 			_AdoptModel();
465b965ce70SHumdinger 			_UpdateAvailableRepositories();
46604c9d578SStephan Aßmus 			break;
46704c9d578SStephan Aßmus 		}
46804c9d578SStephan Aßmus 
46904c9d578SStephan Aßmus 		case MSG_SEARCH_TERMS_MODIFIED:
47004c9d578SStephan Aßmus 		{
47104c9d578SStephan Aßmus 			// TODO: Do this with a delay!
47204c9d578SStephan Aßmus 			BString searchTerms;
47304c9d578SStephan Aßmus 			if (message->FindString("search terms", &searchTerms) != B_OK)
47404c9d578SStephan Aßmus 				searchTerms = "";
47504c9d578SStephan Aßmus 			{
47604c9d578SStephan Aßmus 				BAutolock locker(fModel.Lock());
47704c9d578SStephan Aßmus 				fModel.SetSearchTerms(searchTerms);
47804c9d578SStephan Aßmus 			}
47904c9d578SStephan Aßmus 			_AdoptModel();
48004c9d578SStephan Aßmus 			break;
48104c9d578SStephan Aßmus 		}
48204c9d578SStephan Aßmus 
483da651104SStephan Aßmus 		case MSG_PACKAGE_CHANGED:
48404c9d578SStephan Aßmus 		{
48504c9d578SStephan Aßmus 			PackageInfo* info;
48604c9d578SStephan Aßmus 			if (message->FindPointer("package", (void**)&info) == B_OK) {
48704c9d578SStephan Aßmus 				PackageInfoRef ref(info, true);
488da651104SStephan Aßmus 				uint32 changes;
489da651104SStephan Aßmus 				if (message->FindUInt32("changes", &changes) != B_OK)
490da651104SStephan Aßmus 					changes = 0;
491da651104SStephan Aßmus 				if ((changes & PKG_CHANGED_STATE) != 0) {
49204c9d578SStephan Aßmus 					BAutolock locker(fModel.Lock());
49304c9d578SStephan Aßmus 					fModel.SetPackageState(ref, ref->State());
49404c9d578SStephan Aßmus 				}
495c4199192SAndrew Lindesay 				_AddRemovePackageFromLists(ref);
49687016f8fSAndrew Lindesay 				if ((changes & PKG_CHANGED_STATE) != 0
497*779ab335SX512 						&& !fCoordinator.IsSet()) {
4984e6fbe03SJulian Harnath 					fWorkStatusView->PackageStatusChanged(ref);
49957e51fffSStephan Aßmus 				}
50010cd325cSAndrew Lindesay 			}
50104c9d578SStephan Aßmus 			break;
50204c9d578SStephan Aßmus 		}
50304c9d578SStephan Aßmus 
50404c9d578SStephan Aßmus 		case MSG_RATE_PACKAGE:
5051bbda92dSStephan Aßmus 			_RatePackage();
50604c9d578SStephan Aßmus 			break;
50704c9d578SStephan Aßmus 
508d5ef985eSStephan Aßmus 		case MSG_SHOW_SCREENSHOT:
509d5ef985eSStephan Aßmus 			_ShowScreenshot();
510d5ef985eSStephan Aßmus 			break;
511d5ef985eSStephan Aßmus 
512125d42d9SJulian Harnath 		case MSG_PACKAGE_WORKER_BUSY:
513125d42d9SJulian Harnath 		{
514125d42d9SJulian Harnath 			BString reason;
515125d42d9SJulian Harnath 			status_t status = message->FindString("reason", &reason);
516125d42d9SJulian Harnath 			if (status != B_OK)
517125d42d9SJulian Harnath 				break;
518125d42d9SJulian Harnath 			fWorkStatusView->SetBusy(reason);
519125d42d9SJulian Harnath 			break;
520125d42d9SJulian Harnath 		}
521125d42d9SJulian Harnath 
522125d42d9SJulian Harnath 		case MSG_PACKAGE_WORKER_IDLE:
523125d42d9SJulian Harnath 			fWorkStatusView->SetIdle();
524125d42d9SJulian Harnath 			break;
525125d42d9SJulian Harnath 
52610cd325cSAndrew Lindesay 		case MSG_USER_USAGE_CONDITIONS_NOT_LATEST:
52710cd325cSAndrew Lindesay 		{
52810cd325cSAndrew Lindesay 			BMessage userDetailMsg;
52910cd325cSAndrew Lindesay 			if (message->FindMessage("userDetail", &userDetailMsg) != B_OK) {
53010cd325cSAndrew Lindesay 				debugger("expected the [userDetail] data to be carried in the "
53110cd325cSAndrew Lindesay 					"message.");
53210cd325cSAndrew Lindesay 			}
53310cd325cSAndrew Lindesay 			UserDetail userDetail(&userDetailMsg);
53410cd325cSAndrew Lindesay 			_HandleUserUsageConditionsNotLatest(userDetail);
53510cd325cSAndrew Lindesay 			break;
53610cd325cSAndrew Lindesay 		}
53710cd325cSAndrew Lindesay 
53804c9d578SStephan Aßmus 		default:
53904c9d578SStephan Aßmus 			BWindow::MessageReceived(message);
54004c9d578SStephan Aßmus 			break;
54104c9d578SStephan Aßmus 	}
54204c9d578SStephan Aßmus }
54304c9d578SStephan Aßmus 
54404c9d578SStephan Aßmus 
545ccf707d0SAndrew Lindesay static const char*
546ccf707d0SAndrew Lindesay main_window_package_list_view_mode_str(package_list_view_mode mode)
547ccf707d0SAndrew Lindesay {
548ccf707d0SAndrew Lindesay 	if (mode == PROMINENT)
549ccf707d0SAndrew Lindesay 		return "PROMINENT";
550ccf707d0SAndrew Lindesay 	return "ALL";
551ccf707d0SAndrew Lindesay }
552ccf707d0SAndrew Lindesay 
553ccf707d0SAndrew Lindesay 
554ccf707d0SAndrew Lindesay static package_list_view_mode
555ccf707d0SAndrew Lindesay main_window_str_to_package_list_view_mode(const BString& str)
556ccf707d0SAndrew Lindesay {
557ccf707d0SAndrew Lindesay 	if (str == "PROMINENT")
558ccf707d0SAndrew Lindesay 		return PROMINENT;
559ccf707d0SAndrew Lindesay 	return ALL;
560ccf707d0SAndrew Lindesay }
561ccf707d0SAndrew Lindesay 
562ccf707d0SAndrew Lindesay 
56304c9d578SStephan Aßmus void
56404c9d578SStephan Aßmus MainWindow::StoreSettings(BMessage& settings) const
56504c9d578SStephan Aßmus {
566f7c2983eSAxel Dörfler 	settings.AddRect(_WindowFrameName(), Frame());
567f7c2983eSAxel Dörfler 	if (!fSinglePackageMode) {
56804c9d578SStephan Aßmus 		settings.AddRect("window frame", Frame());
56904c9d578SStephan Aßmus 
57004c9d578SStephan Aßmus 		BMessage columnSettings;
5719883929bSAndrew Lindesay 		if (fPackageListView != NULL)
57204c9d578SStephan Aßmus 			fPackageListView->SaveState(&columnSettings);
57304c9d578SStephan Aßmus 
57404c9d578SStephan Aßmus 		settings.AddMessage("column settings", &columnSettings);
57504c9d578SStephan Aßmus 
576ccf707d0SAndrew Lindesay 		settings.AddString(KEY_PACKAGE_LIST_VIEW_MODE,
577ccf707d0SAndrew Lindesay 			main_window_package_list_view_mode_str(
578ccf707d0SAndrew Lindesay 				fModel.PackageListViewMode()));
5792997e05bSStephan Aßmus 		settings.AddBool("show available packages",
5802997e05bSStephan Aßmus 			fModel.ShowAvailablePackages());
5812997e05bSStephan Aßmus 		settings.AddBool("show installed packages",
5822997e05bSStephan Aßmus 			fModel.ShowInstalledPackages());
58304c9d578SStephan Aßmus 		settings.AddBool("show develop packages", fModel.ShowDevelopPackages());
58404c9d578SStephan Aßmus 		settings.AddBool("show source packages", fModel.ShowSourcePackages());
5856d519fd1SStephan Aßmus 	}
5868f03a0f9SStephan Aßmus 
587d2d4866dSAndrew Lindesay 	settings.AddString("username", fModel.Nickname());
58804c9d578SStephan Aßmus }
58904c9d578SStephan Aßmus 
59004c9d578SStephan Aßmus 
59104c9d578SStephan Aßmus void
59204c9d578SStephan Aßmus MainWindow::PackageChanged(const PackageInfoEvent& event)
59304c9d578SStephan Aßmus {
594a9edb9bfSAndrew Lindesay 	uint32 watchedChanges = PKG_CHANGED_STATE | PKG_CHANGED_PROMINENCE;
595a9edb9bfSAndrew Lindesay 	if ((event.Changes() & watchedChanges) != 0) {
59604c9d578SStephan Aßmus 		PackageInfoRef ref(event.Package());
597da651104SStephan Aßmus 		BMessage message(MSG_PACKAGE_CHANGED);
59804c9d578SStephan Aßmus 		message.AddPointer("package", ref.Get());
599da651104SStephan Aßmus 		message.AddUInt32("changes", event.Changes());
60004c9d578SStephan Aßmus 		ref.Detach();
60104c9d578SStephan Aßmus 			// reference needs to be released by MessageReceived();
60204c9d578SStephan Aßmus 		PostMessage(&message);
60304c9d578SStephan Aßmus 	}
60404c9d578SStephan Aßmus }
60504c9d578SStephan Aßmus 
60604c9d578SStephan Aßmus 
60704c9d578SStephan Aßmus status_t
60804c9d578SStephan Aßmus MainWindow::SchedulePackageActions(PackageActionList& list)
60904c9d578SStephan Aßmus {
61004c9d578SStephan Aßmus 	AutoLocker<BLocker> lock(&fPendingActionsLock);
61104c9d578SStephan Aßmus 	for (int32 i = 0; i < list.CountItems(); i++) {
61204c9d578SStephan Aßmus 		if (!fPendingActions.Add(list.ItemAtFast(i)))
61304c9d578SStephan Aßmus 			return B_NO_MEMORY;
61404c9d578SStephan Aßmus 	}
61504c9d578SStephan Aßmus 
61604c9d578SStephan Aßmus 	return release_sem_etc(fPendingActionsSem, list.CountItems(), 0);
61704c9d578SStephan Aßmus }
61804c9d578SStephan Aßmus 
61904c9d578SStephan Aßmus 
62004c9d578SStephan Aßmus Model*
62104c9d578SStephan Aßmus MainWindow::GetModel()
62204c9d578SStephan Aßmus {
62304c9d578SStephan Aßmus 	return &fModel;
62404c9d578SStephan Aßmus }
62504c9d578SStephan Aßmus 
62604c9d578SStephan Aßmus 
62704c9d578SStephan Aßmus void
62804c9d578SStephan Aßmus MainWindow::_BuildMenu(BMenuBar* menuBar)
62904c9d578SStephan Aßmus {
63004c9d578SStephan Aßmus 	BMenu* menu = new BMenu(B_TRANSLATE("Tools"));
6313369e03dSAndrew Lindesay 	fRefreshRepositoriesItem = new BMenuItem(
6323369e03dSAndrew Lindesay 		B_TRANSLATE("Refresh repositories"), new BMessage(MSG_REFRESH_REPOS));
6333369e03dSAndrew Lindesay 	menu->AddItem(fRefreshRepositoriesItem);
634d7f78130SHumdinger 	menu->AddItem(new BMenuItem(B_TRANSLATE("Manage repositories"
635d7f78130SHumdinger 		B_UTF8_ELLIPSIS), new BMessage(MSG_MANAGE_REPOS)));
636d144f952SAugustin Cavalier 	menu->AddItem(new BMenuItem(B_TRANSLATE("Check for updates"
637d144f952SAugustin Cavalier 		B_UTF8_ELLIPSIS), new BMessage(MSG_SOFTWARE_UPDATER)));
638e0a26dceSStephan Aßmus 
63904c9d578SStephan Aßmus 	menuBar->AddItem(menu);
64004c9d578SStephan Aßmus 
641b965ce70SHumdinger 	fRepositoryMenu = new BMenu(B_TRANSLATE("Repositories"));
642b965ce70SHumdinger 	menuBar->AddItem(fRepositoryMenu);
643b965ce70SHumdinger 
6444fade61fSStephan Aßmus 	menu = new BMenu(B_TRANSLATE("Show"));
6454fade61fSStephan Aßmus 
646fdec4227SStephan Aßmus 	fShowAvailablePackagesItem = new BMenuItem(
6474fade61fSStephan Aßmus 		B_TRANSLATE("Available packages"),
648fdec4227SStephan Aßmus 		new BMessage(MSG_SHOW_AVAILABLE_PACKAGES));
649fdec4227SStephan Aßmus 	menu->AddItem(fShowAvailablePackagesItem);
650fdec4227SStephan Aßmus 
651fdec4227SStephan Aßmus 	fShowInstalledPackagesItem = new BMenuItem(
6524fade61fSStephan Aßmus 		B_TRANSLATE("Installed packages"),
653fdec4227SStephan Aßmus 		new BMessage(MSG_SHOW_INSTALLED_PACKAGES));
654fdec4227SStephan Aßmus 	menu->AddItem(fShowInstalledPackagesItem);
655fdec4227SStephan Aßmus 
656fdec4227SStephan Aßmus 	menu->AddSeparatorItem();
657fdec4227SStephan Aßmus 
658fdec4227SStephan Aßmus 	fShowDevelopPackagesItem = new BMenuItem(
6594fade61fSStephan Aßmus 		B_TRANSLATE("Develop packages"),
660fdec4227SStephan Aßmus 		new BMessage(MSG_SHOW_DEVELOP_PACKAGES));
661fdec4227SStephan Aßmus 	menu->AddItem(fShowDevelopPackagesItem);
662fdec4227SStephan Aßmus 
663fdec4227SStephan Aßmus 	fShowSourcePackagesItem = new BMenuItem(
6644fade61fSStephan Aßmus 		B_TRANSLATE("Source packages"),
665fdec4227SStephan Aßmus 		new BMessage(MSG_SHOW_SOURCE_PACKAGES));
666fdec4227SStephan Aßmus 	menu->AddItem(fShowSourcePackagesItem);
667fdec4227SStephan Aßmus 
668fdec4227SStephan Aßmus 	menuBar->AddItem(menu);
66904c9d578SStephan Aßmus }
67004c9d578SStephan Aßmus 
67104c9d578SStephan Aßmus 
67204c9d578SStephan Aßmus void
673e0a26dceSStephan Aßmus MainWindow::_BuildUserMenu(BMenuBar* menuBar)
674e0a26dceSStephan Aßmus {
675e0a26dceSStephan Aßmus 	fUserMenu = new BMenu(B_TRANSLATE("Not logged in"));
676e0a26dceSStephan Aßmus 
677e0a26dceSStephan Aßmus 	fLogInItem = new BMenuItem(B_TRANSLATE("Log in" B_UTF8_ELLIPSIS),
678e0a26dceSStephan Aßmus 		new BMessage(MSG_LOG_IN));
679e0a26dceSStephan Aßmus 	fUserMenu->AddItem(fLogInItem);
680e0a26dceSStephan Aßmus 
681e0a26dceSStephan Aßmus 	fLogOutItem = new BMenuItem(B_TRANSLATE("Log out"),
682e0a26dceSStephan Aßmus 		new BMessage(MSG_LOG_OUT));
683e0a26dceSStephan Aßmus 	fUserMenu->AddItem(fLogOutItem);
684e0a26dceSStephan Aßmus 
6850c82f64bSAndrew Lindesay 	BMenuItem *latestUserUsageConditionsMenuItem =
6861448ced0SHumdinger 		new BMenuItem(B_TRANSLATE("View latest usage conditions"
68701339a54SAndrew Lindesay 			B_UTF8_ELLIPSIS),
68801339a54SAndrew Lindesay 			new BMessage(MSG_VIEW_LATEST_USER_USAGE_CONDITIONS));
6890c82f64bSAndrew Lindesay 	fUserMenu->AddItem(latestUserUsageConditionsMenuItem);
69001339a54SAndrew Lindesay 
691d2d4866dSAndrew Lindesay 	fUsersUserUsageConditionsMenuItem =
692d2d4866dSAndrew Lindesay 		new BMenuItem(B_TRANSLATE("View agreed usage conditions"
693d2d4866dSAndrew Lindesay 			B_UTF8_ELLIPSIS),
694d2d4866dSAndrew Lindesay 			new BMessage(MSG_VIEW_USERS_USER_USAGE_CONDITIONS));
695d2d4866dSAndrew Lindesay 	fUserMenu->AddItem(fUsersUserUsageConditionsMenuItem);
696d2d4866dSAndrew Lindesay 
697e0a26dceSStephan Aßmus 	menuBar->AddItem(fUserMenu);
698e0a26dceSStephan Aßmus }
699e0a26dceSStephan Aßmus 
700e0a26dceSStephan Aßmus 
701e0a26dceSStephan Aßmus void
702d2d4866dSAndrew Lindesay MainWindow::_RestoreNickname(const BMessage& settings)
703f7c2983eSAxel Dörfler {
704d2d4866dSAndrew Lindesay 	BString nickname;
705d2d4866dSAndrew Lindesay 	if (settings.FindString("username", &nickname) == B_OK
706d2d4866dSAndrew Lindesay 		&& nickname.Length() > 0) {
707d2d4866dSAndrew Lindesay 		fModel.SetNickname(nickname);
708f7c2983eSAxel Dörfler 	}
709f7c2983eSAxel Dörfler }
710f7c2983eSAxel Dörfler 
711f7c2983eSAxel Dörfler 
712f7c2983eSAxel Dörfler const char*
713f7c2983eSAxel Dörfler MainWindow::_WindowFrameName() const
714f7c2983eSAxel Dörfler {
715f7c2983eSAxel Dörfler 	if (fSinglePackageMode)
716f7c2983eSAxel Dörfler 		return "small window frame";
717f7c2983eSAxel Dörfler 
718f7c2983eSAxel Dörfler 	return "window frame";
719f7c2983eSAxel Dörfler }
720f7c2983eSAxel Dörfler 
721f7c2983eSAxel Dörfler 
722f7c2983eSAxel Dörfler void
723f7c2983eSAxel Dörfler MainWindow::_RestoreWindowFrame(const BMessage& settings)
724f7c2983eSAxel Dörfler {
725f7c2983eSAxel Dörfler 	BRect frame = Frame();
726f7c2983eSAxel Dörfler 
727f7c2983eSAxel Dörfler 	BRect windowFrame;
728f7c2983eSAxel Dörfler 	bool fromSettings = false;
729f7c2983eSAxel Dörfler 	if (settings.FindRect(_WindowFrameName(), &windowFrame) == B_OK) {
730f7c2983eSAxel Dörfler 		frame = windowFrame;
731f7c2983eSAxel Dörfler 		fromSettings = true;
732f7c2983eSAxel Dörfler 	} else if (!fSinglePackageMode) {
733f7c2983eSAxel Dörfler 		// Resize to occupy a certain screen size
734f7c2983eSAxel Dörfler 		BRect screenFrame = BScreen(this).Frame();
735f7c2983eSAxel Dörfler 		float width = frame.Width();
736f7c2983eSAxel Dörfler 		float height = frame.Height();
737f7c2983eSAxel Dörfler 		if (width < screenFrame.Width() * .666f
738f7c2983eSAxel Dörfler 			&& height < screenFrame.Height() * .666f) {
739f7c2983eSAxel Dörfler 			frame.bottom = frame.top + screenFrame.Height() * .666f;
740f7c2983eSAxel Dörfler 			frame.right = frame.left
741f7c2983eSAxel Dörfler 				+ std::min(screenFrame.Width() * .666f, height * 7 / 5);
742f7c2983eSAxel Dörfler 		}
743f7c2983eSAxel Dörfler 	}
744f7c2983eSAxel Dörfler 
745f7c2983eSAxel Dörfler 	MoveTo(frame.LeftTop());
746f7c2983eSAxel Dörfler 	ResizeTo(frame.Width(), frame.Height());
747f7c2983eSAxel Dörfler 
748f7c2983eSAxel Dörfler 	if (fromSettings)
7498e96ec34SAxel Dörfler 		MoveOnScreen();
750f7c2983eSAxel Dörfler 	else
751f7c2983eSAxel Dörfler 		CenterOnScreen();
752f7c2983eSAxel Dörfler }
753f7c2983eSAxel Dörfler 
754f7c2983eSAxel Dörfler 
755f7c2983eSAxel Dörfler void
756ccf707d0SAndrew Lindesay MainWindow::_RestoreModelSettings(const BMessage& settings)
757ccf707d0SAndrew Lindesay {
758ccf707d0SAndrew Lindesay 	BString packageListViewMode;
759ccf707d0SAndrew Lindesay 	if (settings.FindString(KEY_PACKAGE_LIST_VIEW_MODE,
760ccf707d0SAndrew Lindesay 			&packageListViewMode) == B_OK) {
761ccf707d0SAndrew Lindesay 		fModel.SetPackageListViewMode(
762ccf707d0SAndrew Lindesay 			main_window_str_to_package_list_view_mode(packageListViewMode));
763ccf707d0SAndrew Lindesay 	}
764ccf707d0SAndrew Lindesay 
765ccf707d0SAndrew Lindesay 	bool showOption;
766ccf707d0SAndrew Lindesay 	if (settings.FindBool("show available packages", &showOption) == B_OK)
767ccf707d0SAndrew Lindesay 		fModel.SetShowAvailablePackages(showOption);
768ccf707d0SAndrew Lindesay 	if (settings.FindBool("show installed packages", &showOption) == B_OK)
769ccf707d0SAndrew Lindesay 		fModel.SetShowInstalledPackages(showOption);
770ccf707d0SAndrew Lindesay 	if (settings.FindBool("show develop packages", &showOption) == B_OK)
771ccf707d0SAndrew Lindesay 		fModel.SetShowDevelopPackages(showOption);
772ccf707d0SAndrew Lindesay 	if (settings.FindBool("show source packages", &showOption) == B_OK)
773ccf707d0SAndrew Lindesay 		fModel.SetShowSourcePackages(showOption);
774ccf707d0SAndrew Lindesay }
775ccf707d0SAndrew Lindesay 
776ccf707d0SAndrew Lindesay 
777ccf707d0SAndrew Lindesay void
77863975654SStephan Aßmus MainWindow::_InitWorkerThreads()
77963975654SStephan Aßmus {
78063975654SStephan Aßmus 	fPendingActionsSem = create_sem(0, "PendingPackageActions");
78163975654SStephan Aßmus 	if (fPendingActionsSem >= 0) {
78263975654SStephan Aßmus 		fPendingActionsWorker = spawn_thread(&_PackageActionWorker,
78363975654SStephan Aßmus 			"Planet Express", B_NORMAL_PRIORITY, this);
78463975654SStephan Aßmus 		if (fPendingActionsWorker >= 0)
78563975654SStephan Aßmus 			resume_thread(fPendingActionsWorker);
78609f82905SStephan Aßmus 	} else
78709f82905SStephan Aßmus 		fPendingActionsWorker = -1;
78863975654SStephan Aßmus 
78963975654SStephan Aßmus 	fPackageToPopulateSem = create_sem(0, "PopulatePackage");
79063975654SStephan Aßmus 	if (fPackageToPopulateSem >= 0) {
79163975654SStephan Aßmus 		fPopulatePackageWorker = spawn_thread(&_PopulatePackageWorker,
79263975654SStephan Aßmus 			"Package Populator", B_NORMAL_PRIORITY, this);
79363975654SStephan Aßmus 		if (fPopulatePackageWorker >= 0)
79463975654SStephan Aßmus 			resume_thread(fPopulatePackageWorker);
79509f82905SStephan Aßmus 	} else
79609f82905SStephan Aßmus 		fPopulatePackageWorker = -1;
79763975654SStephan Aßmus }
79863975654SStephan Aßmus 
79963975654SStephan Aßmus 
80063975654SStephan Aßmus void
801c4199192SAndrew Lindesay MainWindow::_AdoptModelControls()
80204c9d578SStephan Aßmus {
8039883929bSAndrew Lindesay 	if (fSinglePackageMode)
8049883929bSAndrew Lindesay 		return;
8059883929bSAndrew Lindesay 
80604c9d578SStephan Aßmus 	BAutolock locker(fModel.Lock());
807fdec4227SStephan Aßmus 	fShowAvailablePackagesItem->SetMarked(fModel.ShowAvailablePackages());
808fdec4227SStephan Aßmus 	fShowInstalledPackagesItem->SetMarked(fModel.ShowInstalledPackages());
809fdec4227SStephan Aßmus 	fShowSourcePackagesItem->SetMarked(fModel.ShowSourcePackages());
810fdec4227SStephan Aßmus 	fShowDevelopPackagesItem->SetMarked(fModel.ShowDevelopPackages());
811da651104SStephan Aßmus 
812ccf707d0SAndrew Lindesay 	if (fModel.PackageListViewMode() == PROMINENT)
813ccf707d0SAndrew Lindesay 		fListTabs->Select(TAB_PROMINENT_PACKAGES);
8144fade61fSStephan Aßmus 	else
815ccf707d0SAndrew Lindesay 		fListTabs->Select(TAB_ALL_PACKAGES);
816b965ce70SHumdinger 
817b965ce70SHumdinger 	fFilterView->AdoptModel(fModel);
81804c9d578SStephan Aßmus }
81904c9d578SStephan Aßmus 
82004c9d578SStephan Aßmus 
82104c9d578SStephan Aßmus void
822c4199192SAndrew Lindesay MainWindow::_AdoptModel()
823c4199192SAndrew Lindesay {
824fa5c8097SAndrew Lindesay 	HDTRACE("adopting model to main window ui");
825c4199192SAndrew Lindesay 
826c4199192SAndrew Lindesay 	if (fSinglePackageMode)
827c4199192SAndrew Lindesay 		return;
828c4199192SAndrew Lindesay 
82905880d13SAndrew Lindesay 	std::vector<DepotInfoRef> depots = _CreateSnapshotOfDepots();
83005880d13SAndrew Lindesay 	std::vector<DepotInfoRef>::iterator it;
83105880d13SAndrew Lindesay 	for (it = depots.begin(); it != depots.end(); it++) {
83205880d13SAndrew Lindesay 		DepotInfoRef depotInfoRef = *it;
83305880d13SAndrew Lindesay 		const PackageList& packages = depotInfoRef->Packages();
834c4199192SAndrew Lindesay 		for (int32 p = 0; p < packages.CountItems(); p++)
835c4199192SAndrew Lindesay 			_AddRemovePackageFromLists(packages.ItemAtFast(p));
836c4199192SAndrew Lindesay 	}
837c4199192SAndrew Lindesay 
838c4199192SAndrew Lindesay 	_AdoptModelControls();
839c4199192SAndrew Lindesay }
840c4199192SAndrew Lindesay 
841c4199192SAndrew Lindesay 
842c4199192SAndrew Lindesay void
843c4199192SAndrew Lindesay MainWindow::_AddRemovePackageFromLists(const PackageInfoRef& package)
844c4199192SAndrew Lindesay {
845c4199192SAndrew Lindesay 	bool matches;
846c4199192SAndrew Lindesay 
847c4199192SAndrew Lindesay 	{
848c4199192SAndrew Lindesay 		AutoLocker<BLocker> modelLocker(fModel.Lock());
849c4199192SAndrew Lindesay 		matches = fModel.MatchesFilter(package);
850c4199192SAndrew Lindesay 	}
851c4199192SAndrew Lindesay 
852c4199192SAndrew Lindesay 	if (matches) {
853c4199192SAndrew Lindesay 		if (package->IsProminent())
854c4199192SAndrew Lindesay 			fFeaturedPackagesView->AddPackage(package);
855c4199192SAndrew Lindesay 		fPackageListView->AddPackage(package);
856c4199192SAndrew Lindesay 	} else {
857c4199192SAndrew Lindesay 		fFeaturedPackagesView->RemovePackage(package);
858c4199192SAndrew Lindesay 		fPackageListView->RemovePackage(package);
859c4199192SAndrew Lindesay 	}
860c4199192SAndrew Lindesay }
861c4199192SAndrew Lindesay 
862c4199192SAndrew Lindesay 
863c4199192SAndrew Lindesay void
86404c9d578SStephan Aßmus MainWindow::_AdoptPackage(const PackageInfoRef& package)
86504c9d578SStephan Aßmus {
86675ba9dbfSStephan Aßmus 	{
86775ba9dbfSStephan Aßmus 		BAutolock locker(fModel.Lock());
86804c9d578SStephan Aßmus 		fPackageInfoView->SetPackage(package);
8691986ab9fSStephan Aßmus 
870664372abSStephan Aßmus 		if (fFeaturedPackagesView != NULL)
871664372abSStephan Aßmus 			fFeaturedPackagesView->SelectPackage(package);
8721986ab9fSStephan Aßmus 		if (fPackageListView != NULL)
8731986ab9fSStephan Aßmus 			fPackageListView->SelectPackage(package);
87475ba9dbfSStephan Aßmus 	}
87504c9d578SStephan Aßmus 
876a9edb9bfSAndrew Lindesay 	_PopulatePackageAsync(false);
87704c9d578SStephan Aßmus }
87804c9d578SStephan Aßmus 
87904c9d578SStephan Aßmus 
88004c9d578SStephan Aßmus void
88104c9d578SStephan Aßmus MainWindow::_ClearPackage()
88204c9d578SStephan Aßmus {
88304c9d578SStephan Aßmus 	fPackageInfoView->Clear();
88404c9d578SStephan Aßmus }
88504c9d578SStephan Aßmus 
88604c9d578SStephan Aßmus 
88704c9d578SStephan Aßmus void
8883369e03dSAndrew Lindesay MainWindow::_StartBulkLoad(bool force)
88904c9d578SStephan Aßmus {
890c4199192SAndrew Lindesay 	if (fFeaturedPackagesView != NULL)
891c4199192SAndrew Lindesay 		fFeaturedPackagesView->Clear();
892c4199192SAndrew Lindesay 	if (fPackageListView != NULL)
893c4199192SAndrew Lindesay 		fPackageListView->Clear();
894c4199192SAndrew Lindesay 	fPackageInfoView->Clear();
895c4199192SAndrew Lindesay 
89610cd325cSAndrew Lindesay 	fRefreshRepositoriesItem->SetEnabled(false);
89710cd325cSAndrew Lindesay 	ProcessCoordinator* bulkLoadCoordinator =
89810cd325cSAndrew Lindesay 		ProcessCoordinatorFactory::CreateBulkLoadCoordinator(
8993369e03dSAndrew Lindesay 			this,
9003369e03dSAndrew Lindesay 				// PackageInfoListener
9013369e03dSAndrew Lindesay 			this,
9023369e03dSAndrew Lindesay 				// ProcessCoordinatorListener
9033369e03dSAndrew Lindesay 			&fModel, force);
90410cd325cSAndrew Lindesay 	_AddProcessCoordinator(bulkLoadCoordinator);
90504c9d578SStephan Aßmus }
90604c9d578SStephan Aßmus 
90704c9d578SStephan Aßmus 
90804c9d578SStephan Aßmus void
90910cd325cSAndrew Lindesay MainWindow::_BulkLoadCompleteReceived(status_t errorStatus)
91004c9d578SStephan Aßmus {
91110cd325cSAndrew Lindesay 	if (errorStatus != B_OK) {
9123369e03dSAndrew Lindesay 		AppUtils::NotifySimpleError(
9131448ced0SHumdinger 			B_TRANSLATE("Package update error"),
9143369e03dSAndrew Lindesay 			B_TRANSLATE("While updating package data, a problem has arisen "
9153369e03dSAndrew Lindesay 				"that may cause data to be outdated or missing from the "
9163369e03dSAndrew Lindesay 				"application's display. Additional details regarding this "
9173369e03dSAndrew Lindesay 				"problem may be able to be obtained from the application "
918b21c9447SAndrew Lindesay 				"logs."
919b21c9447SAndrew Lindesay 				ALERT_MSG_LOGS_USER_GUIDE));
92004c9d578SStephan Aßmus 	}
92110cd325cSAndrew Lindesay 
9223369e03dSAndrew Lindesay 	fRefreshRepositoriesItem->SetEnabled(true);
92310cd325cSAndrew Lindesay 	_AdoptModel();
92410cd325cSAndrew Lindesay 	_UpdateAvailableRepositories();
925ccf707d0SAndrew Lindesay 
926ccf707d0SAndrew Lindesay 	// if after loading everything in, it transpires that there are no
927ccf707d0SAndrew Lindesay 	// featured packages then the featured packages should be disabled
928ccf707d0SAndrew Lindesay 	// and the user should be switched to the "all packages" view so
929ccf707d0SAndrew Lindesay 	// that they are not presented with a blank window!
930ccf707d0SAndrew Lindesay 
931ccf707d0SAndrew Lindesay 	bool hasProminentPackages = fModel.HasAnyProminentPackages();
932ccf707d0SAndrew Lindesay 	fListTabs->TabAt(TAB_PROMINENT_PACKAGES)->SetEnabled(hasProminentPackages);
933ccf707d0SAndrew Lindesay 	if (!hasProminentPackages
934ccf707d0SAndrew Lindesay 			&& fListTabs->Selection() == TAB_PROMINENT_PACKAGES) {
935ccf707d0SAndrew Lindesay 		fModel.SetPackageListViewMode(ALL);
936ccf707d0SAndrew Lindesay 		fListTabs->Select(TAB_ALL_PACKAGES);
937ccf707d0SAndrew Lindesay 	}
93804c9d578SStephan Aßmus }
93904c9d578SStephan Aßmus 
94004c9d578SStephan Aßmus 
9413369e03dSAndrew Lindesay void
94210cd325cSAndrew Lindesay MainWindow::_NotifyWorkStatusClear()
94304c9d578SStephan Aßmus {
94410cd325cSAndrew Lindesay 	BMessage message(MSG_WORK_STATUS_CLEAR);
94510cd325cSAndrew Lindesay 	this->PostMessage(&message, this);
94610cd325cSAndrew Lindesay }
94710cd325cSAndrew Lindesay 
94810cd325cSAndrew Lindesay 
94910cd325cSAndrew Lindesay void
95010cd325cSAndrew Lindesay MainWindow::_HandleWorkStatusClear()
95110cd325cSAndrew Lindesay {
95210cd325cSAndrew Lindesay 	fWorkStatusView->SetText("");
9533369e03dSAndrew Lindesay 	fWorkStatusView->SetIdle();
9543369e03dSAndrew Lindesay }
95504c9d578SStephan Aßmus 
95604c9d578SStephan Aßmus 
9573369e03dSAndrew Lindesay /*! Sends off a message to the Window so that it can change the status view
9583369e03dSAndrew Lindesay     on the front-end in the UI thread.
9593369e03dSAndrew Lindesay */
96004c9d578SStephan Aßmus 
9613369e03dSAndrew Lindesay void
9623369e03dSAndrew Lindesay MainWindow::_NotifyWorkStatusChange(const BString& text, float progress)
9633369e03dSAndrew Lindesay {
9643369e03dSAndrew Lindesay 	BMessage message(MSG_WORK_STATUS_CHANGE);
96504c9d578SStephan Aßmus 
9663369e03dSAndrew Lindesay 	if (!text.IsEmpty())
9673369e03dSAndrew Lindesay 		message.AddString(KEY_WORK_STATUS_TEXT, text);
9683369e03dSAndrew Lindesay 	message.AddFloat(KEY_WORK_STATUS_PROGRESS, progress);
96904c9d578SStephan Aßmus 
9703369e03dSAndrew Lindesay 	this->PostMessage(&message, this);
9713369e03dSAndrew Lindesay }
97204c9d578SStephan Aßmus 
9733369e03dSAndrew Lindesay 
9743369e03dSAndrew Lindesay void
9753369e03dSAndrew Lindesay MainWindow::_HandleWorkStatusChangeMessageReceived(const BMessage* message)
9763369e03dSAndrew Lindesay {
9779883929bSAndrew Lindesay 	if (fWorkStatusView == NULL)
9789883929bSAndrew Lindesay 		return;
9799883929bSAndrew Lindesay 
9803369e03dSAndrew Lindesay 	BString text;
9813369e03dSAndrew Lindesay 	float progress;
9823369e03dSAndrew Lindesay 
9833369e03dSAndrew Lindesay 	if (message->FindString(KEY_WORK_STATUS_TEXT, &text) == B_OK)
9843369e03dSAndrew Lindesay 		fWorkStatusView->SetText(text);
9853369e03dSAndrew Lindesay 
9863369e03dSAndrew Lindesay 	if (message->FindFloat(KEY_WORK_STATUS_PROGRESS, &progress) == B_OK)
9873369e03dSAndrew Lindesay 		fWorkStatusView->SetProgress(progress);
98804c9d578SStephan Aßmus }
98904c9d578SStephan Aßmus 
99004c9d578SStephan Aßmus 
99104c9d578SStephan Aßmus status_t
99204c9d578SStephan Aßmus MainWindow::_PackageActionWorker(void* arg)
99304c9d578SStephan Aßmus {
99404c9d578SStephan Aßmus 	MainWindow* window = reinterpret_cast<MainWindow*>(arg);
99504c9d578SStephan Aßmus 
99604c9d578SStephan Aßmus 	while (acquire_sem(window->fPendingActionsSem) == B_OK) {
99704c9d578SStephan Aßmus 		PackageActionRef ref;
99804c9d578SStephan Aßmus 		{
99904c9d578SStephan Aßmus 			AutoLocker<BLocker> lock(&window->fPendingActionsLock);
100004c9d578SStephan Aßmus 			ref = window->fPendingActions.ItemAt(0);
1001*779ab335SX512 			if (!ref.IsSet())
100204c9d578SStephan Aßmus 				break;
100304c9d578SStephan Aßmus 			window->fPendingActions.Remove(0);
100404c9d578SStephan Aßmus 		}
100504c9d578SStephan Aßmus 
1006125d42d9SJulian Harnath 		BMessenger messenger(window);
1007125d42d9SJulian Harnath 		BMessage busyMessage(MSG_PACKAGE_WORKER_BUSY);
1008125d42d9SJulian Harnath 		BString text(ref->Label());
1009bc622f6bSHumdinger 		text << B_UTF8_ELLIPSIS;
1010125d42d9SJulian Harnath 		busyMessage.AddString("reason", text);
1011125d42d9SJulian Harnath 
1012125d42d9SJulian Harnath 		messenger.SendMessage(&busyMessage);
101304c9d578SStephan Aßmus 		ref->Perform();
1014125d42d9SJulian Harnath 		messenger.SendMessage(MSG_PACKAGE_WORKER_IDLE);
101504c9d578SStephan Aßmus 	}
101604c9d578SStephan Aßmus 
101704c9d578SStephan Aßmus 	return 0;
101804c9d578SStephan Aßmus }
101904c9d578SStephan Aßmus 
102004c9d578SStephan Aßmus 
1021a9edb9bfSAndrew Lindesay /*! This method will cause the package to have its data refreshed from
1022a9edb9bfSAndrew Lindesay     the server application.  The refresh happens in the background; this method
1023a9edb9bfSAndrew Lindesay     is asynchronous.
1024a9edb9bfSAndrew Lindesay */
1025a9edb9bfSAndrew Lindesay 
1026a9edb9bfSAndrew Lindesay void
1027a9edb9bfSAndrew Lindesay MainWindow::_PopulatePackageAsync(bool forcePopulate)
1028a9edb9bfSAndrew Lindesay {
1029a9edb9bfSAndrew Lindesay 		// Trigger asynchronous package population from the web-app
1030a9edb9bfSAndrew Lindesay 	{
1031a9edb9bfSAndrew Lindesay 		AutoLocker<BLocker> lock(&fPackageToPopulateLock);
1032a9edb9bfSAndrew Lindesay 		fPackageToPopulate = fPackageInfoView->Package();
1033a9edb9bfSAndrew Lindesay 		fForcePopulatePackage = forcePopulate;
1034a9edb9bfSAndrew Lindesay 	}
1035a9edb9bfSAndrew Lindesay 	release_sem_etc(fPackageToPopulateSem, 1, 0);
1036a9edb9bfSAndrew Lindesay 
1037f96d1f4dSAndrew Lindesay 	HDDEBUG("pkg [%s] will be updated from the server.",
1038fa5c8097SAndrew Lindesay 		fPackageToPopulate->Name().String());
1039a9edb9bfSAndrew Lindesay }
1040a9edb9bfSAndrew Lindesay 
1041a9edb9bfSAndrew Lindesay 
1042a9edb9bfSAndrew Lindesay /*! This method will run in the background.  The thread will block until there
1043a9edb9bfSAndrew Lindesay     is a package to be updated.  When the thread unblocks, it will update the
1044a9edb9bfSAndrew Lindesay     package with information from the server.
1045a9edb9bfSAndrew Lindesay */
1046a9edb9bfSAndrew Lindesay 
104704c9d578SStephan Aßmus status_t
104804c9d578SStephan Aßmus MainWindow::_PopulatePackageWorker(void* arg)
104904c9d578SStephan Aßmus {
105004c9d578SStephan Aßmus 	MainWindow* window = reinterpret_cast<MainWindow*>(arg);
105104c9d578SStephan Aßmus 
105204c9d578SStephan Aßmus 	while (acquire_sem(window->fPackageToPopulateSem) == B_OK) {
105304c9d578SStephan Aßmus 		PackageInfoRef package;
1054a9edb9bfSAndrew Lindesay 		bool force;
105504c9d578SStephan Aßmus 		{
105604c9d578SStephan Aßmus 			AutoLocker<BLocker> lock(&window->fPackageToPopulateLock);
105704c9d578SStephan Aßmus 			package = window->fPackageToPopulate;
1058a9edb9bfSAndrew Lindesay 			force = window->fForcePopulatePackage;
105904c9d578SStephan Aßmus 		}
106004c9d578SStephan Aßmus 
1061*779ab335SX512 		if (package.IsSet()) {
1062a9edb9bfSAndrew Lindesay 			uint32 populateFlags = Model::POPULATE_USER_RATINGS
1063a9edb9bfSAndrew Lindesay 				| Model::POPULATE_SCREEN_SHOTS
1064a9edb9bfSAndrew Lindesay 				| Model::POPULATE_CHANGELOG;
1065a9edb9bfSAndrew Lindesay 
1066a9edb9bfSAndrew Lindesay 			if (force)
1067a9edb9bfSAndrew Lindesay 				populateFlags |= Model::POPULATE_FORCE;
1068a9edb9bfSAndrew Lindesay 
1069a9edb9bfSAndrew Lindesay 			window->fModel.PopulatePackage(package, populateFlags);
1070a9edb9bfSAndrew Lindesay 
1071fa5c8097SAndrew Lindesay 			HDDEBUG("populating package [%s]", package->Name().String());
107204c9d578SStephan Aßmus 		}
107304c9d578SStephan Aßmus 	}
107404c9d578SStephan Aßmus 
107504c9d578SStephan Aßmus 	return 0;
107604c9d578SStephan Aßmus }
107704c9d578SStephan Aßmus 
107804c9d578SStephan Aßmus 
107904c9d578SStephan Aßmus void
10801bbda92dSStephan Aßmus MainWindow::_OpenLoginWindow(const BMessage& onSuccessMessage)
108104c9d578SStephan Aßmus {
108204c9d578SStephan Aßmus 	UserLoginWindow* window = new UserLoginWindow(this,
108304c9d578SStephan Aßmus 		BRect(0, 0, 500, 400), fModel);
10841bbda92dSStephan Aßmus 
10851bbda92dSStephan Aßmus 	if (onSuccessMessage.what != 0)
10861bbda92dSStephan Aßmus 		window->SetOnSuccessMessage(BMessenger(this), onSuccessMessage);
10871bbda92dSStephan Aßmus 
108804c9d578SStephan Aßmus 	window->Show();
108904c9d578SStephan Aßmus }
109004c9d578SStephan Aßmus 
10918f03a0f9SStephan Aßmus 
10928f03a0f9SStephan Aßmus void
109310cd325cSAndrew Lindesay MainWindow::_StartUserVerify()
109410cd325cSAndrew Lindesay {
109510cd325cSAndrew Lindesay 	if (!fModel.Nickname().IsEmpty()) {
109610cd325cSAndrew Lindesay 		_AddProcessCoordinator(
109710cd325cSAndrew Lindesay 			ProcessCoordinatorFactory::CreateUserDetailVerifierCoordinator(
109810cd325cSAndrew Lindesay 				this,
109910cd325cSAndrew Lindesay 					// UserDetailVerifierListener
110010cd325cSAndrew Lindesay 				this,
110110cd325cSAndrew Lindesay 					// ProcessCoordinatorListener
110210cd325cSAndrew Lindesay 				&fModel) );
110310cd325cSAndrew Lindesay 	}
110410cd325cSAndrew Lindesay }
110510cd325cSAndrew Lindesay 
110610cd325cSAndrew Lindesay 
110710cd325cSAndrew Lindesay void
11088f03a0f9SStephan Aßmus MainWindow::_UpdateAuthorization()
11098f03a0f9SStephan Aßmus {
1110d2d4866dSAndrew Lindesay 	BString nickname(fModel.Nickname());
1111d2d4866dSAndrew Lindesay 	bool hasUser = !nickname.IsEmpty();
1112e0a26dceSStephan Aßmus 
11136d519fd1SStephan Aßmus 	if (fLogOutItem != NULL)
1114e0a26dceSStephan Aßmus 		fLogOutItem->SetEnabled(hasUser);
1115d2d4866dSAndrew Lindesay 	if (fUsersUserUsageConditionsMenuItem != NULL)
1116d2d4866dSAndrew Lindesay 		fUsersUserUsageConditionsMenuItem->SetEnabled(hasUser);
1117e0a26dceSStephan Aßmus 	if (fLogInItem != NULL) {
1118e0a26dceSStephan Aßmus 		if (hasUser)
1119e0a26dceSStephan Aßmus 			fLogInItem->SetLabel(B_TRANSLATE("Switch account" B_UTF8_ELLIPSIS));
1120e0a26dceSStephan Aßmus 		else
1121e0a26dceSStephan Aßmus 			fLogInItem->SetLabel(B_TRANSLATE("Log in" B_UTF8_ELLIPSIS));
1122e0a26dceSStephan Aßmus 	}
1123e0a26dceSStephan Aßmus 
1124e0a26dceSStephan Aßmus 	if (fUserMenu != NULL) {
1125e0a26dceSStephan Aßmus 		BString label;
1126d2d4866dSAndrew Lindesay 		if (hasUser) {
1127e0a26dceSStephan Aßmus 			label = B_TRANSLATE("Logged in as %User%");
1128d2d4866dSAndrew Lindesay 			label.ReplaceAll("%User%", nickname);
1129d2d4866dSAndrew Lindesay 		} else {
1130d2d4866dSAndrew Lindesay 			label = B_TRANSLATE("Not logged in");
1131e0a26dceSStephan Aßmus 		}
1132e0a26dceSStephan Aßmus 		fUserMenu->Superitem()->SetLabel(label);
1133e0a26dceSStephan Aßmus 	}
11348f03a0f9SStephan Aßmus }
11351bbda92dSStephan Aßmus 
11361bbda92dSStephan Aßmus 
11371bbda92dSStephan Aßmus void
1138b965ce70SHumdinger MainWindow::_UpdateAvailableRepositories()
1139b965ce70SHumdinger {
1140b965ce70SHumdinger 	fRepositoryMenu->RemoveItems(0, fRepositoryMenu->CountItems(), true);
1141b965ce70SHumdinger 
1142b965ce70SHumdinger 	fRepositoryMenu->AddItem(new BMenuItem(B_TRANSLATE("All repositories"),
1143b965ce70SHumdinger 		new BMessage(MSG_DEPOT_SELECTED)));
1144b965ce70SHumdinger 
1145b965ce70SHumdinger 	fRepositoryMenu->AddItem(new BSeparatorItem());
1146b965ce70SHumdinger 
1147b965ce70SHumdinger 	bool foundSelectedDepot = false;
114805880d13SAndrew Lindesay 	std::vector<DepotInfoRef> depots = _CreateSnapshotOfDepots();
114905880d13SAndrew Lindesay 	std::vector<DepotInfoRef>::iterator it;
1150d13c3d89SAndrew Lindesay 
115105880d13SAndrew Lindesay 	for (it = depots.begin(); it != depots.end(); it++) {
115205880d13SAndrew Lindesay 		DepotInfoRef depot = *it;
115305880d13SAndrew Lindesay 
115405880d13SAndrew Lindesay 		if (depot->Name().Length() != 0) {
1155b965ce70SHumdinger 			BMessage* message = new BMessage(MSG_DEPOT_SELECTED);
115605880d13SAndrew Lindesay 			message->AddString("name", depot->Name());
115705880d13SAndrew Lindesay 			BMenuItem* item = new(std::nothrow) BMenuItem(depot->Name(), message);
115805880d13SAndrew Lindesay 
115905880d13SAndrew Lindesay 			if (item == NULL)
116005880d13SAndrew Lindesay 				HDFATAL("memory exhaustion");
116105880d13SAndrew Lindesay 
1162b965ce70SHumdinger 			fRepositoryMenu->AddItem(item);
1163b965ce70SHumdinger 
116405880d13SAndrew Lindesay 			if (depot->Name() == fModel.Depot()) {
1165b965ce70SHumdinger 				item->SetMarked(true);
1166b965ce70SHumdinger 				foundSelectedDepot = true;
1167b965ce70SHumdinger 			}
1168b965ce70SHumdinger 		}
1169d13c3d89SAndrew Lindesay 	}
1170b965ce70SHumdinger 
1171b965ce70SHumdinger 	if (!foundSelectedDepot)
1172b965ce70SHumdinger 		fRepositoryMenu->ItemAt(0)->SetMarked(true);
1173b965ce70SHumdinger }
1174b965ce70SHumdinger 
1175b965ce70SHumdinger 
1176a9edb9bfSAndrew Lindesay bool
1177a9edb9bfSAndrew Lindesay MainWindow::_SelectedPackageHasWebAppRepositoryCode()
1178a9edb9bfSAndrew Lindesay {
1179a9edb9bfSAndrew Lindesay 	const PackageInfoRef& package = fPackageInfoView->Package();
11806ab878c0SAndrew Lindesay 	const BString depotName = package->DepotName();
1181a9edb9bfSAndrew Lindesay 
11826ab878c0SAndrew Lindesay 	if (depotName.IsEmpty()) {
1183fa5c8097SAndrew Lindesay 		HDDEBUG("the package [%s] has no depot name", package->Name().String());
11846ab878c0SAndrew Lindesay 	} else {
11856ab878c0SAndrew Lindesay 		const DepotInfo* depot = fModel.DepotForName(depotName);
1186a9edb9bfSAndrew Lindesay 
11876ab878c0SAndrew Lindesay 		if (depot == NULL) {
1188f96d1f4dSAndrew Lindesay 			HDINFO("the depot [%s] was not able to be found",
1189fa5c8097SAndrew Lindesay 				depotName.String());
11906ab878c0SAndrew Lindesay 		} else {
11916ab878c0SAndrew Lindesay 			BString repositoryCode = depot->WebAppRepositoryCode();
1192a9edb9bfSAndrew Lindesay 
11936ab878c0SAndrew Lindesay 			if (repositoryCode.IsEmpty()) {
1194f96d1f4dSAndrew Lindesay 				HDINFO("the depot [%s] has no web app repository code",
1195fa5c8097SAndrew Lindesay 					depotName.String());
1196fa5c8097SAndrew Lindesay 			} else
11976ab878c0SAndrew Lindesay 				return true;
11986ab878c0SAndrew Lindesay 		}
11996ab878c0SAndrew Lindesay 	}
12006ab878c0SAndrew Lindesay 
12016ab878c0SAndrew Lindesay 	return false;
1202a9edb9bfSAndrew Lindesay }
1203a9edb9bfSAndrew Lindesay 
1204a9edb9bfSAndrew Lindesay 
1205b965ce70SHumdinger void
12061bbda92dSStephan Aßmus MainWindow::_RatePackage()
12071bbda92dSStephan Aßmus {
1208a9edb9bfSAndrew Lindesay 	if (!_SelectedPackageHasWebAppRepositoryCode()) {
1209a9edb9bfSAndrew Lindesay 		BAlert* alert = new(std::nothrow) BAlert(
1210cbadcae1SHumdinger 			B_TRANSLATE("Rating not possible"),
1211cbadcae1SHumdinger 			B_TRANSLATE("This package doesn't seem to be on the HaikuDepot "
1212cbadcae1SHumdinger 				"Server, so it's not possible to create a new rating "
1213cbadcae1SHumdinger 				"or edit an existing rating."),
1214a9edb9bfSAndrew Lindesay 			B_TRANSLATE("OK"));
1215a9edb9bfSAndrew Lindesay 		alert->Go();
1216a9edb9bfSAndrew Lindesay     	return;
1217a9edb9bfSAndrew Lindesay 	}
1218a9edb9bfSAndrew Lindesay 
1219d2d4866dSAndrew Lindesay 	if (fModel.Nickname().IsEmpty()) {
12201bbda92dSStephan Aßmus 		BAlert* alert = new(std::nothrow) BAlert(
12211bbda92dSStephan Aßmus 			B_TRANSLATE("Not logged in"),
12221bbda92dSStephan Aßmus 			B_TRANSLATE("You need to be logged into an account before you "
12231bbda92dSStephan Aßmus 				"can rate packages."),
12241bbda92dSStephan Aßmus 			B_TRANSLATE("Cancel"),
12251bbda92dSStephan Aßmus 			B_TRANSLATE("Login or Create account"));
12261bbda92dSStephan Aßmus 
12271bbda92dSStephan Aßmus 		if (alert == NULL)
12281bbda92dSStephan Aßmus 			return;
12291bbda92dSStephan Aßmus 
12301bbda92dSStephan Aßmus 		int32 choice = alert->Go();
12311bbda92dSStephan Aßmus 		if (choice == 1)
12321bbda92dSStephan Aßmus 			_OpenLoginWindow(BMessage(MSG_RATE_PACKAGE));
12331bbda92dSStephan Aßmus 		return;
12341bbda92dSStephan Aßmus 	}
12351bbda92dSStephan Aßmus 
12361bbda92dSStephan Aßmus 	// TODO: Allow only one RatePackageWindow
12371bbda92dSStephan Aßmus 	// TODO: Mechanism for remembering the window frame
12381bbda92dSStephan Aßmus 	RatePackageWindow* window = new RatePackageWindow(this,
12391bbda92dSStephan Aßmus 		BRect(0, 0, 500, 400), fModel);
12401bbda92dSStephan Aßmus 	window->SetPackage(fPackageInfoView->Package());
12411bbda92dSStephan Aßmus 	window->Show();
12421bbda92dSStephan Aßmus }
1243d5ef985eSStephan Aßmus 
1244d5ef985eSStephan Aßmus 
1245d5ef985eSStephan Aßmus void
1246d5ef985eSStephan Aßmus MainWindow::_ShowScreenshot()
1247d5ef985eSStephan Aßmus {
1248d5ef985eSStephan Aßmus 	// TODO: Mechanism for remembering the window frame
1249d5ef985eSStephan Aßmus 	if (fScreenshotWindow == NULL)
1250d5ef985eSStephan Aßmus 		fScreenshotWindow = new ScreenshotWindow(this, BRect(0, 0, 500, 400));
1251d5ef985eSStephan Aßmus 
1252d5ef985eSStephan Aßmus 	if (fScreenshotWindow->LockWithTimeout(1000) != B_OK)
1253d5ef985eSStephan Aßmus 		return;
1254d5ef985eSStephan Aßmus 
1255d5ef985eSStephan Aßmus 	fScreenshotWindow->SetPackage(fPackageInfoView->Package());
1256d5ef985eSStephan Aßmus 
1257d5ef985eSStephan Aßmus 	if (fScreenshotWindow->IsHidden())
1258d5ef985eSStephan Aßmus 		fScreenshotWindow->Show();
1259d5ef985eSStephan Aßmus 	else
1260d5ef985eSStephan Aßmus 		fScreenshotWindow->Activate();
1261d5ef985eSStephan Aßmus 
1262d5ef985eSStephan Aßmus 	fScreenshotWindow->Unlock();
1263d5ef985eSStephan Aßmus }
126401339a54SAndrew Lindesay 
126501339a54SAndrew Lindesay 
126601339a54SAndrew Lindesay void
1267d2d4866dSAndrew Lindesay MainWindow::_ViewUserUsageConditions(
1268d2d4866dSAndrew Lindesay 	UserUsageConditionsSelectionMode mode)
126901339a54SAndrew Lindesay {
127001339a54SAndrew Lindesay 	UserUsageConditionsWindow* window = new UserUsageConditionsWindow(
1271d2d4866dSAndrew Lindesay 		fModel, mode);
127201339a54SAndrew Lindesay 	window->Show();
127301339a54SAndrew Lindesay }
127410cd325cSAndrew Lindesay 
127510cd325cSAndrew Lindesay 
127610cd325cSAndrew Lindesay void
127710cd325cSAndrew Lindesay MainWindow::UserCredentialsFailed()
127810cd325cSAndrew Lindesay {
127910cd325cSAndrew Lindesay 	BString message = B_TRANSLATE("The password previously "
128010cd325cSAndrew Lindesay 		"supplied for the user [%Nickname%] is not currently "
128110cd325cSAndrew Lindesay 		"valid. The user will be logged-out of this application "
128210cd325cSAndrew Lindesay 		"and you should login again with your updated password.");
128310cd325cSAndrew Lindesay 	message.ReplaceAll("%Nickname%", fModel.Nickname());
128410cd325cSAndrew Lindesay 
128510cd325cSAndrew Lindesay 	AppUtils::NotifySimpleError(B_TRANSLATE("Login issue"),
128610cd325cSAndrew Lindesay 		message);
128710cd325cSAndrew Lindesay 
128810cd325cSAndrew Lindesay 	{
128910cd325cSAndrew Lindesay 		AutoLocker<BLocker> locker(fModel.Lock());
129010cd325cSAndrew Lindesay 		fModel.SetNickname("");
129110cd325cSAndrew Lindesay 	}
129210cd325cSAndrew Lindesay }
129310cd325cSAndrew Lindesay 
129410cd325cSAndrew Lindesay 
129510cd325cSAndrew Lindesay /*! \brief This method is invoked from the UserDetailVerifierProcess on a
129610cd325cSAndrew Lindesay 		   background thread.  For this reason it lodges a message into itself
129710cd325cSAndrew Lindesay 		   which can then be handled on the main thread.
129810cd325cSAndrew Lindesay */
129910cd325cSAndrew Lindesay 
130010cd325cSAndrew Lindesay void
130110cd325cSAndrew Lindesay MainWindow::UserUsageConditionsNotLatest(const UserDetail& userDetail)
130210cd325cSAndrew Lindesay {
130310cd325cSAndrew Lindesay 	BMessage message(MSG_USER_USAGE_CONDITIONS_NOT_LATEST);
130410cd325cSAndrew Lindesay 	BMessage detailsMessage;
130510cd325cSAndrew Lindesay 	if (userDetail.Archive(&detailsMessage, true) != B_OK
130610cd325cSAndrew Lindesay 			|| message.AddMessage("userDetail", &detailsMessage) != B_OK) {
1307fa5c8097SAndrew Lindesay 		HDERROR("unable to archive the user detail into a message");
130810cd325cSAndrew Lindesay 	}
130910cd325cSAndrew Lindesay 	else
131010cd325cSAndrew Lindesay 		BMessenger(this).SendMessage(&message);
131110cd325cSAndrew Lindesay }
131210cd325cSAndrew Lindesay 
131310cd325cSAndrew Lindesay 
131410cd325cSAndrew Lindesay void
131510cd325cSAndrew Lindesay MainWindow::_HandleUserUsageConditionsNotLatest(
131610cd325cSAndrew Lindesay 	const UserDetail& userDetail)
131710cd325cSAndrew Lindesay {
131810cd325cSAndrew Lindesay 	ToLatestUserUsageConditionsWindow* window =
131910cd325cSAndrew Lindesay 		new ToLatestUserUsageConditionsWindow(this, fModel, userDetail);
132010cd325cSAndrew Lindesay 	window->Show();
132110cd325cSAndrew Lindesay }
132210cd325cSAndrew Lindesay 
132310cd325cSAndrew Lindesay 
132410cd325cSAndrew Lindesay void
132510cd325cSAndrew Lindesay MainWindow::_AddProcessCoordinator(ProcessCoordinator* item)
132610cd325cSAndrew Lindesay {
132710cd325cSAndrew Lindesay 	AutoLocker<BLocker> lock(&fCoordinatorLock);
132810cd325cSAndrew Lindesay 
1329*779ab335SX512 	if (!fCoordinator.IsSet()) {
133010cd325cSAndrew Lindesay 		if (acquire_sem(fCoordinatorRunningSem) != B_OK)
133110cd325cSAndrew Lindesay 			debugger("unable to acquire the process coordinator sem");
1332f96d1f4dSAndrew Lindesay 		HDINFO("adding and starting a process coordinator [%s]",
1333fa5c8097SAndrew Lindesay 			item->Name().String());
1334f95ec23eSAndrew Lindesay 		fCoordinator = BReference<ProcessCoordinator>(item);
133510cd325cSAndrew Lindesay 		fCoordinator->Start();
133610cd325cSAndrew Lindesay 	}
133710cd325cSAndrew Lindesay 	else {
1338f96d1f4dSAndrew Lindesay 		HDINFO("adding process coordinator [%s] to the queue",
133910cd325cSAndrew Lindesay 			item->Name().String());
134010cd325cSAndrew Lindesay 		fCoordinatorQueue.push(item);
134110cd325cSAndrew Lindesay 	}
134210cd325cSAndrew Lindesay }
134310cd325cSAndrew Lindesay 
134410cd325cSAndrew Lindesay 
134510cd325cSAndrew Lindesay void
134610cd325cSAndrew Lindesay MainWindow::_SpinUntilProcessCoordinatorComplete()
134710cd325cSAndrew Lindesay {
134810cd325cSAndrew Lindesay 	while (true) {
134910cd325cSAndrew Lindesay 		if (acquire_sem(fCoordinatorRunningSem) != B_OK)
135010cd325cSAndrew Lindesay 			debugger("unable to acquire the process coordinator sem");
135110cd325cSAndrew Lindesay 		if (release_sem(fCoordinatorRunningSem) != B_OK)
135210cd325cSAndrew Lindesay 			debugger("unable to release the process coordinator sem");
135310cd325cSAndrew Lindesay 		{
135410cd325cSAndrew Lindesay 			AutoLocker<BLocker> lock(&fCoordinatorLock);
1355*779ab335SX512 			if (!fCoordinator.IsSet())
135610cd325cSAndrew Lindesay 				return;
135710cd325cSAndrew Lindesay 		}
135810cd325cSAndrew Lindesay 	}
135910cd325cSAndrew Lindesay }
136010cd325cSAndrew Lindesay 
136110cd325cSAndrew Lindesay 
136210cd325cSAndrew Lindesay void
136310cd325cSAndrew Lindesay MainWindow::_StopProcessCoordinators()
136410cd325cSAndrew Lindesay {
1365fa5c8097SAndrew Lindesay 	HDINFO("will stop all process coordinators");
136610cd325cSAndrew Lindesay 
136710cd325cSAndrew Lindesay 	{
136810cd325cSAndrew Lindesay 		AutoLocker<BLocker> lock(&fCoordinatorLock);
136910cd325cSAndrew Lindesay 
137010cd325cSAndrew Lindesay 		while (!fCoordinatorQueue.empty()) {
1371f96d1f4dSAndrew Lindesay 			BReference<ProcessCoordinator> processCoordinator
1372f96d1f4dSAndrew Lindesay 				= fCoordinatorQueue.front();
1373f96d1f4dSAndrew Lindesay 			HDINFO("will drop queued process coordinator [%s]",
1374fa5c8097SAndrew Lindesay 				processCoordinator->Name().String());
137510cd325cSAndrew Lindesay 			fCoordinatorQueue.pop();
137610cd325cSAndrew Lindesay 		}
137710cd325cSAndrew Lindesay 
1378*779ab335SX512 		if (fCoordinator.IsSet()) {
137910cd325cSAndrew Lindesay 			fCoordinator->Stop();
138010cd325cSAndrew Lindesay 		}
138110cd325cSAndrew Lindesay 	}
138210cd325cSAndrew Lindesay 
1383fa5c8097SAndrew Lindesay 	HDINFO("will wait until the process coordinator has stopped");
138410cd325cSAndrew Lindesay 
138510cd325cSAndrew Lindesay 	_SpinUntilProcessCoordinatorComplete();
138610cd325cSAndrew Lindesay 
1387fa5c8097SAndrew Lindesay 	HDINFO("did stop all process coordinators");
138810cd325cSAndrew Lindesay }
138910cd325cSAndrew Lindesay 
139010cd325cSAndrew Lindesay 
139110cd325cSAndrew Lindesay /*! This method is called when there is some change in the bulk load process
139210cd325cSAndrew Lindesay 	or other process coordinator.
139310cd325cSAndrew Lindesay 	A change may mean that a new process has started / stopped etc... or it
139410cd325cSAndrew Lindesay 	may mean that the entire coordinator has finished.
139510cd325cSAndrew Lindesay */
139610cd325cSAndrew Lindesay 
139710cd325cSAndrew Lindesay void
139810cd325cSAndrew Lindesay MainWindow::CoordinatorChanged(ProcessCoordinatorState& coordinatorState)
139910cd325cSAndrew Lindesay {
140010cd325cSAndrew Lindesay 	AutoLocker<BLocker> lock(&fCoordinatorLock);
140110cd325cSAndrew Lindesay 
1402f95ec23eSAndrew Lindesay 	if (fCoordinator.Get() == coordinatorState.Coordinator()) {
140310cd325cSAndrew Lindesay 		if (!coordinatorState.IsRunning()) {
140410cd325cSAndrew Lindesay 			if (release_sem(fCoordinatorRunningSem) != B_OK)
140510cd325cSAndrew Lindesay 				debugger("unable to release the process coordinator sem");
1406f96d1f4dSAndrew Lindesay 			HDINFO("process coordinator [%s] did complete",
1407fa5c8097SAndrew Lindesay 				fCoordinator->Name().String());
140810cd325cSAndrew Lindesay 			// complete the last one that just finished
140910cd325cSAndrew Lindesay 			BMessage* message = fCoordinator->Message();
141010cd325cSAndrew Lindesay 
141110cd325cSAndrew Lindesay 			if (message != NULL) {
141210cd325cSAndrew Lindesay 				BMessenger messenger(this);
141310cd325cSAndrew Lindesay 				message->AddInt64(KEY_ERROR_STATUS,
141410cd325cSAndrew Lindesay 					(int64) fCoordinator->ErrorStatus());
141510cd325cSAndrew Lindesay 				messenger.SendMessage(message);
141610cd325cSAndrew Lindesay 			}
141710cd325cSAndrew Lindesay 
1418f95ec23eSAndrew Lindesay 			fCoordinator = BReference<ProcessCoordinator>(NULL);
1419f95ec23eSAndrew Lindesay 				// will delete the old process coordinator if it is not used
1420f95ec23eSAndrew Lindesay 				// elsewhere.
142110cd325cSAndrew Lindesay 
142210cd325cSAndrew Lindesay 			// now schedule the next one.
142310cd325cSAndrew Lindesay 			if (!fCoordinatorQueue.empty()) {
142410cd325cSAndrew Lindesay 				if (acquire_sem(fCoordinatorRunningSem) != B_OK)
142510cd325cSAndrew Lindesay 					debugger("unable to acquire the process coordinator sem");
142610cd325cSAndrew Lindesay 				fCoordinator = fCoordinatorQueue.front();
1427f96d1f4dSAndrew Lindesay 				HDINFO("starting next process coordinator [%s]",
142810cd325cSAndrew Lindesay 					fCoordinator->Name().String());
142910cd325cSAndrew Lindesay 				fCoordinatorQueue.pop();
143010cd325cSAndrew Lindesay 				fCoordinator->Start();
143110cd325cSAndrew Lindesay 			}
143210cd325cSAndrew Lindesay 			else {
143310cd325cSAndrew Lindesay 				_NotifyWorkStatusClear();
143410cd325cSAndrew Lindesay 			}
143510cd325cSAndrew Lindesay 		}
143610cd325cSAndrew Lindesay 		else {
143710cd325cSAndrew Lindesay 			_NotifyWorkStatusChange(coordinatorState.Message(),
143810cd325cSAndrew Lindesay 				coordinatorState.Progress());
143910cd325cSAndrew Lindesay 				// show the progress to the user.
144010cd325cSAndrew Lindesay 		}
1441fa5c8097SAndrew Lindesay 	} else
1442fa5c8097SAndrew Lindesay 		HDINFO("! unknown process coordinator changed");
144310cd325cSAndrew Lindesay }
1444ccf707d0SAndrew Lindesay 
1445ccf707d0SAndrew Lindesay 
1446ccf707d0SAndrew Lindesay static package_list_view_mode
1447ccf707d0SAndrew Lindesay main_window_tab_to_package_list_view_mode(int32 tab)
1448ccf707d0SAndrew Lindesay {
1449ccf707d0SAndrew Lindesay 	if (tab == TAB_PROMINENT_PACKAGES)
1450ccf707d0SAndrew Lindesay 		return PROMINENT;
1451ccf707d0SAndrew Lindesay 	return ALL;
1452ccf707d0SAndrew Lindesay }
1453ccf707d0SAndrew Lindesay 
1454ccf707d0SAndrew Lindesay 
1455ccf707d0SAndrew Lindesay void
1456ccf707d0SAndrew Lindesay MainWindow::_HandleChangePackageListViewMode()
1457ccf707d0SAndrew Lindesay {
1458ccf707d0SAndrew Lindesay 	package_list_view_mode tabMode = main_window_tab_to_package_list_view_mode(
1459ccf707d0SAndrew Lindesay 		fListTabs->Selection());
1460ccf707d0SAndrew Lindesay 	package_list_view_mode modelMode = fModel.PackageListViewMode();
1461ccf707d0SAndrew Lindesay 
1462ccf707d0SAndrew Lindesay 	if (tabMode != modelMode) {
1463ccf707d0SAndrew Lindesay 		BAutolock locker(fModel.Lock());
1464ccf707d0SAndrew Lindesay 		fModel.SetPackageListViewMode(tabMode);
1465ccf707d0SAndrew Lindesay 	}
1466ccf707d0SAndrew Lindesay }
146705880d13SAndrew Lindesay 
146805880d13SAndrew Lindesay 
146905880d13SAndrew Lindesay std::vector<DepotInfoRef>
147005880d13SAndrew Lindesay MainWindow::_CreateSnapshotOfDepots()
147105880d13SAndrew Lindesay {
147205880d13SAndrew Lindesay 	std::vector<DepotInfoRef> result;
147305880d13SAndrew Lindesay 	BAutolock locker(fModel.Lock());
147405880d13SAndrew Lindesay 	int32 countDepots = fModel.CountDepots();
147505880d13SAndrew Lindesay 	for(int32 i = 0; i < countDepots; i++)
147605880d13SAndrew Lindesay 		result.push_back(fModel.DepotAtIndex(i));
147705880d13SAndrew Lindesay 	return result;
147805880d13SAndrew Lindesay }
1479