xref: /haiku/src/apps/haikudepot/ui/MainWindow.cpp (revision 0b69420bc8fbb47f594b5eb9aa4e5e87476f0ee9)
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.
6d75b4d61SAndrew Lindesay  * Copyright 2016-2021, 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 				}
4326f07feadSAndrew Lindesay 				if (!package.IsSet() || name != package->Name())
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 				}
495*0b69420bSAndrew Lindesay 
496*0b69420bSAndrew Lindesay 				fFeaturedPackagesView->BeginAddRemove();
497c4199192SAndrew Lindesay 				_AddRemovePackageFromLists(ref);
498*0b69420bSAndrew Lindesay 				fFeaturedPackagesView->EndAddRemove();
499*0b69420bSAndrew Lindesay 
50087016f8fSAndrew Lindesay 				if ((changes & PKG_CHANGED_STATE) != 0
501779ab335SX512 						&& !fCoordinator.IsSet()) {
5024e6fbe03SJulian Harnath 					fWorkStatusView->PackageStatusChanged(ref);
50357e51fffSStephan Aßmus 				}
50410cd325cSAndrew Lindesay 			}
50504c9d578SStephan Aßmus 			break;
50604c9d578SStephan Aßmus 		}
50704c9d578SStephan Aßmus 
50804c9d578SStephan Aßmus 		case MSG_RATE_PACKAGE:
5091bbda92dSStephan Aßmus 			_RatePackage();
51004c9d578SStephan Aßmus 			break;
51104c9d578SStephan Aßmus 
512d5ef985eSStephan Aßmus 		case MSG_SHOW_SCREENSHOT:
513d5ef985eSStephan Aßmus 			_ShowScreenshot();
514d5ef985eSStephan Aßmus 			break;
515d5ef985eSStephan Aßmus 
516125d42d9SJulian Harnath 		case MSG_PACKAGE_WORKER_BUSY:
517125d42d9SJulian Harnath 		{
518125d42d9SJulian Harnath 			BString reason;
519125d42d9SJulian Harnath 			status_t status = message->FindString("reason", &reason);
520125d42d9SJulian Harnath 			if (status != B_OK)
521125d42d9SJulian Harnath 				break;
522125d42d9SJulian Harnath 			fWorkStatusView->SetBusy(reason);
523125d42d9SJulian Harnath 			break;
524125d42d9SJulian Harnath 		}
525125d42d9SJulian Harnath 
526125d42d9SJulian Harnath 		case MSG_PACKAGE_WORKER_IDLE:
527125d42d9SJulian Harnath 			fWorkStatusView->SetIdle();
528125d42d9SJulian Harnath 			break;
529125d42d9SJulian Harnath 
53010cd325cSAndrew Lindesay 		case MSG_USER_USAGE_CONDITIONS_NOT_LATEST:
53110cd325cSAndrew Lindesay 		{
53210cd325cSAndrew Lindesay 			BMessage userDetailMsg;
53310cd325cSAndrew Lindesay 			if (message->FindMessage("userDetail", &userDetailMsg) != B_OK) {
53410cd325cSAndrew Lindesay 				debugger("expected the [userDetail] data to be carried in the "
53510cd325cSAndrew Lindesay 					"message.");
53610cd325cSAndrew Lindesay 			}
53710cd325cSAndrew Lindesay 			UserDetail userDetail(&userDetailMsg);
53810cd325cSAndrew Lindesay 			_HandleUserUsageConditionsNotLatest(userDetail);
53910cd325cSAndrew Lindesay 			break;
54010cd325cSAndrew Lindesay 		}
54110cd325cSAndrew Lindesay 
54204c9d578SStephan Aßmus 		default:
54304c9d578SStephan Aßmus 			BWindow::MessageReceived(message);
54404c9d578SStephan Aßmus 			break;
54504c9d578SStephan Aßmus 	}
54604c9d578SStephan Aßmus }
54704c9d578SStephan Aßmus 
54804c9d578SStephan Aßmus 
549ccf707d0SAndrew Lindesay static const char*
550ccf707d0SAndrew Lindesay main_window_package_list_view_mode_str(package_list_view_mode mode)
551ccf707d0SAndrew Lindesay {
552ccf707d0SAndrew Lindesay 	if (mode == PROMINENT)
553ccf707d0SAndrew Lindesay 		return "PROMINENT";
554ccf707d0SAndrew Lindesay 	return "ALL";
555ccf707d0SAndrew Lindesay }
556ccf707d0SAndrew Lindesay 
557ccf707d0SAndrew Lindesay 
558ccf707d0SAndrew Lindesay static package_list_view_mode
559ccf707d0SAndrew Lindesay main_window_str_to_package_list_view_mode(const BString& str)
560ccf707d0SAndrew Lindesay {
561ccf707d0SAndrew Lindesay 	if (str == "PROMINENT")
562ccf707d0SAndrew Lindesay 		return PROMINENT;
563ccf707d0SAndrew Lindesay 	return ALL;
564ccf707d0SAndrew Lindesay }
565ccf707d0SAndrew Lindesay 
566ccf707d0SAndrew Lindesay 
56704c9d578SStephan Aßmus void
56804c9d578SStephan Aßmus MainWindow::StoreSettings(BMessage& settings) const
56904c9d578SStephan Aßmus {
570f7c2983eSAxel Dörfler 	settings.AddRect(_WindowFrameName(), Frame());
571f7c2983eSAxel Dörfler 	if (!fSinglePackageMode) {
57204c9d578SStephan Aßmus 		settings.AddRect("window frame", Frame());
57304c9d578SStephan Aßmus 
57404c9d578SStephan Aßmus 		BMessage columnSettings;
5759883929bSAndrew Lindesay 		if (fPackageListView != NULL)
57604c9d578SStephan Aßmus 			fPackageListView->SaveState(&columnSettings);
57704c9d578SStephan Aßmus 
57804c9d578SStephan Aßmus 		settings.AddMessage("column settings", &columnSettings);
57904c9d578SStephan Aßmus 
580ccf707d0SAndrew Lindesay 		settings.AddString(KEY_PACKAGE_LIST_VIEW_MODE,
581ccf707d0SAndrew Lindesay 			main_window_package_list_view_mode_str(
582ccf707d0SAndrew Lindesay 				fModel.PackageListViewMode()));
5832997e05bSStephan Aßmus 		settings.AddBool("show available packages",
5842997e05bSStephan Aßmus 			fModel.ShowAvailablePackages());
5852997e05bSStephan Aßmus 		settings.AddBool("show installed packages",
5862997e05bSStephan Aßmus 			fModel.ShowInstalledPackages());
58704c9d578SStephan Aßmus 		settings.AddBool("show develop packages", fModel.ShowDevelopPackages());
58804c9d578SStephan Aßmus 		settings.AddBool("show source packages", fModel.ShowSourcePackages());
5896d519fd1SStephan Aßmus 	}
5908f03a0f9SStephan Aßmus 
591d2d4866dSAndrew Lindesay 	settings.AddString("username", fModel.Nickname());
59204c9d578SStephan Aßmus }
59304c9d578SStephan Aßmus 
59404c9d578SStephan Aßmus 
59504c9d578SStephan Aßmus void
59604c9d578SStephan Aßmus MainWindow::PackageChanged(const PackageInfoEvent& event)
59704c9d578SStephan Aßmus {
598a9edb9bfSAndrew Lindesay 	uint32 watchedChanges = PKG_CHANGED_STATE | PKG_CHANGED_PROMINENCE;
599a9edb9bfSAndrew Lindesay 	if ((event.Changes() & watchedChanges) != 0) {
60004c9d578SStephan Aßmus 		PackageInfoRef ref(event.Package());
601da651104SStephan Aßmus 		BMessage message(MSG_PACKAGE_CHANGED);
60204c9d578SStephan Aßmus 		message.AddPointer("package", ref.Get());
603da651104SStephan Aßmus 		message.AddUInt32("changes", event.Changes());
60404c9d578SStephan Aßmus 		ref.Detach();
60504c9d578SStephan Aßmus 			// reference needs to be released by MessageReceived();
60604c9d578SStephan Aßmus 		PostMessage(&message);
60704c9d578SStephan Aßmus 	}
60804c9d578SStephan Aßmus }
60904c9d578SStephan Aßmus 
61004c9d578SStephan Aßmus 
61104c9d578SStephan Aßmus status_t
6126f07feadSAndrew Lindesay MainWindow::SchedulePackageAction(PackageActionRef action)
61304c9d578SStephan Aßmus {
61404c9d578SStephan Aßmus 	AutoLocker<BLocker> lock(&fPendingActionsLock);
6156f07feadSAndrew Lindesay 	fPendingActions.push(action);
6166f07feadSAndrew Lindesay 	return release_sem_etc(fPendingActionsSem, 1, 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;
831*0b69420bSAndrew Lindesay 
832*0b69420bSAndrew Lindesay 	fFeaturedPackagesView->BeginAddRemove();
833*0b69420bSAndrew Lindesay 
83405880d13SAndrew Lindesay 	for (it = depots.begin(); it != depots.end(); it++) {
83505880d13SAndrew Lindesay 		DepotInfoRef depotInfoRef = *it;
836d75b4d61SAndrew Lindesay 		for (int i = 0; i < depotInfoRef->CountPackages(); i++) {
837d75b4d61SAndrew Lindesay 			PackageInfoRef package = depotInfoRef->PackageAtIndex(i);
838d75b4d61SAndrew Lindesay 			_AddRemovePackageFromLists(package);
839d75b4d61SAndrew Lindesay 		}
840c4199192SAndrew Lindesay 	}
841c4199192SAndrew Lindesay 
842*0b69420bSAndrew Lindesay 	fFeaturedPackagesView->EndAddRemove();
843*0b69420bSAndrew Lindesay 
844c4199192SAndrew Lindesay 	_AdoptModelControls();
845c4199192SAndrew Lindesay }
846c4199192SAndrew Lindesay 
847c4199192SAndrew Lindesay 
848c4199192SAndrew Lindesay void
849c4199192SAndrew Lindesay MainWindow::_AddRemovePackageFromLists(const PackageInfoRef& package)
850c4199192SAndrew Lindesay {
851c4199192SAndrew Lindesay 	bool matches;
852c4199192SAndrew Lindesay 
853c4199192SAndrew Lindesay 	{
854c4199192SAndrew Lindesay 		AutoLocker<BLocker> modelLocker(fModel.Lock());
855c4199192SAndrew Lindesay 		matches = fModel.MatchesFilter(package);
856c4199192SAndrew Lindesay 	}
857c4199192SAndrew Lindesay 
858c4199192SAndrew Lindesay 	if (matches) {
859c4199192SAndrew Lindesay 		if (package->IsProminent())
860c4199192SAndrew Lindesay 			fFeaturedPackagesView->AddPackage(package);
861c4199192SAndrew Lindesay 		fPackageListView->AddPackage(package);
862c4199192SAndrew Lindesay 	} else {
863c4199192SAndrew Lindesay 		fFeaturedPackagesView->RemovePackage(package);
864c4199192SAndrew Lindesay 		fPackageListView->RemovePackage(package);
865c4199192SAndrew Lindesay 	}
866c4199192SAndrew Lindesay }
867c4199192SAndrew Lindesay 
868c4199192SAndrew Lindesay 
869c4199192SAndrew Lindesay void
87004c9d578SStephan Aßmus MainWindow::_AdoptPackage(const PackageInfoRef& package)
87104c9d578SStephan Aßmus {
87275ba9dbfSStephan Aßmus 	{
87375ba9dbfSStephan Aßmus 		BAutolock locker(fModel.Lock());
87404c9d578SStephan Aßmus 		fPackageInfoView->SetPackage(package);
8751986ab9fSStephan Aßmus 
876664372abSStephan Aßmus 		if (fFeaturedPackagesView != NULL)
877664372abSStephan Aßmus 			fFeaturedPackagesView->SelectPackage(package);
8781986ab9fSStephan Aßmus 		if (fPackageListView != NULL)
8791986ab9fSStephan Aßmus 			fPackageListView->SelectPackage(package);
88075ba9dbfSStephan Aßmus 	}
88104c9d578SStephan Aßmus 
882a9edb9bfSAndrew Lindesay 	_PopulatePackageAsync(false);
88304c9d578SStephan Aßmus }
88404c9d578SStephan Aßmus 
88504c9d578SStephan Aßmus 
88604c9d578SStephan Aßmus void
88704c9d578SStephan Aßmus MainWindow::_ClearPackage()
88804c9d578SStephan Aßmus {
88904c9d578SStephan Aßmus 	fPackageInfoView->Clear();
89004c9d578SStephan Aßmus }
89104c9d578SStephan Aßmus 
89204c9d578SStephan Aßmus 
89304c9d578SStephan Aßmus void
8943369e03dSAndrew Lindesay MainWindow::_StartBulkLoad(bool force)
89504c9d578SStephan Aßmus {
896c4199192SAndrew Lindesay 	if (fFeaturedPackagesView != NULL)
897c4199192SAndrew Lindesay 		fFeaturedPackagesView->Clear();
898c4199192SAndrew Lindesay 	if (fPackageListView != NULL)
899c4199192SAndrew Lindesay 		fPackageListView->Clear();
900c4199192SAndrew Lindesay 	fPackageInfoView->Clear();
901c4199192SAndrew Lindesay 
90210cd325cSAndrew Lindesay 	fRefreshRepositoriesItem->SetEnabled(false);
90310cd325cSAndrew Lindesay 	ProcessCoordinator* bulkLoadCoordinator =
90410cd325cSAndrew Lindesay 		ProcessCoordinatorFactory::CreateBulkLoadCoordinator(
9053369e03dSAndrew Lindesay 			this,
9063369e03dSAndrew Lindesay 				// PackageInfoListener
9073369e03dSAndrew Lindesay 			this,
9083369e03dSAndrew Lindesay 				// ProcessCoordinatorListener
9093369e03dSAndrew Lindesay 			&fModel, force);
91010cd325cSAndrew Lindesay 	_AddProcessCoordinator(bulkLoadCoordinator);
91104c9d578SStephan Aßmus }
91204c9d578SStephan Aßmus 
91304c9d578SStephan Aßmus 
91404c9d578SStephan Aßmus void
91510cd325cSAndrew Lindesay MainWindow::_BulkLoadCompleteReceived(status_t errorStatus)
91604c9d578SStephan Aßmus {
91710cd325cSAndrew Lindesay 	if (errorStatus != B_OK) {
9183369e03dSAndrew Lindesay 		AppUtils::NotifySimpleError(
9191448ced0SHumdinger 			B_TRANSLATE("Package update error"),
9203369e03dSAndrew Lindesay 			B_TRANSLATE("While updating package data, a problem has arisen "
9213369e03dSAndrew Lindesay 				"that may cause data to be outdated or missing from the "
9223369e03dSAndrew Lindesay 				"application's display. Additional details regarding this "
9233369e03dSAndrew Lindesay 				"problem may be able to be obtained from the application "
924b21c9447SAndrew Lindesay 				"logs."
925b21c9447SAndrew Lindesay 				ALERT_MSG_LOGS_USER_GUIDE));
92604c9d578SStephan Aßmus 	}
92710cd325cSAndrew Lindesay 
9283369e03dSAndrew Lindesay 	fRefreshRepositoriesItem->SetEnabled(true);
92910cd325cSAndrew Lindesay 	_AdoptModel();
93010cd325cSAndrew Lindesay 	_UpdateAvailableRepositories();
931ccf707d0SAndrew Lindesay 
932ccf707d0SAndrew Lindesay 	// if after loading everything in, it transpires that there are no
933ccf707d0SAndrew Lindesay 	// featured packages then the featured packages should be disabled
934ccf707d0SAndrew Lindesay 	// and the user should be switched to the "all packages" view so
935ccf707d0SAndrew Lindesay 	// that they are not presented with a blank window!
936ccf707d0SAndrew Lindesay 
937ccf707d0SAndrew Lindesay 	bool hasProminentPackages = fModel.HasAnyProminentPackages();
938ccf707d0SAndrew Lindesay 	fListTabs->TabAt(TAB_PROMINENT_PACKAGES)->SetEnabled(hasProminentPackages);
939ccf707d0SAndrew Lindesay 	if (!hasProminentPackages
940ccf707d0SAndrew Lindesay 			&& fListTabs->Selection() == TAB_PROMINENT_PACKAGES) {
941ccf707d0SAndrew Lindesay 		fModel.SetPackageListViewMode(ALL);
942ccf707d0SAndrew Lindesay 		fListTabs->Select(TAB_ALL_PACKAGES);
943ccf707d0SAndrew Lindesay 	}
94404c9d578SStephan Aßmus }
94504c9d578SStephan Aßmus 
94604c9d578SStephan Aßmus 
9473369e03dSAndrew Lindesay void
94810cd325cSAndrew Lindesay MainWindow::_NotifyWorkStatusClear()
94904c9d578SStephan Aßmus {
95010cd325cSAndrew Lindesay 	BMessage message(MSG_WORK_STATUS_CLEAR);
95110cd325cSAndrew Lindesay 	this->PostMessage(&message, this);
95210cd325cSAndrew Lindesay }
95310cd325cSAndrew Lindesay 
95410cd325cSAndrew Lindesay 
95510cd325cSAndrew Lindesay void
95610cd325cSAndrew Lindesay MainWindow::_HandleWorkStatusClear()
95710cd325cSAndrew Lindesay {
95810cd325cSAndrew Lindesay 	fWorkStatusView->SetText("");
9593369e03dSAndrew Lindesay 	fWorkStatusView->SetIdle();
9603369e03dSAndrew Lindesay }
96104c9d578SStephan Aßmus 
96204c9d578SStephan Aßmus 
9633369e03dSAndrew Lindesay /*! Sends off a message to the Window so that it can change the status view
9643369e03dSAndrew Lindesay     on the front-end in the UI thread.
9653369e03dSAndrew Lindesay */
96604c9d578SStephan Aßmus 
9673369e03dSAndrew Lindesay void
9683369e03dSAndrew Lindesay MainWindow::_NotifyWorkStatusChange(const BString& text, float progress)
9693369e03dSAndrew Lindesay {
9703369e03dSAndrew Lindesay 	BMessage message(MSG_WORK_STATUS_CHANGE);
97104c9d578SStephan Aßmus 
9723369e03dSAndrew Lindesay 	if (!text.IsEmpty())
9733369e03dSAndrew Lindesay 		message.AddString(KEY_WORK_STATUS_TEXT, text);
9743369e03dSAndrew Lindesay 	message.AddFloat(KEY_WORK_STATUS_PROGRESS, progress);
97504c9d578SStephan Aßmus 
9763369e03dSAndrew Lindesay 	this->PostMessage(&message, this);
9773369e03dSAndrew Lindesay }
97804c9d578SStephan Aßmus 
9793369e03dSAndrew Lindesay 
9803369e03dSAndrew Lindesay void
9813369e03dSAndrew Lindesay MainWindow::_HandleWorkStatusChangeMessageReceived(const BMessage* message)
9823369e03dSAndrew Lindesay {
9839883929bSAndrew Lindesay 	if (fWorkStatusView == NULL)
9849883929bSAndrew Lindesay 		return;
9859883929bSAndrew Lindesay 
9863369e03dSAndrew Lindesay 	BString text;
9873369e03dSAndrew Lindesay 	float progress;
9883369e03dSAndrew Lindesay 
9893369e03dSAndrew Lindesay 	if (message->FindString(KEY_WORK_STATUS_TEXT, &text) == B_OK)
9903369e03dSAndrew Lindesay 		fWorkStatusView->SetText(text);
9913369e03dSAndrew Lindesay 
9923369e03dSAndrew Lindesay 	if (message->FindFloat(KEY_WORK_STATUS_PROGRESS, &progress) == B_OK)
9933369e03dSAndrew Lindesay 		fWorkStatusView->SetProgress(progress);
99404c9d578SStephan Aßmus }
99504c9d578SStephan Aßmus 
99604c9d578SStephan Aßmus 
9976f07feadSAndrew Lindesay /*static*/ status_t
99804c9d578SStephan Aßmus MainWindow::_PackageActionWorker(void* arg)
99904c9d578SStephan Aßmus {
100004c9d578SStephan Aßmus 	MainWindow* window = reinterpret_cast<MainWindow*>(arg);
100104c9d578SStephan Aßmus 
100204c9d578SStephan Aßmus 	while (acquire_sem(window->fPendingActionsSem) == B_OK) {
100304c9d578SStephan Aßmus 		PackageActionRef ref;
100404c9d578SStephan Aßmus 		{
100504c9d578SStephan Aßmus 			AutoLocker<BLocker> lock(&window->fPendingActionsLock);
10066f07feadSAndrew Lindesay 			ref = window->fPendingActions.front();
10076f07feadSAndrew Lindesay 			window->fPendingActions.pop();
1008779ab335SX512 			if (!ref.IsSet())
100904c9d578SStephan Aßmus 				break;
101004c9d578SStephan Aßmus 		}
101104c9d578SStephan Aßmus 
1012125d42d9SJulian Harnath 		BMessenger messenger(window);
1013125d42d9SJulian Harnath 		BMessage busyMessage(MSG_PACKAGE_WORKER_BUSY);
1014125d42d9SJulian Harnath 		BString text(ref->Label());
1015bc622f6bSHumdinger 		text << B_UTF8_ELLIPSIS;
1016125d42d9SJulian Harnath 		busyMessage.AddString("reason", text);
1017125d42d9SJulian Harnath 
1018125d42d9SJulian Harnath 		messenger.SendMessage(&busyMessage);
101904c9d578SStephan Aßmus 		ref->Perform();
1020125d42d9SJulian Harnath 		messenger.SendMessage(MSG_PACKAGE_WORKER_IDLE);
102104c9d578SStephan Aßmus 	}
102204c9d578SStephan Aßmus 
102304c9d578SStephan Aßmus 	return 0;
102404c9d578SStephan Aßmus }
102504c9d578SStephan Aßmus 
102604c9d578SStephan Aßmus 
1027a9edb9bfSAndrew Lindesay /*! This method will cause the package to have its data refreshed from
1028a9edb9bfSAndrew Lindesay     the server application.  The refresh happens in the background; this method
1029a9edb9bfSAndrew Lindesay     is asynchronous.
1030a9edb9bfSAndrew Lindesay */
1031a9edb9bfSAndrew Lindesay 
1032a9edb9bfSAndrew Lindesay void
1033a9edb9bfSAndrew Lindesay MainWindow::_PopulatePackageAsync(bool forcePopulate)
1034a9edb9bfSAndrew Lindesay {
1035a9edb9bfSAndrew Lindesay 		// Trigger asynchronous package population from the web-app
1036a9edb9bfSAndrew Lindesay 	{
1037a9edb9bfSAndrew Lindesay 		AutoLocker<BLocker> lock(&fPackageToPopulateLock);
1038a9edb9bfSAndrew Lindesay 		fPackageToPopulate = fPackageInfoView->Package();
1039a9edb9bfSAndrew Lindesay 		fForcePopulatePackage = forcePopulate;
1040a9edb9bfSAndrew Lindesay 	}
1041a9edb9bfSAndrew Lindesay 	release_sem_etc(fPackageToPopulateSem, 1, 0);
1042a9edb9bfSAndrew Lindesay 
1043f96d1f4dSAndrew Lindesay 	HDDEBUG("pkg [%s] will be updated from the server.",
1044fa5c8097SAndrew Lindesay 		fPackageToPopulate->Name().String());
1045a9edb9bfSAndrew Lindesay }
1046a9edb9bfSAndrew Lindesay 
1047a9edb9bfSAndrew Lindesay 
1048a9edb9bfSAndrew Lindesay /*! This method will run in the background.  The thread will block until there
1049a9edb9bfSAndrew Lindesay     is a package to be updated.  When the thread unblocks, it will update the
1050a9edb9bfSAndrew Lindesay     package with information from the server.
1051a9edb9bfSAndrew Lindesay */
1052a9edb9bfSAndrew Lindesay 
105304c9d578SStephan Aßmus status_t
105404c9d578SStephan Aßmus MainWindow::_PopulatePackageWorker(void* arg)
105504c9d578SStephan Aßmus {
105604c9d578SStephan Aßmus 	MainWindow* window = reinterpret_cast<MainWindow*>(arg);
105704c9d578SStephan Aßmus 
105804c9d578SStephan Aßmus 	while (acquire_sem(window->fPackageToPopulateSem) == B_OK) {
105904c9d578SStephan Aßmus 		PackageInfoRef package;
1060a9edb9bfSAndrew Lindesay 		bool force;
106104c9d578SStephan Aßmus 		{
106204c9d578SStephan Aßmus 			AutoLocker<BLocker> lock(&window->fPackageToPopulateLock);
106304c9d578SStephan Aßmus 			package = window->fPackageToPopulate;
1064a9edb9bfSAndrew Lindesay 			force = window->fForcePopulatePackage;
106504c9d578SStephan Aßmus 		}
106604c9d578SStephan Aßmus 
1067779ab335SX512 		if (package.IsSet()) {
1068a9edb9bfSAndrew Lindesay 			uint32 populateFlags = Model::POPULATE_USER_RATINGS
1069a9edb9bfSAndrew Lindesay 				| Model::POPULATE_SCREEN_SHOTS
1070a9edb9bfSAndrew Lindesay 				| Model::POPULATE_CHANGELOG;
1071a9edb9bfSAndrew Lindesay 
1072a9edb9bfSAndrew Lindesay 			if (force)
1073a9edb9bfSAndrew Lindesay 				populateFlags |= Model::POPULATE_FORCE;
1074a9edb9bfSAndrew Lindesay 
1075a9edb9bfSAndrew Lindesay 			window->fModel.PopulatePackage(package, populateFlags);
1076a9edb9bfSAndrew Lindesay 
1077fa5c8097SAndrew Lindesay 			HDDEBUG("populating package [%s]", package->Name().String());
107804c9d578SStephan Aßmus 		}
107904c9d578SStephan Aßmus 	}
108004c9d578SStephan Aßmus 
108104c9d578SStephan Aßmus 	return 0;
108204c9d578SStephan Aßmus }
108304c9d578SStephan Aßmus 
108404c9d578SStephan Aßmus 
108504c9d578SStephan Aßmus void
10861bbda92dSStephan Aßmus MainWindow::_OpenLoginWindow(const BMessage& onSuccessMessage)
108704c9d578SStephan Aßmus {
108804c9d578SStephan Aßmus 	UserLoginWindow* window = new UserLoginWindow(this,
108904c9d578SStephan Aßmus 		BRect(0, 0, 500, 400), fModel);
10901bbda92dSStephan Aßmus 
10911bbda92dSStephan Aßmus 	if (onSuccessMessage.what != 0)
10921bbda92dSStephan Aßmus 		window->SetOnSuccessMessage(BMessenger(this), onSuccessMessage);
10931bbda92dSStephan Aßmus 
109404c9d578SStephan Aßmus 	window->Show();
109504c9d578SStephan Aßmus }
109604c9d578SStephan Aßmus 
10978f03a0f9SStephan Aßmus 
10988f03a0f9SStephan Aßmus void
109910cd325cSAndrew Lindesay MainWindow::_StartUserVerify()
110010cd325cSAndrew Lindesay {
110110cd325cSAndrew Lindesay 	if (!fModel.Nickname().IsEmpty()) {
110210cd325cSAndrew Lindesay 		_AddProcessCoordinator(
110310cd325cSAndrew Lindesay 			ProcessCoordinatorFactory::CreateUserDetailVerifierCoordinator(
110410cd325cSAndrew Lindesay 				this,
110510cd325cSAndrew Lindesay 					// UserDetailVerifierListener
110610cd325cSAndrew Lindesay 				this,
110710cd325cSAndrew Lindesay 					// ProcessCoordinatorListener
110810cd325cSAndrew Lindesay 				&fModel) );
110910cd325cSAndrew Lindesay 	}
111010cd325cSAndrew Lindesay }
111110cd325cSAndrew Lindesay 
111210cd325cSAndrew Lindesay 
111310cd325cSAndrew Lindesay void
11148f03a0f9SStephan Aßmus MainWindow::_UpdateAuthorization()
11158f03a0f9SStephan Aßmus {
1116d2d4866dSAndrew Lindesay 	BString nickname(fModel.Nickname());
1117d2d4866dSAndrew Lindesay 	bool hasUser = !nickname.IsEmpty();
1118e0a26dceSStephan Aßmus 
11196d519fd1SStephan Aßmus 	if (fLogOutItem != NULL)
1120e0a26dceSStephan Aßmus 		fLogOutItem->SetEnabled(hasUser);
1121d2d4866dSAndrew Lindesay 	if (fUsersUserUsageConditionsMenuItem != NULL)
1122d2d4866dSAndrew Lindesay 		fUsersUserUsageConditionsMenuItem->SetEnabled(hasUser);
1123e0a26dceSStephan Aßmus 	if (fLogInItem != NULL) {
1124e0a26dceSStephan Aßmus 		if (hasUser)
1125e0a26dceSStephan Aßmus 			fLogInItem->SetLabel(B_TRANSLATE("Switch account" B_UTF8_ELLIPSIS));
1126e0a26dceSStephan Aßmus 		else
1127e0a26dceSStephan Aßmus 			fLogInItem->SetLabel(B_TRANSLATE("Log in" B_UTF8_ELLIPSIS));
1128e0a26dceSStephan Aßmus 	}
1129e0a26dceSStephan Aßmus 
1130e0a26dceSStephan Aßmus 	if (fUserMenu != NULL) {
1131e0a26dceSStephan Aßmus 		BString label;
1132d2d4866dSAndrew Lindesay 		if (hasUser) {
1133e0a26dceSStephan Aßmus 			label = B_TRANSLATE("Logged in as %User%");
1134d2d4866dSAndrew Lindesay 			label.ReplaceAll("%User%", nickname);
1135d2d4866dSAndrew Lindesay 		} else {
1136d2d4866dSAndrew Lindesay 			label = B_TRANSLATE("Not logged in");
1137e0a26dceSStephan Aßmus 		}
1138e0a26dceSStephan Aßmus 		fUserMenu->Superitem()->SetLabel(label);
1139e0a26dceSStephan Aßmus 	}
11408f03a0f9SStephan Aßmus }
11411bbda92dSStephan Aßmus 
11421bbda92dSStephan Aßmus 
11431bbda92dSStephan Aßmus void
1144b965ce70SHumdinger MainWindow::_UpdateAvailableRepositories()
1145b965ce70SHumdinger {
1146b965ce70SHumdinger 	fRepositoryMenu->RemoveItems(0, fRepositoryMenu->CountItems(), true);
1147b965ce70SHumdinger 
1148b965ce70SHumdinger 	fRepositoryMenu->AddItem(new BMenuItem(B_TRANSLATE("All repositories"),
1149b965ce70SHumdinger 		new BMessage(MSG_DEPOT_SELECTED)));
1150b965ce70SHumdinger 
1151b965ce70SHumdinger 	fRepositoryMenu->AddItem(new BSeparatorItem());
1152b965ce70SHumdinger 
1153b965ce70SHumdinger 	bool foundSelectedDepot = false;
115405880d13SAndrew Lindesay 	std::vector<DepotInfoRef> depots = _CreateSnapshotOfDepots();
115505880d13SAndrew Lindesay 	std::vector<DepotInfoRef>::iterator it;
1156d13c3d89SAndrew Lindesay 
115705880d13SAndrew Lindesay 	for (it = depots.begin(); it != depots.end(); it++) {
115805880d13SAndrew Lindesay 		DepotInfoRef depot = *it;
115905880d13SAndrew Lindesay 
116005880d13SAndrew Lindesay 		if (depot->Name().Length() != 0) {
1161b965ce70SHumdinger 			BMessage* message = new BMessage(MSG_DEPOT_SELECTED);
116205880d13SAndrew Lindesay 			message->AddString("name", depot->Name());
116305880d13SAndrew Lindesay 			BMenuItem* item = new(std::nothrow) BMenuItem(depot->Name(), message);
116405880d13SAndrew Lindesay 
116505880d13SAndrew Lindesay 			if (item == NULL)
116605880d13SAndrew Lindesay 				HDFATAL("memory exhaustion");
116705880d13SAndrew Lindesay 
1168b965ce70SHumdinger 			fRepositoryMenu->AddItem(item);
1169b965ce70SHumdinger 
117005880d13SAndrew Lindesay 			if (depot->Name() == fModel.Depot()) {
1171b965ce70SHumdinger 				item->SetMarked(true);
1172b965ce70SHumdinger 				foundSelectedDepot = true;
1173b965ce70SHumdinger 			}
1174b965ce70SHumdinger 		}
1175d13c3d89SAndrew Lindesay 	}
1176b965ce70SHumdinger 
1177b965ce70SHumdinger 	if (!foundSelectedDepot)
1178b965ce70SHumdinger 		fRepositoryMenu->ItemAt(0)->SetMarked(true);
1179b965ce70SHumdinger }
1180b965ce70SHumdinger 
1181b965ce70SHumdinger 
1182a9edb9bfSAndrew Lindesay bool
1183a9edb9bfSAndrew Lindesay MainWindow::_SelectedPackageHasWebAppRepositoryCode()
1184a9edb9bfSAndrew Lindesay {
1185a9edb9bfSAndrew Lindesay 	const PackageInfoRef& package = fPackageInfoView->Package();
11866ab878c0SAndrew Lindesay 	const BString depotName = package->DepotName();
1187a9edb9bfSAndrew Lindesay 
11886ab878c0SAndrew Lindesay 	if (depotName.IsEmpty()) {
1189fa5c8097SAndrew Lindesay 		HDDEBUG("the package [%s] has no depot name", package->Name().String());
11906ab878c0SAndrew Lindesay 	} else {
11916ab878c0SAndrew Lindesay 		const DepotInfo* depot = fModel.DepotForName(depotName);
1192a9edb9bfSAndrew Lindesay 
11936ab878c0SAndrew Lindesay 		if (depot == NULL) {
1194f96d1f4dSAndrew Lindesay 			HDINFO("the depot [%s] was not able to be found",
1195fa5c8097SAndrew Lindesay 				depotName.String());
11966ab878c0SAndrew Lindesay 		} else {
11976ab878c0SAndrew Lindesay 			BString repositoryCode = depot->WebAppRepositoryCode();
1198a9edb9bfSAndrew Lindesay 
11996ab878c0SAndrew Lindesay 			if (repositoryCode.IsEmpty()) {
1200f96d1f4dSAndrew Lindesay 				HDINFO("the depot [%s] has no web app repository code",
1201fa5c8097SAndrew Lindesay 					depotName.String());
1202fa5c8097SAndrew Lindesay 			} else
12036ab878c0SAndrew Lindesay 				return true;
12046ab878c0SAndrew Lindesay 		}
12056ab878c0SAndrew Lindesay 	}
12066ab878c0SAndrew Lindesay 
12076ab878c0SAndrew Lindesay 	return false;
1208a9edb9bfSAndrew Lindesay }
1209a9edb9bfSAndrew Lindesay 
1210a9edb9bfSAndrew Lindesay 
1211b965ce70SHumdinger void
12121bbda92dSStephan Aßmus MainWindow::_RatePackage()
12131bbda92dSStephan Aßmus {
1214a9edb9bfSAndrew Lindesay 	if (!_SelectedPackageHasWebAppRepositoryCode()) {
1215a9edb9bfSAndrew Lindesay 		BAlert* alert = new(std::nothrow) BAlert(
1216cbadcae1SHumdinger 			B_TRANSLATE("Rating not possible"),
1217cbadcae1SHumdinger 			B_TRANSLATE("This package doesn't seem to be on the HaikuDepot "
1218cbadcae1SHumdinger 				"Server, so it's not possible to create a new rating "
1219cbadcae1SHumdinger 				"or edit an existing rating."),
1220a9edb9bfSAndrew Lindesay 			B_TRANSLATE("OK"));
1221a9edb9bfSAndrew Lindesay 		alert->Go();
1222a9edb9bfSAndrew Lindesay     	return;
1223a9edb9bfSAndrew Lindesay 	}
1224a9edb9bfSAndrew Lindesay 
1225d2d4866dSAndrew Lindesay 	if (fModel.Nickname().IsEmpty()) {
12261bbda92dSStephan Aßmus 		BAlert* alert = new(std::nothrow) BAlert(
12271bbda92dSStephan Aßmus 			B_TRANSLATE("Not logged in"),
12281bbda92dSStephan Aßmus 			B_TRANSLATE("You need to be logged into an account before you "
12291bbda92dSStephan Aßmus 				"can rate packages."),
12301bbda92dSStephan Aßmus 			B_TRANSLATE("Cancel"),
12311bbda92dSStephan Aßmus 			B_TRANSLATE("Login or Create account"));
12321bbda92dSStephan Aßmus 
12331bbda92dSStephan Aßmus 		if (alert == NULL)
12341bbda92dSStephan Aßmus 			return;
12351bbda92dSStephan Aßmus 
12361bbda92dSStephan Aßmus 		int32 choice = alert->Go();
12371bbda92dSStephan Aßmus 		if (choice == 1)
12381bbda92dSStephan Aßmus 			_OpenLoginWindow(BMessage(MSG_RATE_PACKAGE));
12391bbda92dSStephan Aßmus 		return;
12401bbda92dSStephan Aßmus 	}
12411bbda92dSStephan Aßmus 
12421bbda92dSStephan Aßmus 	// TODO: Allow only one RatePackageWindow
12431bbda92dSStephan Aßmus 	// TODO: Mechanism for remembering the window frame
12441bbda92dSStephan Aßmus 	RatePackageWindow* window = new RatePackageWindow(this,
12451bbda92dSStephan Aßmus 		BRect(0, 0, 500, 400), fModel);
12461bbda92dSStephan Aßmus 	window->SetPackage(fPackageInfoView->Package());
12471bbda92dSStephan Aßmus 	window->Show();
12481bbda92dSStephan Aßmus }
1249d5ef985eSStephan Aßmus 
1250d5ef985eSStephan Aßmus 
1251d5ef985eSStephan Aßmus void
1252d5ef985eSStephan Aßmus MainWindow::_ShowScreenshot()
1253d5ef985eSStephan Aßmus {
1254d5ef985eSStephan Aßmus 	// TODO: Mechanism for remembering the window frame
1255d5ef985eSStephan Aßmus 	if (fScreenshotWindow == NULL)
1256d5ef985eSStephan Aßmus 		fScreenshotWindow = new ScreenshotWindow(this, BRect(0, 0, 500, 400));
1257d5ef985eSStephan Aßmus 
1258d5ef985eSStephan Aßmus 	if (fScreenshotWindow->LockWithTimeout(1000) != B_OK)
1259d5ef985eSStephan Aßmus 		return;
1260d5ef985eSStephan Aßmus 
1261d5ef985eSStephan Aßmus 	fScreenshotWindow->SetPackage(fPackageInfoView->Package());
1262d5ef985eSStephan Aßmus 
1263d5ef985eSStephan Aßmus 	if (fScreenshotWindow->IsHidden())
1264d5ef985eSStephan Aßmus 		fScreenshotWindow->Show();
1265d5ef985eSStephan Aßmus 	else
1266d5ef985eSStephan Aßmus 		fScreenshotWindow->Activate();
1267d5ef985eSStephan Aßmus 
1268d5ef985eSStephan Aßmus 	fScreenshotWindow->Unlock();
1269d5ef985eSStephan Aßmus }
127001339a54SAndrew Lindesay 
127101339a54SAndrew Lindesay 
127201339a54SAndrew Lindesay void
1273d2d4866dSAndrew Lindesay MainWindow::_ViewUserUsageConditions(
1274d2d4866dSAndrew Lindesay 	UserUsageConditionsSelectionMode mode)
127501339a54SAndrew Lindesay {
127601339a54SAndrew Lindesay 	UserUsageConditionsWindow* window = new UserUsageConditionsWindow(
1277d2d4866dSAndrew Lindesay 		fModel, mode);
127801339a54SAndrew Lindesay 	window->Show();
127901339a54SAndrew Lindesay }
128010cd325cSAndrew Lindesay 
128110cd325cSAndrew Lindesay 
128210cd325cSAndrew Lindesay void
128310cd325cSAndrew Lindesay MainWindow::UserCredentialsFailed()
128410cd325cSAndrew Lindesay {
128510cd325cSAndrew Lindesay 	BString message = B_TRANSLATE("The password previously "
128610cd325cSAndrew Lindesay 		"supplied for the user [%Nickname%] is not currently "
128710cd325cSAndrew Lindesay 		"valid. The user will be logged-out of this application "
128810cd325cSAndrew Lindesay 		"and you should login again with your updated password.");
128910cd325cSAndrew Lindesay 	message.ReplaceAll("%Nickname%", fModel.Nickname());
129010cd325cSAndrew Lindesay 
129110cd325cSAndrew Lindesay 	AppUtils::NotifySimpleError(B_TRANSLATE("Login issue"),
129210cd325cSAndrew Lindesay 		message);
129310cd325cSAndrew Lindesay 
129410cd325cSAndrew Lindesay 	{
129510cd325cSAndrew Lindesay 		AutoLocker<BLocker> locker(fModel.Lock());
129610cd325cSAndrew Lindesay 		fModel.SetNickname("");
129710cd325cSAndrew Lindesay 	}
129810cd325cSAndrew Lindesay }
129910cd325cSAndrew Lindesay 
130010cd325cSAndrew Lindesay 
130110cd325cSAndrew Lindesay /*! \brief This method is invoked from the UserDetailVerifierProcess on a
130210cd325cSAndrew Lindesay 		   background thread.  For this reason it lodges a message into itself
130310cd325cSAndrew Lindesay 		   which can then be handled on the main thread.
130410cd325cSAndrew Lindesay */
130510cd325cSAndrew Lindesay 
130610cd325cSAndrew Lindesay void
130710cd325cSAndrew Lindesay MainWindow::UserUsageConditionsNotLatest(const UserDetail& userDetail)
130810cd325cSAndrew Lindesay {
130910cd325cSAndrew Lindesay 	BMessage message(MSG_USER_USAGE_CONDITIONS_NOT_LATEST);
131010cd325cSAndrew Lindesay 	BMessage detailsMessage;
131110cd325cSAndrew Lindesay 	if (userDetail.Archive(&detailsMessage, true) != B_OK
131210cd325cSAndrew Lindesay 			|| message.AddMessage("userDetail", &detailsMessage) != B_OK) {
1313fa5c8097SAndrew Lindesay 		HDERROR("unable to archive the user detail into a message");
131410cd325cSAndrew Lindesay 	}
131510cd325cSAndrew Lindesay 	else
131610cd325cSAndrew Lindesay 		BMessenger(this).SendMessage(&message);
131710cd325cSAndrew Lindesay }
131810cd325cSAndrew Lindesay 
131910cd325cSAndrew Lindesay 
132010cd325cSAndrew Lindesay void
132110cd325cSAndrew Lindesay MainWindow::_HandleUserUsageConditionsNotLatest(
132210cd325cSAndrew Lindesay 	const UserDetail& userDetail)
132310cd325cSAndrew Lindesay {
132410cd325cSAndrew Lindesay 	ToLatestUserUsageConditionsWindow* window =
132510cd325cSAndrew Lindesay 		new ToLatestUserUsageConditionsWindow(this, fModel, userDetail);
132610cd325cSAndrew Lindesay 	window->Show();
132710cd325cSAndrew Lindesay }
132810cd325cSAndrew Lindesay 
132910cd325cSAndrew Lindesay 
133010cd325cSAndrew Lindesay void
133110cd325cSAndrew Lindesay MainWindow::_AddProcessCoordinator(ProcessCoordinator* item)
133210cd325cSAndrew Lindesay {
133310cd325cSAndrew Lindesay 	AutoLocker<BLocker> lock(&fCoordinatorLock);
133410cd325cSAndrew Lindesay 
1335779ab335SX512 	if (!fCoordinator.IsSet()) {
133610cd325cSAndrew Lindesay 		if (acquire_sem(fCoordinatorRunningSem) != B_OK)
133710cd325cSAndrew Lindesay 			debugger("unable to acquire the process coordinator sem");
1338f96d1f4dSAndrew Lindesay 		HDINFO("adding and starting a process coordinator [%s]",
1339fa5c8097SAndrew Lindesay 			item->Name().String());
1340f95ec23eSAndrew Lindesay 		fCoordinator = BReference<ProcessCoordinator>(item);
134110cd325cSAndrew Lindesay 		fCoordinator->Start();
134210cd325cSAndrew Lindesay 	}
134310cd325cSAndrew Lindesay 	else {
1344f96d1f4dSAndrew Lindesay 		HDINFO("adding process coordinator [%s] to the queue",
134510cd325cSAndrew Lindesay 			item->Name().String());
134610cd325cSAndrew Lindesay 		fCoordinatorQueue.push(item);
134710cd325cSAndrew Lindesay 	}
134810cd325cSAndrew Lindesay }
134910cd325cSAndrew Lindesay 
135010cd325cSAndrew Lindesay 
135110cd325cSAndrew Lindesay void
135210cd325cSAndrew Lindesay MainWindow::_SpinUntilProcessCoordinatorComplete()
135310cd325cSAndrew Lindesay {
135410cd325cSAndrew Lindesay 	while (true) {
135510cd325cSAndrew Lindesay 		if (acquire_sem(fCoordinatorRunningSem) != B_OK)
135610cd325cSAndrew Lindesay 			debugger("unable to acquire the process coordinator sem");
135710cd325cSAndrew Lindesay 		if (release_sem(fCoordinatorRunningSem) != B_OK)
135810cd325cSAndrew Lindesay 			debugger("unable to release the process coordinator sem");
135910cd325cSAndrew Lindesay 		{
136010cd325cSAndrew Lindesay 			AutoLocker<BLocker> lock(&fCoordinatorLock);
1361779ab335SX512 			if (!fCoordinator.IsSet())
136210cd325cSAndrew Lindesay 				return;
136310cd325cSAndrew Lindesay 		}
136410cd325cSAndrew Lindesay 	}
136510cd325cSAndrew Lindesay }
136610cd325cSAndrew Lindesay 
136710cd325cSAndrew Lindesay 
136810cd325cSAndrew Lindesay void
136910cd325cSAndrew Lindesay MainWindow::_StopProcessCoordinators()
137010cd325cSAndrew Lindesay {
1371fa5c8097SAndrew Lindesay 	HDINFO("will stop all process coordinators");
137210cd325cSAndrew Lindesay 
137310cd325cSAndrew Lindesay 	{
137410cd325cSAndrew Lindesay 		AutoLocker<BLocker> lock(&fCoordinatorLock);
137510cd325cSAndrew Lindesay 
137610cd325cSAndrew Lindesay 		while (!fCoordinatorQueue.empty()) {
1377f96d1f4dSAndrew Lindesay 			BReference<ProcessCoordinator> processCoordinator
1378f96d1f4dSAndrew Lindesay 				= fCoordinatorQueue.front();
1379f96d1f4dSAndrew Lindesay 			HDINFO("will drop queued process coordinator [%s]",
1380fa5c8097SAndrew Lindesay 				processCoordinator->Name().String());
138110cd325cSAndrew Lindesay 			fCoordinatorQueue.pop();
138210cd325cSAndrew Lindesay 		}
138310cd325cSAndrew Lindesay 
1384779ab335SX512 		if (fCoordinator.IsSet()) {
138510cd325cSAndrew Lindesay 			fCoordinator->Stop();
138610cd325cSAndrew Lindesay 		}
138710cd325cSAndrew Lindesay 	}
138810cd325cSAndrew Lindesay 
1389fa5c8097SAndrew Lindesay 	HDINFO("will wait until the process coordinator has stopped");
139010cd325cSAndrew Lindesay 
139110cd325cSAndrew Lindesay 	_SpinUntilProcessCoordinatorComplete();
139210cd325cSAndrew Lindesay 
1393fa5c8097SAndrew Lindesay 	HDINFO("did stop all process coordinators");
139410cd325cSAndrew Lindesay }
139510cd325cSAndrew Lindesay 
139610cd325cSAndrew Lindesay 
139710cd325cSAndrew Lindesay /*! This method is called when there is some change in the bulk load process
139810cd325cSAndrew Lindesay 	or other process coordinator.
139910cd325cSAndrew Lindesay 	A change may mean that a new process has started / stopped etc... or it
140010cd325cSAndrew Lindesay 	may mean that the entire coordinator has finished.
140110cd325cSAndrew Lindesay */
140210cd325cSAndrew Lindesay 
140310cd325cSAndrew Lindesay void
140410cd325cSAndrew Lindesay MainWindow::CoordinatorChanged(ProcessCoordinatorState& coordinatorState)
140510cd325cSAndrew Lindesay {
140610cd325cSAndrew Lindesay 	AutoLocker<BLocker> lock(&fCoordinatorLock);
140710cd325cSAndrew Lindesay 
1408f95ec23eSAndrew Lindesay 	if (fCoordinator.Get() == coordinatorState.Coordinator()) {
140910cd325cSAndrew Lindesay 		if (!coordinatorState.IsRunning()) {
141010cd325cSAndrew Lindesay 			if (release_sem(fCoordinatorRunningSem) != B_OK)
141110cd325cSAndrew Lindesay 				debugger("unable to release the process coordinator sem");
1412f96d1f4dSAndrew Lindesay 			HDINFO("process coordinator [%s] did complete",
1413fa5c8097SAndrew Lindesay 				fCoordinator->Name().String());
141410cd325cSAndrew Lindesay 			// complete the last one that just finished
141510cd325cSAndrew Lindesay 			BMessage* message = fCoordinator->Message();
141610cd325cSAndrew Lindesay 
141710cd325cSAndrew Lindesay 			if (message != NULL) {
141810cd325cSAndrew Lindesay 				BMessenger messenger(this);
141910cd325cSAndrew Lindesay 				message->AddInt64(KEY_ERROR_STATUS,
142010cd325cSAndrew Lindesay 					(int64) fCoordinator->ErrorStatus());
142110cd325cSAndrew Lindesay 				messenger.SendMessage(message);
142210cd325cSAndrew Lindesay 			}
142310cd325cSAndrew Lindesay 
1424f95ec23eSAndrew Lindesay 			fCoordinator = BReference<ProcessCoordinator>(NULL);
1425f95ec23eSAndrew Lindesay 				// will delete the old process coordinator if it is not used
1426f95ec23eSAndrew Lindesay 				// elsewhere.
142710cd325cSAndrew Lindesay 
142810cd325cSAndrew Lindesay 			// now schedule the next one.
142910cd325cSAndrew Lindesay 			if (!fCoordinatorQueue.empty()) {
143010cd325cSAndrew Lindesay 				if (acquire_sem(fCoordinatorRunningSem) != B_OK)
143110cd325cSAndrew Lindesay 					debugger("unable to acquire the process coordinator sem");
143210cd325cSAndrew Lindesay 				fCoordinator = fCoordinatorQueue.front();
1433f96d1f4dSAndrew Lindesay 				HDINFO("starting next process coordinator [%s]",
143410cd325cSAndrew Lindesay 					fCoordinator->Name().String());
143510cd325cSAndrew Lindesay 				fCoordinatorQueue.pop();
143610cd325cSAndrew Lindesay 				fCoordinator->Start();
143710cd325cSAndrew Lindesay 			}
143810cd325cSAndrew Lindesay 			else {
143910cd325cSAndrew Lindesay 				_NotifyWorkStatusClear();
144010cd325cSAndrew Lindesay 			}
144110cd325cSAndrew Lindesay 		}
144210cd325cSAndrew Lindesay 		else {
144310cd325cSAndrew Lindesay 			_NotifyWorkStatusChange(coordinatorState.Message(),
144410cd325cSAndrew Lindesay 				coordinatorState.Progress());
144510cd325cSAndrew Lindesay 				// show the progress to the user.
144610cd325cSAndrew Lindesay 		}
1447fa5c8097SAndrew Lindesay 	} else
1448fa5c8097SAndrew Lindesay 		HDINFO("! unknown process coordinator changed");
144910cd325cSAndrew Lindesay }
1450ccf707d0SAndrew Lindesay 
1451ccf707d0SAndrew Lindesay 
1452ccf707d0SAndrew Lindesay static package_list_view_mode
1453ccf707d0SAndrew Lindesay main_window_tab_to_package_list_view_mode(int32 tab)
1454ccf707d0SAndrew Lindesay {
1455ccf707d0SAndrew Lindesay 	if (tab == TAB_PROMINENT_PACKAGES)
1456ccf707d0SAndrew Lindesay 		return PROMINENT;
1457ccf707d0SAndrew Lindesay 	return ALL;
1458ccf707d0SAndrew Lindesay }
1459ccf707d0SAndrew Lindesay 
1460ccf707d0SAndrew Lindesay 
1461ccf707d0SAndrew Lindesay void
1462ccf707d0SAndrew Lindesay MainWindow::_HandleChangePackageListViewMode()
1463ccf707d0SAndrew Lindesay {
1464ccf707d0SAndrew Lindesay 	package_list_view_mode tabMode = main_window_tab_to_package_list_view_mode(
1465ccf707d0SAndrew Lindesay 		fListTabs->Selection());
1466ccf707d0SAndrew Lindesay 	package_list_view_mode modelMode = fModel.PackageListViewMode();
1467ccf707d0SAndrew Lindesay 
1468ccf707d0SAndrew Lindesay 	if (tabMode != modelMode) {
1469ccf707d0SAndrew Lindesay 		BAutolock locker(fModel.Lock());
1470ccf707d0SAndrew Lindesay 		fModel.SetPackageListViewMode(tabMode);
1471ccf707d0SAndrew Lindesay 	}
1472ccf707d0SAndrew Lindesay }
147305880d13SAndrew Lindesay 
147405880d13SAndrew Lindesay 
147505880d13SAndrew Lindesay std::vector<DepotInfoRef>
147605880d13SAndrew Lindesay MainWindow::_CreateSnapshotOfDepots()
147705880d13SAndrew Lindesay {
147805880d13SAndrew Lindesay 	std::vector<DepotInfoRef> result;
147905880d13SAndrew Lindesay 	BAutolock locker(fModel.Lock());
148005880d13SAndrew Lindesay 	int32 countDepots = fModel.CountDepots();
148105880d13SAndrew Lindesay 	for(int32 i = 0; i < countDepots; i++)
148205880d13SAndrew Lindesay 		result.push_back(fModel.DepotAtIndex(i));
148305880d13SAndrew Lindesay 	return result;
148405880d13SAndrew Lindesay }
1485