xref: /haiku/src/apps/haikudepot/ui/MainWindow.cpp (revision f32d5c5ca53c502f59f7d260ec5bd0546a577283)
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"
50133ebab6SAndrew Lindesay #include "SettingsWindow.h"
5110cd325cSAndrew Lindesay #include "ToLatestUserUsageConditionsWindow.h"
5204c9d578SStephan Aßmus #include "UserLoginWindow.h"
5301339a54SAndrew Lindesay #include "UserUsageConditionsWindow.h"
54125d42d9SJulian Harnath #include "WorkStatusView.h"
5504c9d578SStephan Aßmus 
5604c9d578SStephan Aßmus 
5704c9d578SStephan Aßmus #undef B_TRANSLATION_CONTEXT
5804c9d578SStephan Aßmus #define B_TRANSLATION_CONTEXT "MainWindow"
5904c9d578SStephan Aßmus 
6004c9d578SStephan Aßmus 
6104c9d578SStephan Aßmus enum {
625bf2b6ebSBrian Hill 	MSG_REFRESH_REPOS						= 'mrrp',
635bf2b6ebSBrian Hill 	MSG_MANAGE_REPOS						= 'mmrp',
64d144f952SAugustin Cavalier 	MSG_SOFTWARE_UPDATER					= 'mswu',
65133ebab6SAndrew Lindesay 	MSG_SETTINGS							= 'stgs',
6604c9d578SStephan Aßmus 	MSG_LOG_IN								= 'lgin',
678f03a0f9SStephan Aßmus 	MSG_AUTHORIZATION_CHANGED				= 'athc',
6889b16bb4SAndrew Lindesay 	MSG_CATEGORIES_LIST_CHANGED				= 'clic',
69da651104SStephan Aßmus 	MSG_PACKAGE_CHANGED						= 'pchd',
703369e03dSAndrew Lindesay 	MSG_WORK_STATUS_CHANGE					= 'wsch',
713369e03dSAndrew Lindesay 	MSG_WORK_STATUS_CLEAR					= 'wscl',
72fdec4227SStephan Aßmus 
73ccf707d0SAndrew Lindesay 	MSG_CHANGE_PACKAGE_LIST_VIEW_MODE		= 'cplm',
74fdec4227SStephan Aßmus 	MSG_SHOW_AVAILABLE_PACKAGES				= 'savl',
75fdec4227SStephan Aßmus 	MSG_SHOW_INSTALLED_PACKAGES				= 'sins',
7604c9d578SStephan Aßmus 	MSG_SHOW_SOURCE_PACKAGES				= 'ssrc',
7704c9d578SStephan Aßmus 	MSG_SHOW_DEVELOP_PACKAGES				= 'sdvl'
7804c9d578SStephan Aßmus };
7904c9d578SStephan Aßmus 
8010cd325cSAndrew Lindesay #define KEY_ERROR_STATUS				"errorStatus"
81ccf707d0SAndrew Lindesay 
82ccf707d0SAndrew Lindesay #define TAB_PROMINENT_PACKAGES	0
83ccf707d0SAndrew Lindesay #define TAB_ALL_PACKAGES		1
8404c9d578SStephan Aßmus 
8504c9d578SStephan Aßmus using namespace BPackageKit;
8604c9d578SStephan Aßmus using namespace BPackageKit::BManager::BPrivate;
8704c9d578SStephan Aßmus 
8804c9d578SStephan Aßmus 
8904c9d578SStephan Aßmus typedef std::map<BString, PackageInfoRef> PackageInfoMap;
9004c9d578SStephan Aßmus 
9104c9d578SStephan Aßmus 
9204c9d578SStephan Aßmus struct RefreshWorkerParameters {
9304c9d578SStephan Aßmus 	MainWindow* window;
9404c9d578SStephan Aßmus 	bool forceRefresh;
9504c9d578SStephan Aßmus 
9604c9d578SStephan Aßmus 	RefreshWorkerParameters(MainWindow* window, bool forceRefresh)
9704c9d578SStephan Aßmus 		:
9804c9d578SStephan Aßmus 		window(window),
9904c9d578SStephan Aßmus 		forceRefresh(forceRefresh)
10004c9d578SStephan Aßmus 	{
10104c9d578SStephan Aßmus 	}
10204c9d578SStephan Aßmus };
10304c9d578SStephan Aßmus 
10404c9d578SStephan Aßmus 
10589b16bb4SAndrew Lindesay class MainWindowModelListener : public ModelListener {
1068f03a0f9SStephan Aßmus public:
10789b16bb4SAndrew Lindesay 	MainWindowModelListener(const BMessenger& messenger)
1088f03a0f9SStephan Aßmus 		:
1098f03a0f9SStephan Aßmus 		fMessenger(messenger)
1108f03a0f9SStephan Aßmus 	{
1118f03a0f9SStephan Aßmus 	}
1128f03a0f9SStephan Aßmus 
1138f03a0f9SStephan Aßmus 	virtual void AuthorizationChanged()
1148f03a0f9SStephan Aßmus 	{
1158f03a0f9SStephan Aßmus 		if (fMessenger.IsValid())
1168f03a0f9SStephan Aßmus 			fMessenger.SendMessage(MSG_AUTHORIZATION_CHANGED);
1178f03a0f9SStephan Aßmus 	}
1188f03a0f9SStephan Aßmus 
11989b16bb4SAndrew Lindesay 	virtual void CategoryListChanged()
12089b16bb4SAndrew Lindesay 	{
12189b16bb4SAndrew Lindesay 		if (fMessenger.IsValid())
12289b16bb4SAndrew Lindesay 			fMessenger.SendMessage(MSG_CATEGORIES_LIST_CHANGED);
12389b16bb4SAndrew Lindesay 	}
12489b16bb4SAndrew Lindesay 
1258f03a0f9SStephan Aßmus private:
1268f03a0f9SStephan Aßmus 	BMessenger	fMessenger;
1278f03a0f9SStephan Aßmus };
1288f03a0f9SStephan Aßmus 
1298f03a0f9SStephan Aßmus 
130f7c2983eSAxel Dörfler MainWindow::MainWindow(const BMessage& settings)
13104c9d578SStephan Aßmus 	:
132f7c2983eSAxel Dörfler 	BWindow(BRect(50, 50, 650, 550), B_TRANSLATE_SYSTEM_NAME("HaikuDepot"),
13304c9d578SStephan Aßmus 		B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
13404c9d578SStephan Aßmus 		B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS),
135d5ef985eSStephan Aßmus 	fScreenshotWindow(NULL),
136e0a26dceSStephan Aßmus 	fUserMenu(NULL),
137e0a26dceSStephan Aßmus 	fLogInItem(NULL),
138e0a26dceSStephan Aßmus 	fLogOutItem(NULL),
139976cadf1SAndrew Lindesay 	fUsersUserUsageConditionsMenuItem(NULL),
14089b16bb4SAndrew Lindesay 	fModelListener(new MainWindowModelListener(BMessenger(this)), true),
14110cd325cSAndrew Lindesay 	fCoordinator(NULL),
1423369e03dSAndrew Lindesay 	fSinglePackageMode(false)
14304c9d578SStephan Aßmus {
14410cd325cSAndrew Lindesay 	if ((fCoordinatorRunningSem = create_sem(1, "ProcessCoordinatorSem")) < B_OK)
14510cd325cSAndrew Lindesay 		debugger("unable to create the process coordinator semaphore");
14610cd325cSAndrew Lindesay 
147cbadcae1SHumdinger 	BMenuBar* menuBar = new BMenuBar("Main Menu");
14804c9d578SStephan Aßmus 	_BuildMenu(menuBar);
14904c9d578SStephan Aßmus 
150cbadcae1SHumdinger 	BMenuBar* userMenuBar = new BMenuBar("User Menu");
151e0a26dceSStephan Aßmus 	_BuildUserMenu(userMenuBar);
152e0a26dceSStephan Aßmus 	set_small_font(userMenuBar);
153e0a26dceSStephan Aßmus 	userMenuBar->SetExplicitMaxSize(BSize(B_SIZE_UNSET,
154e0a26dceSStephan Aßmus 		menuBar->MaxSize().height));
155e0a26dceSStephan Aßmus 
15604c9d578SStephan Aßmus 	fFilterView = new FilterView();
157f0e491d3SAndrew Lindesay 	fFeaturedPackagesView = new FeaturedPackagesView(fModel);
158f0e491d3SAndrew Lindesay 	fPackageListView = new PackageListView(&fModel);
159f0e491d3SAndrew Lindesay 	fPackageInfoView = new PackageInfoView(&fModel, this);
16004c9d578SStephan Aßmus 
16104c9d578SStephan Aßmus 	fSplitView = new BSplitView(B_VERTICAL, 5.0f);
16204c9d578SStephan Aßmus 
163125d42d9SJulian Harnath 	fWorkStatusView = new WorkStatusView("work status");
164125d42d9SJulian Harnath 	fPackageListView->AttachWorkStatusView(fWorkStatusView);
165125d42d9SJulian Harnath 
166e00a489bSAugustin Cavalier 	fListTabs = new TabView(BMessenger(this),
167ccf707d0SAndrew Lindesay 		BMessage(MSG_CHANGE_PACKAGE_LIST_VIEW_MODE), "list tabs");
168e00a489bSAugustin Cavalier 	fListTabs->AddTab(fFeaturedPackagesView);
169e00a489bSAugustin Cavalier 	fListTabs->AddTab(fPackageListView);
1704b930ccaSStephan Aßmus 
17104c9d578SStephan Aßmus 	BLayoutBuilder::Group<>(this, B_VERTICAL, 0.0f)
172e0a26dceSStephan Aßmus 		.AddGroup(B_HORIZONTAL, 0.0f)
173e0a26dceSStephan Aßmus 			.Add(menuBar, 1.0f)
174e0a26dceSStephan Aßmus 			.Add(userMenuBar, 0.0f)
175e0a26dceSStephan Aßmus 		.End()
17604c9d578SStephan Aßmus 		.Add(fFilterView)
17704c9d578SStephan Aßmus 		.AddSplit(fSplitView)
17804c9d578SStephan Aßmus 			.AddGroup(B_VERTICAL)
179e00a489bSAugustin Cavalier 				.Add(fListTabs)
18004c9d578SStephan Aßmus 				.SetInsets(
18104c9d578SStephan Aßmus 					B_USE_DEFAULT_SPACING, 0.0f,
18204c9d578SStephan Aßmus 					B_USE_DEFAULT_SPACING, 0.0f)
18304c9d578SStephan Aßmus 			.End()
18404c9d578SStephan Aßmus 			.Add(fPackageInfoView)
18504c9d578SStephan Aßmus 		.End()
186125d42d9SJulian Harnath 		.Add(fWorkStatusView)
18704c9d578SStephan Aßmus 	;
18804c9d578SStephan Aßmus 
18904c9d578SStephan Aßmus 	fSplitView->SetCollapsible(0, false);
19004c9d578SStephan Aßmus 	fSplitView->SetCollapsible(1, false);
19104c9d578SStephan Aßmus 
1928f03a0f9SStephan Aßmus 	fModel.AddListener(fModelListener);
1938f03a0f9SStephan Aßmus 
19404c9d578SStephan Aßmus 	BMessage columnSettings;
19504c9d578SStephan Aßmus 	if (settings.FindMessage("column settings", &columnSettings) == B_OK)
19604c9d578SStephan Aßmus 		fPackageListView->LoadState(&columnSettings);
19704c9d578SStephan Aßmus 
198ccf707d0SAndrew Lindesay 	_RestoreModelSettings(settings);
199133ebab6SAndrew Lindesay 	_MaybePromptCanShareAnonymousUserData(settings);
20004c9d578SStephan Aßmus 
201ccf707d0SAndrew Lindesay 	if (fModel.PackageListViewMode() == PROMINENT)
202ccf707d0SAndrew Lindesay 		fListTabs->Select(TAB_PROMINENT_PACKAGES);
2032997e05bSStephan Aßmus 	else
204ccf707d0SAndrew Lindesay 		fListTabs->Select(TAB_ALL_PACKAGES);
2052997e05bSStephan Aßmus 
206d2d4866dSAndrew Lindesay 	_RestoreNickname(settings);
20710cd325cSAndrew Lindesay 	_UpdateAuthorization();
208f7c2983eSAxel Dörfler 	_RestoreWindowFrame(settings);
209f7c2983eSAxel Dörfler 
2108f03a0f9SStephan Aßmus 	// start worker threads
21104c9d578SStephan Aßmus 	BPackageRoster().StartWatching(this,
21204c9d578SStephan Aßmus 		B_WATCH_PACKAGE_INSTALLATION_LOCATIONS);
21304c9d578SStephan Aßmus 
21463975654SStephan Aßmus 	_InitWorkerThreads();
2159883929bSAndrew Lindesay 	_AdoptModel();
2169883929bSAndrew Lindesay 	_StartBulkLoad();
21704c9d578SStephan Aßmus }
21804c9d578SStephan Aßmus 
21904c9d578SStephan Aßmus 
220f7c2983eSAxel Dörfler MainWindow::MainWindow(const BMessage& settings, const PackageInfoRef& package)
2216d519fd1SStephan Aßmus 	:
222f7c2983eSAxel Dörfler 	BWindow(BRect(50, 50, 650, 350), B_TRANSLATE_SYSTEM_NAME("HaikuDepot"),
2236d519fd1SStephan Aßmus 		B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
2246d519fd1SStephan Aßmus 		B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS),
2259883929bSAndrew Lindesay 	fFeaturedPackagesView(NULL),
2269883929bSAndrew Lindesay 	fPackageListView(NULL),
227d78bfd8dSJulian Harnath 	fWorkStatusView(NULL),
228d5ef985eSStephan Aßmus 	fScreenshotWindow(NULL),
229e0a26dceSStephan Aßmus 	fUserMenu(NULL),
230e0a26dceSStephan Aßmus 	fLogInItem(NULL),
2316d519fd1SStephan Aßmus 	fLogOutItem(NULL),
232976cadf1SAndrew Lindesay 	fUsersUserUsageConditionsMenuItem(NULL),
23389b16bb4SAndrew Lindesay 	fModelListener(new MainWindowModelListener(BMessenger(this)), true),
23410cd325cSAndrew Lindesay 	fCoordinator(NULL),
2353369e03dSAndrew Lindesay 	fSinglePackageMode(true)
2366d519fd1SStephan Aßmus {
23710cd325cSAndrew Lindesay 	if ((fCoordinatorRunningSem = create_sem(1, "ProcessCoordinatorSem")) < B_OK)
23810cd325cSAndrew Lindesay 		debugger("unable to create the process coordinator semaphore");
23910cd325cSAndrew Lindesay 
2406d519fd1SStephan Aßmus 	fFilterView = new FilterView();
241f0e491d3SAndrew Lindesay 	fPackageInfoView = new PackageInfoView(&fModel, this);
24287016f8fSAndrew Lindesay 	fWorkStatusView = new WorkStatusView("work status");
2436d519fd1SStephan Aßmus 
2446d519fd1SStephan Aßmus 	BLayoutBuilder::Group<>(this, B_VERTICAL)
2456d519fd1SStephan Aßmus 		.Add(fPackageInfoView)
24687016f8fSAndrew Lindesay 		.Add(fWorkStatusView)
2476d519fd1SStephan Aßmus 		.SetInsets(0, B_USE_WINDOW_INSETS, 0, 0)
2486d519fd1SStephan Aßmus 	;
2496d519fd1SStephan Aßmus 
2506d519fd1SStephan Aßmus 	fModel.AddListener(fModelListener);
2516d519fd1SStephan Aßmus 
2526d519fd1SStephan Aßmus 	// Restore settings
253d2d4866dSAndrew Lindesay 	_RestoreNickname(settings);
254ccf707d0SAndrew Lindesay 	_UpdateAuthorization();
255f7c2983eSAxel Dörfler 	_RestoreWindowFrame(settings);
2566d519fd1SStephan Aßmus 
2576d519fd1SStephan Aßmus 	fPackageInfoView->SetPackage(package);
25863975654SStephan Aßmus 
25963975654SStephan Aßmus 	_InitWorkerThreads();
2606d519fd1SStephan Aßmus }
2616d519fd1SStephan Aßmus 
2626d519fd1SStephan Aßmus 
26304c9d578SStephan Aßmus MainWindow::~MainWindow()
26404c9d578SStephan Aßmus {
26510cd325cSAndrew Lindesay 	_SpinUntilProcessCoordinatorComplete();
26610cd325cSAndrew Lindesay 	delete_sem(fCoordinatorRunningSem);
26710cd325cSAndrew Lindesay 	fCoordinatorRunningSem = 0;
26810cd325cSAndrew Lindesay 
26904c9d578SStephan Aßmus 	BPackageRoster().StopWatching(this);
27004c9d578SStephan Aßmus 
271d5ef985eSStephan Aßmus 	if (fScreenshotWindow != NULL && fScreenshotWindow->Lock())
272d5ef985eSStephan Aßmus 		fScreenshotWindow->Quit();
27304c9d578SStephan Aßmus }
27404c9d578SStephan Aßmus 
27504c9d578SStephan Aßmus 
27604c9d578SStephan Aßmus bool
27704c9d578SStephan Aßmus MainWindow::QuitRequested()
27804c9d578SStephan Aßmus {
27904c9d578SStephan Aßmus 	BMessage settings;
28004c9d578SStephan Aßmus 	StoreSettings(settings);
28104c9d578SStephan Aßmus 
28204c9d578SStephan Aßmus 	BMessage message(MSG_MAIN_WINDOW_CLOSED);
2833369e03dSAndrew Lindesay 	message.AddMessage(KEY_WINDOW_SETTINGS, &settings);
28404c9d578SStephan Aßmus 
28504c9d578SStephan Aßmus 	be_app->PostMessage(&message);
28604c9d578SStephan Aßmus 
28710cd325cSAndrew Lindesay 	_StopProcessCoordinators();
2883369e03dSAndrew Lindesay 
28904c9d578SStephan Aßmus 	return true;
29004c9d578SStephan Aßmus }
29104c9d578SStephan Aßmus 
29204c9d578SStephan Aßmus 
29304c9d578SStephan Aßmus void
29404c9d578SStephan Aßmus MainWindow::MessageReceived(BMessage* message)
29504c9d578SStephan Aßmus {
29604c9d578SStephan Aßmus 	switch (message->what) {
2973369e03dSAndrew Lindesay 		case MSG_BULK_LOAD_DONE:
29810cd325cSAndrew Lindesay 		{
29910cd325cSAndrew Lindesay 			int64 errorStatus64;
30010cd325cSAndrew Lindesay 			if (message->FindInt64(KEY_ERROR_STATUS, &errorStatus64) == B_OK)
30110cd325cSAndrew Lindesay 				_BulkLoadCompleteReceived((status_t) errorStatus64);
30210cd325cSAndrew Lindesay 			else
303fa5c8097SAndrew Lindesay 				HDERROR("expected [%s] value in message", KEY_ERROR_STATUS);
30404c9d578SStephan Aßmus 			break;
30510cd325cSAndrew Lindesay 		}
30604c9d578SStephan Aßmus 		case B_SIMPLE_DATA:
30704c9d578SStephan Aßmus 		case B_REFS_RECEIVED:
30804c9d578SStephan Aßmus 			// TODO: ?
30904c9d578SStephan Aßmus 			break;
31004c9d578SStephan Aßmus 
31104c9d578SStephan Aßmus 		case B_PACKAGE_UPDATE:
312*f32d5c5cSAndrew Lindesay 			_HandleExternalPackageUpdateMessageReceived(message);
31304c9d578SStephan Aßmus 			break;
31404c9d578SStephan Aßmus 
3155bf2b6ebSBrian Hill 		case MSG_REFRESH_REPOS:
3163369e03dSAndrew Lindesay 			_StartBulkLoad(true);
3173369e03dSAndrew Lindesay 			break;
3183369e03dSAndrew Lindesay 
31910cd325cSAndrew Lindesay 		case MSG_WORK_STATUS_CLEAR:
32010cd325cSAndrew Lindesay 			_HandleWorkStatusClear();
32110cd325cSAndrew Lindesay 			break;
32210cd325cSAndrew Lindesay 
3233369e03dSAndrew Lindesay 		case MSG_WORK_STATUS_CHANGE:
3243369e03dSAndrew Lindesay 			_HandleWorkStatusChangeMessageReceived(message);
32504c9d578SStephan Aßmus 			break;
32604c9d578SStephan Aßmus 
3275bf2b6ebSBrian Hill 		case MSG_MANAGE_REPOS:
3285bf2b6ebSBrian Hill 			be_roster->Launch("application/x-vnd.Haiku-Repositories");
3295bf2b6ebSBrian Hill 			break;
3305bf2b6ebSBrian Hill 
331d144f952SAugustin Cavalier 		case MSG_SOFTWARE_UPDATER:
332d144f952SAugustin Cavalier 			be_roster->Launch("application/x-vnd.haiku-softwareupdater");
333d144f952SAugustin Cavalier 			break;
334d144f952SAugustin Cavalier 
33504c9d578SStephan Aßmus 		case MSG_LOG_IN:
3361bbda92dSStephan Aßmus 			_OpenLoginWindow(BMessage());
33704c9d578SStephan Aßmus 			break;
33804c9d578SStephan Aßmus 
339133ebab6SAndrew Lindesay 		case MSG_SETTINGS:
340133ebab6SAndrew Lindesay 			_OpenSettingsWindow();
341133ebab6SAndrew Lindesay 			break;
342133ebab6SAndrew Lindesay 
3438f03a0f9SStephan Aßmus 		case MSG_LOG_OUT:
344d2d4866dSAndrew Lindesay 			fModel.SetNickname("");
3458f03a0f9SStephan Aßmus 			break;
3468f03a0f9SStephan Aßmus 
34701339a54SAndrew Lindesay 		case MSG_VIEW_LATEST_USER_USAGE_CONDITIONS:
348d2d4866dSAndrew Lindesay 			_ViewUserUsageConditions(LATEST);
349d2d4866dSAndrew Lindesay 			break;
350d2d4866dSAndrew Lindesay 
351d2d4866dSAndrew Lindesay 		case MSG_VIEW_USERS_USER_USAGE_CONDITIONS:
352d2d4866dSAndrew Lindesay 			_ViewUserUsageConditions(USER);
35301339a54SAndrew Lindesay 			break;
35401339a54SAndrew Lindesay 
3558f03a0f9SStephan Aßmus 		case MSG_AUTHORIZATION_CHANGED:
35610cd325cSAndrew Lindesay 			_StartUserVerify();
3578f03a0f9SStephan Aßmus 			_UpdateAuthorization();
3588f03a0f9SStephan Aßmus 			break;
3598f03a0f9SStephan Aßmus 
36089b16bb4SAndrew Lindesay 		case MSG_CATEGORIES_LIST_CHANGED:
36189b16bb4SAndrew Lindesay 			fFilterView->AdoptModel(fModel);
36289b16bb4SAndrew Lindesay 			break;
36389b16bb4SAndrew Lindesay 
364ccf707d0SAndrew Lindesay 		case MSG_CHANGE_PACKAGE_LIST_VIEW_MODE:
365ccf707d0SAndrew Lindesay 			_HandleChangePackageListViewMode();
3664fade61fSStephan Aßmus 			break;
3674fade61fSStephan Aßmus 
368fdec4227SStephan Aßmus 		case MSG_SHOW_AVAILABLE_PACKAGES:
369fdec4227SStephan Aßmus 			{
370fdec4227SStephan Aßmus 				BAutolock locker(fModel.Lock());
371fdec4227SStephan Aßmus 				fModel.SetShowAvailablePackages(
372fdec4227SStephan Aßmus 					!fModel.ShowAvailablePackages());
373fdec4227SStephan Aßmus 			}
374fdec4227SStephan Aßmus 			_AdoptModel();
375fdec4227SStephan Aßmus 			break;
376fdec4227SStephan Aßmus 
377fdec4227SStephan Aßmus 		case MSG_SHOW_INSTALLED_PACKAGES:
378fdec4227SStephan Aßmus 			{
379fdec4227SStephan Aßmus 				BAutolock locker(fModel.Lock());
380fdec4227SStephan Aßmus 				fModel.SetShowInstalledPackages(
381fdec4227SStephan Aßmus 					!fModel.ShowInstalledPackages());
382fdec4227SStephan Aßmus 			}
383fdec4227SStephan Aßmus 			_AdoptModel();
384fdec4227SStephan Aßmus 			break;
385fdec4227SStephan Aßmus 
38604c9d578SStephan Aßmus 		case MSG_SHOW_SOURCE_PACKAGES:
38704c9d578SStephan Aßmus 			{
38804c9d578SStephan Aßmus 				BAutolock locker(fModel.Lock());
38904c9d578SStephan Aßmus 				fModel.SetShowSourcePackages(!fModel.ShowSourcePackages());
39004c9d578SStephan Aßmus 			}
39104c9d578SStephan Aßmus 			_AdoptModel();
39204c9d578SStephan Aßmus 			break;
39304c9d578SStephan Aßmus 
39404c9d578SStephan Aßmus 		case MSG_SHOW_DEVELOP_PACKAGES:
39504c9d578SStephan Aßmus 			{
39604c9d578SStephan Aßmus 				BAutolock locker(fModel.Lock());
39704c9d578SStephan Aßmus 				fModel.SetShowDevelopPackages(!fModel.ShowDevelopPackages());
39804c9d578SStephan Aßmus 			}
39904c9d578SStephan Aßmus 			_AdoptModel();
40004c9d578SStephan Aßmus 			break;
40104c9d578SStephan Aßmus 
402a9edb9bfSAndrew Lindesay 			// this may be triggered by, for example, a user rating being added
403a9edb9bfSAndrew Lindesay 			// or having been altered.
404a9edb9bfSAndrew Lindesay 		case MSG_SERVER_DATA_CHANGED:
405a9edb9bfSAndrew Lindesay 		{
406a9edb9bfSAndrew Lindesay 			BString name;
407a9edb9bfSAndrew Lindesay 			if (message->FindString("name", &name) == B_OK) {
408a9edb9bfSAndrew Lindesay 				BAutolock locker(fModel.Lock());
409a9edb9bfSAndrew Lindesay 				if (fPackageInfoView->Package()->Name() == name) {
410a9edb9bfSAndrew Lindesay 					_PopulatePackageAsync(true);
411a9edb9bfSAndrew Lindesay 				} else {
412f96d1f4dSAndrew Lindesay 					HDDEBUG("pkg [%s] is updated on the server, but is "
413f96d1f4dSAndrew Lindesay 						"not selected so will not be updated.",
414fa5c8097SAndrew Lindesay 						name.String());
415a9edb9bfSAndrew Lindesay 				}
416a9edb9bfSAndrew Lindesay 			}
417a9edb9bfSAndrew Lindesay         	break;
418a9edb9bfSAndrew Lindesay         }
419a9edb9bfSAndrew Lindesay 
42004c9d578SStephan Aßmus 		case MSG_PACKAGE_SELECTED:
42104c9d578SStephan Aßmus 		{
42272992391SStephan Aßmus 			BString name;
42372992391SStephan Aßmus 			if (message->FindString("name", &name) == B_OK) {
424c4199192SAndrew Lindesay 				PackageInfoRef package;
425c4199192SAndrew Lindesay 				{
42675ba9dbfSStephan Aßmus 					BAutolock locker(fModel.Lock());
427c4199192SAndrew Lindesay 					package = fModel.PackageForName(name);
428c4199192SAndrew Lindesay 				}
4296f07feadSAndrew Lindesay 				if (!package.IsSet() || name != package->Name())
430c4199192SAndrew Lindesay 					debugger("unable to find the named package");
431133ebab6SAndrew Lindesay 				else {
43204c9d578SStephan Aßmus 					_AdoptPackage(package);
433133ebab6SAndrew Lindesay 					_IncrementViewCounter(package);
434133ebab6SAndrew Lindesay 				}
43504c9d578SStephan Aßmus 			} else {
43604c9d578SStephan Aßmus 				_ClearPackage();
43704c9d578SStephan Aßmus 			}
43804c9d578SStephan Aßmus 			break;
43904c9d578SStephan Aßmus 		}
44004c9d578SStephan Aßmus 
44104c9d578SStephan Aßmus 		case MSG_CATEGORY_SELECTED:
44204c9d578SStephan Aßmus 		{
44389b16bb4SAndrew Lindesay 			BString code;
44489b16bb4SAndrew Lindesay 			if (message->FindString("code", &code) != B_OK)
44589b16bb4SAndrew Lindesay 				code = "";
44604c9d578SStephan Aßmus 			{
44704c9d578SStephan Aßmus 				BAutolock locker(fModel.Lock());
44889b16bb4SAndrew Lindesay 				fModel.SetCategory(code);
44904c9d578SStephan Aßmus 			}
45004c9d578SStephan Aßmus 			_AdoptModel();
45104c9d578SStephan Aßmus 			break;
45204c9d578SStephan Aßmus 		}
45304c9d578SStephan Aßmus 
45404c9d578SStephan Aßmus 		case MSG_DEPOT_SELECTED:
45504c9d578SStephan Aßmus 		{
45604c9d578SStephan Aßmus 			BString name;
45704c9d578SStephan Aßmus 			if (message->FindString("name", &name) != B_OK)
45804c9d578SStephan Aßmus 				name = "";
45904c9d578SStephan Aßmus 			{
46004c9d578SStephan Aßmus 				BAutolock locker(fModel.Lock());
46104c9d578SStephan Aßmus 				fModel.SetDepot(name);
46204c9d578SStephan Aßmus 			}
46304c9d578SStephan Aßmus 			_AdoptModel();
464b965ce70SHumdinger 			_UpdateAvailableRepositories();
46504c9d578SStephan Aßmus 			break;
46604c9d578SStephan Aßmus 		}
46704c9d578SStephan Aßmus 
46804c9d578SStephan Aßmus 		case MSG_SEARCH_TERMS_MODIFIED:
46904c9d578SStephan Aßmus 		{
47004c9d578SStephan Aßmus 			// TODO: Do this with a delay!
47104c9d578SStephan Aßmus 			BString searchTerms;
47204c9d578SStephan Aßmus 			if (message->FindString("search terms", &searchTerms) != B_OK)
47304c9d578SStephan Aßmus 				searchTerms = "";
47404c9d578SStephan Aßmus 			{
47504c9d578SStephan Aßmus 				BAutolock locker(fModel.Lock());
47604c9d578SStephan Aßmus 				fModel.SetSearchTerms(searchTerms);
47704c9d578SStephan Aßmus 			}
47804c9d578SStephan Aßmus 			_AdoptModel();
47904c9d578SStephan Aßmus 			break;
48004c9d578SStephan Aßmus 		}
48104c9d578SStephan Aßmus 
482da651104SStephan Aßmus 		case MSG_PACKAGE_CHANGED:
48304c9d578SStephan Aßmus 		{
48404c9d578SStephan Aßmus 			PackageInfo* info;
48504c9d578SStephan Aßmus 			if (message->FindPointer("package", (void**)&info) == B_OK) {
48604c9d578SStephan Aßmus 				PackageInfoRef ref(info, true);
487da651104SStephan Aßmus 				uint32 changes;
488da651104SStephan Aßmus 				if (message->FindUInt32("changes", &changes) != B_OK)
489da651104SStephan Aßmus 					changes = 0;
490da651104SStephan Aßmus 				if ((changes & PKG_CHANGED_STATE) != 0) {
49104c9d578SStephan Aßmus 					BAutolock locker(fModel.Lock());
49204c9d578SStephan Aßmus 					fModel.SetPackageState(ref, ref->State());
49304c9d578SStephan Aßmus 				}
4940b69420bSAndrew Lindesay 
4950b69420bSAndrew Lindesay 				fFeaturedPackagesView->BeginAddRemove();
496c4199192SAndrew Lindesay 				_AddRemovePackageFromLists(ref);
4970b69420bSAndrew Lindesay 				fFeaturedPackagesView->EndAddRemove();
4980b69420bSAndrew Lindesay 
49987016f8fSAndrew Lindesay 				if ((changes & PKG_CHANGED_STATE) != 0
500779ab335SX512 						&& !fCoordinator.IsSet()) {
5014e6fbe03SJulian Harnath 					fWorkStatusView->PackageStatusChanged(ref);
50257e51fffSStephan Aßmus 				}
50310cd325cSAndrew Lindesay 			}
50404c9d578SStephan Aßmus 			break;
50504c9d578SStephan Aßmus 		}
50604c9d578SStephan Aßmus 
50704c9d578SStephan Aßmus 		case MSG_RATE_PACKAGE:
5081bbda92dSStephan Aßmus 			_RatePackage();
50904c9d578SStephan Aßmus 			break;
51004c9d578SStephan Aßmus 
511d5ef985eSStephan Aßmus 		case MSG_SHOW_SCREENSHOT:
512d5ef985eSStephan Aßmus 			_ShowScreenshot();
513d5ef985eSStephan Aßmus 			break;
514d5ef985eSStephan Aßmus 
515125d42d9SJulian Harnath 		case MSG_PACKAGE_WORKER_BUSY:
516125d42d9SJulian Harnath 		{
517125d42d9SJulian Harnath 			BString reason;
518125d42d9SJulian Harnath 			status_t status = message->FindString("reason", &reason);
519125d42d9SJulian Harnath 			if (status != B_OK)
520125d42d9SJulian Harnath 				break;
521125d42d9SJulian Harnath 			fWorkStatusView->SetBusy(reason);
522125d42d9SJulian Harnath 			break;
523125d42d9SJulian Harnath 		}
524125d42d9SJulian Harnath 
525125d42d9SJulian Harnath 		case MSG_PACKAGE_WORKER_IDLE:
526125d42d9SJulian Harnath 			fWorkStatusView->SetIdle();
527125d42d9SJulian Harnath 			break;
528125d42d9SJulian Harnath 
52910cd325cSAndrew Lindesay 		case MSG_USER_USAGE_CONDITIONS_NOT_LATEST:
53010cd325cSAndrew Lindesay 		{
53110cd325cSAndrew Lindesay 			BMessage userDetailMsg;
53210cd325cSAndrew Lindesay 			if (message->FindMessage("userDetail", &userDetailMsg) != B_OK) {
53310cd325cSAndrew Lindesay 				debugger("expected the [userDetail] data to be carried in the "
53410cd325cSAndrew Lindesay 					"message.");
53510cd325cSAndrew Lindesay 			}
53610cd325cSAndrew Lindesay 			UserDetail userDetail(&userDetailMsg);
53710cd325cSAndrew Lindesay 			_HandleUserUsageConditionsNotLatest(userDetail);
53810cd325cSAndrew Lindesay 			break;
53910cd325cSAndrew Lindesay 		}
54010cd325cSAndrew Lindesay 
54104c9d578SStephan Aßmus 		default:
54204c9d578SStephan Aßmus 			BWindow::MessageReceived(message);
54304c9d578SStephan Aßmus 			break;
54404c9d578SStephan Aßmus 	}
54504c9d578SStephan Aßmus }
54604c9d578SStephan Aßmus 
54704c9d578SStephan Aßmus 
548ccf707d0SAndrew Lindesay static const char*
549ccf707d0SAndrew Lindesay main_window_package_list_view_mode_str(package_list_view_mode mode)
550ccf707d0SAndrew Lindesay {
551ccf707d0SAndrew Lindesay 	if (mode == PROMINENT)
552ccf707d0SAndrew Lindesay 		return "PROMINENT";
553ccf707d0SAndrew Lindesay 	return "ALL";
554ccf707d0SAndrew Lindesay }
555ccf707d0SAndrew Lindesay 
556ccf707d0SAndrew Lindesay 
557ccf707d0SAndrew Lindesay static package_list_view_mode
558ccf707d0SAndrew Lindesay main_window_str_to_package_list_view_mode(const BString& str)
559ccf707d0SAndrew Lindesay {
560ccf707d0SAndrew Lindesay 	if (str == "PROMINENT")
561ccf707d0SAndrew Lindesay 		return PROMINENT;
562ccf707d0SAndrew Lindesay 	return ALL;
563ccf707d0SAndrew Lindesay }
564ccf707d0SAndrew Lindesay 
565ccf707d0SAndrew Lindesay 
56604c9d578SStephan Aßmus void
56704c9d578SStephan Aßmus MainWindow::StoreSettings(BMessage& settings) const
56804c9d578SStephan Aßmus {
569f7c2983eSAxel Dörfler 	settings.AddRect(_WindowFrameName(), Frame());
570f7c2983eSAxel Dörfler 	if (!fSinglePackageMode) {
57104c9d578SStephan Aßmus 		settings.AddRect("window frame", Frame());
57204c9d578SStephan Aßmus 
57304c9d578SStephan Aßmus 		BMessage columnSettings;
5749883929bSAndrew Lindesay 		if (fPackageListView != NULL)
57504c9d578SStephan Aßmus 			fPackageListView->SaveState(&columnSettings);
57604c9d578SStephan Aßmus 
57704c9d578SStephan Aßmus 		settings.AddMessage("column settings", &columnSettings);
57804c9d578SStephan Aßmus 
579133ebab6SAndrew Lindesay 		settings.AddString(SETTING_PACKAGE_LIST_VIEW_MODE,
580ccf707d0SAndrew Lindesay 			main_window_package_list_view_mode_str(
581ccf707d0SAndrew Lindesay 				fModel.PackageListViewMode()));
582133ebab6SAndrew Lindesay 		settings.AddBool(SETTING_SHOW_AVAILABLE_PACKAGES,
5832997e05bSStephan Aßmus 			fModel.ShowAvailablePackages());
584133ebab6SAndrew Lindesay 		settings.AddBool(SETTING_SHOW_INSTALLED_PACKAGES,
5852997e05bSStephan Aßmus 			fModel.ShowInstalledPackages());
586133ebab6SAndrew Lindesay 		settings.AddBool(SETTING_SHOW_DEVELOP_PACKAGES,
587133ebab6SAndrew Lindesay 			fModel.ShowDevelopPackages());
588133ebab6SAndrew Lindesay 		settings.AddBool(SETTING_SHOW_SOURCE_PACKAGES,
589133ebab6SAndrew Lindesay 			fModel.ShowSourcePackages());
590133ebab6SAndrew Lindesay 		settings.AddBool(SETTING_CAN_SHARE_ANONYMOUS_USER_DATA,
591133ebab6SAndrew Lindesay 			fModel.CanShareAnonymousUsageData());
5926d519fd1SStephan Aßmus 	}
5938f03a0f9SStephan Aßmus 
594d2d4866dSAndrew Lindesay 	settings.AddString("username", fModel.Nickname());
59504c9d578SStephan Aßmus }
59604c9d578SStephan Aßmus 
59704c9d578SStephan Aßmus 
59804c9d578SStephan Aßmus void
599a18f873fSAndrew Lindesay MainWindow::Consume(ProcessCoordinator *item)
600a18f873fSAndrew Lindesay {
601a18f873fSAndrew Lindesay 	_AddProcessCoordinator(item);
602a18f873fSAndrew Lindesay }
603a18f873fSAndrew Lindesay 
604a18f873fSAndrew Lindesay 
605a18f873fSAndrew Lindesay void
60604c9d578SStephan Aßmus MainWindow::PackageChanged(const PackageInfoEvent& event)
60704c9d578SStephan Aßmus {
608a9edb9bfSAndrew Lindesay 	uint32 watchedChanges = PKG_CHANGED_STATE | PKG_CHANGED_PROMINENCE;
609a9edb9bfSAndrew Lindesay 	if ((event.Changes() & watchedChanges) != 0) {
61004c9d578SStephan Aßmus 		PackageInfoRef ref(event.Package());
611da651104SStephan Aßmus 		BMessage message(MSG_PACKAGE_CHANGED);
61204c9d578SStephan Aßmus 		message.AddPointer("package", ref.Get());
613da651104SStephan Aßmus 		message.AddUInt32("changes", event.Changes());
61404c9d578SStephan Aßmus 		ref.Detach();
61504c9d578SStephan Aßmus 			// reference needs to be released by MessageReceived();
61604c9d578SStephan Aßmus 		PostMessage(&message);
61704c9d578SStephan Aßmus 	}
61804c9d578SStephan Aßmus }
61904c9d578SStephan Aßmus 
62004c9d578SStephan Aßmus 
62104c9d578SStephan Aßmus void
62204c9d578SStephan Aßmus MainWindow::_BuildMenu(BMenuBar* menuBar)
62304c9d578SStephan Aßmus {
6240b6928f1SHumdinger 	BMenu* menu = new BMenu(B_TRANSLATE_SYSTEM_NAME("HaikuDepot"));
6253369e03dSAndrew Lindesay 	fRefreshRepositoriesItem = new BMenuItem(
6263369e03dSAndrew Lindesay 		B_TRANSLATE("Refresh repositories"), new BMessage(MSG_REFRESH_REPOS));
6273369e03dSAndrew Lindesay 	menu->AddItem(fRefreshRepositoriesItem);
628d7f78130SHumdinger 	menu->AddItem(new BMenuItem(B_TRANSLATE("Manage repositories"
629d7f78130SHumdinger 		B_UTF8_ELLIPSIS), new BMessage(MSG_MANAGE_REPOS)));
630d144f952SAugustin Cavalier 	menu->AddItem(new BMenuItem(B_TRANSLATE("Check for updates"
631d144f952SAugustin Cavalier 		B_UTF8_ELLIPSIS), new BMessage(MSG_SOFTWARE_UPDATER)));
6320b6928f1SHumdinger 	menu->AddSeparatorItem();
6330b6928f1SHumdinger 	menu->AddItem(new BMenuItem(B_TRANSLATE("Settings" B_UTF8_ELLIPSIS),
634e1ae57abSJoachim Mairböck 		new BMessage(MSG_SETTINGS), ','));
6350b6928f1SHumdinger 	menu->AddItem(new BMenuItem(B_TRANSLATE("Quit"),
6360b6928f1SHumdinger 		new BMessage(B_QUIT_REQUESTED), 'Q'));
63704c9d578SStephan Aßmus 	menuBar->AddItem(menu);
63804c9d578SStephan Aßmus 
639b965ce70SHumdinger 	fRepositoryMenu = new BMenu(B_TRANSLATE("Repositories"));
640b965ce70SHumdinger 	menuBar->AddItem(fRepositoryMenu);
641b965ce70SHumdinger 
6424fade61fSStephan Aßmus 	menu = new BMenu(B_TRANSLATE("Show"));
6434fade61fSStephan Aßmus 
644fdec4227SStephan Aßmus 	fShowAvailablePackagesItem = new BMenuItem(
6454fade61fSStephan Aßmus 		B_TRANSLATE("Available packages"),
646fdec4227SStephan Aßmus 		new BMessage(MSG_SHOW_AVAILABLE_PACKAGES));
647fdec4227SStephan Aßmus 	menu->AddItem(fShowAvailablePackagesItem);
648fdec4227SStephan Aßmus 
649fdec4227SStephan Aßmus 	fShowInstalledPackagesItem = new BMenuItem(
6504fade61fSStephan Aßmus 		B_TRANSLATE("Installed packages"),
651fdec4227SStephan Aßmus 		new BMessage(MSG_SHOW_INSTALLED_PACKAGES));
652fdec4227SStephan Aßmus 	menu->AddItem(fShowInstalledPackagesItem);
653fdec4227SStephan Aßmus 
654fdec4227SStephan Aßmus 	menu->AddSeparatorItem();
655fdec4227SStephan Aßmus 
656fdec4227SStephan Aßmus 	fShowDevelopPackagesItem = new BMenuItem(
6574fade61fSStephan Aßmus 		B_TRANSLATE("Develop packages"),
658fdec4227SStephan Aßmus 		new BMessage(MSG_SHOW_DEVELOP_PACKAGES));
659fdec4227SStephan Aßmus 	menu->AddItem(fShowDevelopPackagesItem);
660fdec4227SStephan Aßmus 
661fdec4227SStephan Aßmus 	fShowSourcePackagesItem = new BMenuItem(
6624fade61fSStephan Aßmus 		B_TRANSLATE("Source packages"),
663fdec4227SStephan Aßmus 		new BMessage(MSG_SHOW_SOURCE_PACKAGES));
664fdec4227SStephan Aßmus 	menu->AddItem(fShowSourcePackagesItem);
665fdec4227SStephan Aßmus 
666fdec4227SStephan Aßmus 	menuBar->AddItem(menu);
66704c9d578SStephan Aßmus }
66804c9d578SStephan Aßmus 
66904c9d578SStephan Aßmus 
67004c9d578SStephan Aßmus void
671e0a26dceSStephan Aßmus MainWindow::_BuildUserMenu(BMenuBar* menuBar)
672e0a26dceSStephan Aßmus {
673e0a26dceSStephan Aßmus 	fUserMenu = new BMenu(B_TRANSLATE("Not logged in"));
674e0a26dceSStephan Aßmus 
675e0a26dceSStephan Aßmus 	fLogInItem = new BMenuItem(B_TRANSLATE("Log in" B_UTF8_ELLIPSIS),
676e0a26dceSStephan Aßmus 		new BMessage(MSG_LOG_IN));
677e0a26dceSStephan Aßmus 	fUserMenu->AddItem(fLogInItem);
678e0a26dceSStephan Aßmus 
679e0a26dceSStephan Aßmus 	fLogOutItem = new BMenuItem(B_TRANSLATE("Log out"),
680e0a26dceSStephan Aßmus 		new BMessage(MSG_LOG_OUT));
681e0a26dceSStephan Aßmus 	fUserMenu->AddItem(fLogOutItem);
682e0a26dceSStephan Aßmus 
6830c82f64bSAndrew Lindesay 	BMenuItem *latestUserUsageConditionsMenuItem =
6841448ced0SHumdinger 		new BMenuItem(B_TRANSLATE("View latest usage conditions"
68501339a54SAndrew Lindesay 			B_UTF8_ELLIPSIS),
68601339a54SAndrew Lindesay 			new BMessage(MSG_VIEW_LATEST_USER_USAGE_CONDITIONS));
6870c82f64bSAndrew Lindesay 	fUserMenu->AddItem(latestUserUsageConditionsMenuItem);
68801339a54SAndrew Lindesay 
689d2d4866dSAndrew Lindesay 	fUsersUserUsageConditionsMenuItem =
690d2d4866dSAndrew Lindesay 		new BMenuItem(B_TRANSLATE("View agreed usage conditions"
691d2d4866dSAndrew Lindesay 			B_UTF8_ELLIPSIS),
692d2d4866dSAndrew Lindesay 			new BMessage(MSG_VIEW_USERS_USER_USAGE_CONDITIONS));
693d2d4866dSAndrew Lindesay 	fUserMenu->AddItem(fUsersUserUsageConditionsMenuItem);
694d2d4866dSAndrew Lindesay 
695e0a26dceSStephan Aßmus 	menuBar->AddItem(fUserMenu);
696e0a26dceSStephan Aßmus }
697e0a26dceSStephan Aßmus 
698e0a26dceSStephan Aßmus 
699e0a26dceSStephan Aßmus void
700d2d4866dSAndrew Lindesay MainWindow::_RestoreNickname(const BMessage& settings)
701f7c2983eSAxel Dörfler {
702d2d4866dSAndrew Lindesay 	BString nickname;
703d2d4866dSAndrew Lindesay 	if (settings.FindString("username", &nickname) == B_OK
704d2d4866dSAndrew Lindesay 		&& nickname.Length() > 0) {
705d2d4866dSAndrew Lindesay 		fModel.SetNickname(nickname);
706f7c2983eSAxel Dörfler 	}
707f7c2983eSAxel Dörfler }
708f7c2983eSAxel Dörfler 
709f7c2983eSAxel Dörfler 
710f7c2983eSAxel Dörfler const char*
711f7c2983eSAxel Dörfler MainWindow::_WindowFrameName() const
712f7c2983eSAxel Dörfler {
713f7c2983eSAxel Dörfler 	if (fSinglePackageMode)
714f7c2983eSAxel Dörfler 		return "small window frame";
715f7c2983eSAxel Dörfler 
716f7c2983eSAxel Dörfler 	return "window frame";
717f7c2983eSAxel Dörfler }
718f7c2983eSAxel Dörfler 
719f7c2983eSAxel Dörfler 
720f7c2983eSAxel Dörfler void
721f7c2983eSAxel Dörfler MainWindow::_RestoreWindowFrame(const BMessage& settings)
722f7c2983eSAxel Dörfler {
723f7c2983eSAxel Dörfler 	BRect frame = Frame();
724f7c2983eSAxel Dörfler 
725f7c2983eSAxel Dörfler 	BRect windowFrame;
726f7c2983eSAxel Dörfler 	bool fromSettings = false;
727f7c2983eSAxel Dörfler 	if (settings.FindRect(_WindowFrameName(), &windowFrame) == B_OK) {
728f7c2983eSAxel Dörfler 		frame = windowFrame;
729f7c2983eSAxel Dörfler 		fromSettings = true;
730f7c2983eSAxel Dörfler 	} else if (!fSinglePackageMode) {
731f7c2983eSAxel Dörfler 		// Resize to occupy a certain screen size
732f7c2983eSAxel Dörfler 		BRect screenFrame = BScreen(this).Frame();
733f7c2983eSAxel Dörfler 		float width = frame.Width();
734f7c2983eSAxel Dörfler 		float height = frame.Height();
735f7c2983eSAxel Dörfler 		if (width < screenFrame.Width() * .666f
736f7c2983eSAxel Dörfler 			&& height < screenFrame.Height() * .666f) {
737f7c2983eSAxel Dörfler 			frame.bottom = frame.top + screenFrame.Height() * .666f;
738f7c2983eSAxel Dörfler 			frame.right = frame.left
739f7c2983eSAxel Dörfler 				+ std::min(screenFrame.Width() * .666f, height * 7 / 5);
740f7c2983eSAxel Dörfler 		}
741f7c2983eSAxel Dörfler 	}
742f7c2983eSAxel Dörfler 
743f7c2983eSAxel Dörfler 	MoveTo(frame.LeftTop());
744f7c2983eSAxel Dörfler 	ResizeTo(frame.Width(), frame.Height());
745f7c2983eSAxel Dörfler 
746f7c2983eSAxel Dörfler 	if (fromSettings)
7478e96ec34SAxel Dörfler 		MoveOnScreen();
748f7c2983eSAxel Dörfler 	else
749f7c2983eSAxel Dörfler 		CenterOnScreen();
750f7c2983eSAxel Dörfler }
751f7c2983eSAxel Dörfler 
752f7c2983eSAxel Dörfler 
753f7c2983eSAxel Dörfler void
754ccf707d0SAndrew Lindesay MainWindow::_RestoreModelSettings(const BMessage& settings)
755ccf707d0SAndrew Lindesay {
756ccf707d0SAndrew Lindesay 	BString packageListViewMode;
757133ebab6SAndrew Lindesay 	if (settings.FindString(SETTING_PACKAGE_LIST_VIEW_MODE,
758ccf707d0SAndrew Lindesay 			&packageListViewMode) == B_OK) {
759ccf707d0SAndrew Lindesay 		fModel.SetPackageListViewMode(
760ccf707d0SAndrew Lindesay 			main_window_str_to_package_list_view_mode(packageListViewMode));
761ccf707d0SAndrew Lindesay 	}
762ccf707d0SAndrew Lindesay 
763ccf707d0SAndrew Lindesay 	bool showOption;
764133ebab6SAndrew Lindesay 	if (settings.FindBool(SETTING_SHOW_AVAILABLE_PACKAGES, &showOption) == B_OK)
765ccf707d0SAndrew Lindesay 		fModel.SetShowAvailablePackages(showOption);
766133ebab6SAndrew Lindesay 	if (settings.FindBool(SETTING_SHOW_INSTALLED_PACKAGES, &showOption) == B_OK)
767ccf707d0SAndrew Lindesay 		fModel.SetShowInstalledPackages(showOption);
768133ebab6SAndrew Lindesay 	if (settings.FindBool(SETTING_SHOW_DEVELOP_PACKAGES, &showOption) == B_OK)
769ccf707d0SAndrew Lindesay 		fModel.SetShowDevelopPackages(showOption);
770133ebab6SAndrew Lindesay 	if (settings.FindBool(SETTING_SHOW_SOURCE_PACKAGES, &showOption) == B_OK)
771ccf707d0SAndrew Lindesay 		fModel.SetShowSourcePackages(showOption);
772133ebab6SAndrew Lindesay 	if (settings.FindBool(SETTING_CAN_SHARE_ANONYMOUS_USER_DATA,
773133ebab6SAndrew Lindesay 			&showOption) == B_OK) {
774133ebab6SAndrew Lindesay 		fModel.SetCanShareAnonymousUsageData(showOption);
775133ebab6SAndrew Lindesay 	}
776133ebab6SAndrew Lindesay }
777133ebab6SAndrew Lindesay 
778133ebab6SAndrew Lindesay 
779133ebab6SAndrew Lindesay void
780133ebab6SAndrew Lindesay MainWindow::_MaybePromptCanShareAnonymousUserData(const BMessage& settings)
781133ebab6SAndrew Lindesay {
782133ebab6SAndrew Lindesay 	bool showOption;
783133ebab6SAndrew Lindesay 	if (settings.FindBool(SETTING_CAN_SHARE_ANONYMOUS_USER_DATA,
784133ebab6SAndrew Lindesay 			&showOption) == B_NAME_NOT_FOUND) {
785133ebab6SAndrew Lindesay 		_PromptCanShareAnonymousUserData();
786133ebab6SAndrew Lindesay 	}
787133ebab6SAndrew Lindesay }
788133ebab6SAndrew Lindesay 
789133ebab6SAndrew Lindesay 
790133ebab6SAndrew Lindesay void
791133ebab6SAndrew Lindesay MainWindow::_PromptCanShareAnonymousUserData()
792133ebab6SAndrew Lindesay {
793133ebab6SAndrew Lindesay 	BAlert* alert = new(std::nothrow) BAlert(
794133ebab6SAndrew Lindesay 		B_TRANSLATE("Sending anonymous usage data"),
795133ebab6SAndrew Lindesay 		B_TRANSLATE("Would it be acceptable to send anonymous usage data to the"
796133ebab6SAndrew Lindesay 			" HaikuDepotServer system from this computer? You can change your"
797133ebab6SAndrew Lindesay 			" preference in the \"Settings\" window later."),
798133ebab6SAndrew Lindesay 		B_TRANSLATE("No"),
799133ebab6SAndrew Lindesay 		B_TRANSLATE("Yes"));
800133ebab6SAndrew Lindesay 
801133ebab6SAndrew Lindesay 	int32 result = alert->Go();
802133ebab6SAndrew Lindesay 	fModel.SetCanShareAnonymousUsageData(1 == result);
803ccf707d0SAndrew Lindesay }
804ccf707d0SAndrew Lindesay 
805ccf707d0SAndrew Lindesay 
806ccf707d0SAndrew Lindesay void
80763975654SStephan Aßmus MainWindow::_InitWorkerThreads()
80863975654SStephan Aßmus {
80963975654SStephan Aßmus 	fPackageToPopulateSem = create_sem(0, "PopulatePackage");
81063975654SStephan Aßmus 	if (fPackageToPopulateSem >= 0) {
81163975654SStephan Aßmus 		fPopulatePackageWorker = spawn_thread(&_PopulatePackageWorker,
81263975654SStephan Aßmus 			"Package Populator", B_NORMAL_PRIORITY, this);
81363975654SStephan Aßmus 		if (fPopulatePackageWorker >= 0)
81463975654SStephan Aßmus 			resume_thread(fPopulatePackageWorker);
81509f82905SStephan Aßmus 	} else
81609f82905SStephan Aßmus 		fPopulatePackageWorker = -1;
81763975654SStephan Aßmus }
81863975654SStephan Aßmus 
81963975654SStephan Aßmus 
82063975654SStephan Aßmus void
821c4199192SAndrew Lindesay MainWindow::_AdoptModelControls()
82204c9d578SStephan Aßmus {
8239883929bSAndrew Lindesay 	if (fSinglePackageMode)
8249883929bSAndrew Lindesay 		return;
8259883929bSAndrew Lindesay 
82604c9d578SStephan Aßmus 	BAutolock locker(fModel.Lock());
827fdec4227SStephan Aßmus 	fShowAvailablePackagesItem->SetMarked(fModel.ShowAvailablePackages());
828fdec4227SStephan Aßmus 	fShowInstalledPackagesItem->SetMarked(fModel.ShowInstalledPackages());
829fdec4227SStephan Aßmus 	fShowSourcePackagesItem->SetMarked(fModel.ShowSourcePackages());
830fdec4227SStephan Aßmus 	fShowDevelopPackagesItem->SetMarked(fModel.ShowDevelopPackages());
831da651104SStephan Aßmus 
832ccf707d0SAndrew Lindesay 	if (fModel.PackageListViewMode() == PROMINENT)
833ccf707d0SAndrew Lindesay 		fListTabs->Select(TAB_PROMINENT_PACKAGES);
8344fade61fSStephan Aßmus 	else
835ccf707d0SAndrew Lindesay 		fListTabs->Select(TAB_ALL_PACKAGES);
836b965ce70SHumdinger 
837b965ce70SHumdinger 	fFilterView->AdoptModel(fModel);
83804c9d578SStephan Aßmus }
83904c9d578SStephan Aßmus 
84004c9d578SStephan Aßmus 
84104c9d578SStephan Aßmus void
842c4199192SAndrew Lindesay MainWindow::_AdoptModel()
843c4199192SAndrew Lindesay {
844fa5c8097SAndrew Lindesay 	HDTRACE("adopting model to main window ui");
845c4199192SAndrew Lindesay 
846c4199192SAndrew Lindesay 	if (fSinglePackageMode)
847c4199192SAndrew Lindesay 		return;
848c4199192SAndrew Lindesay 
84905880d13SAndrew Lindesay 	std::vector<DepotInfoRef> depots = _CreateSnapshotOfDepots();
85005880d13SAndrew Lindesay 	std::vector<DepotInfoRef>::iterator it;
8510b69420bSAndrew Lindesay 
8520b69420bSAndrew Lindesay 	fFeaturedPackagesView->BeginAddRemove();
8530b69420bSAndrew Lindesay 
85405880d13SAndrew Lindesay 	for (it = depots.begin(); it != depots.end(); it++) {
85505880d13SAndrew Lindesay 		DepotInfoRef depotInfoRef = *it;
856d75b4d61SAndrew Lindesay 		for (int i = 0; i < depotInfoRef->CountPackages(); i++) {
857d75b4d61SAndrew Lindesay 			PackageInfoRef package = depotInfoRef->PackageAtIndex(i);
858d75b4d61SAndrew Lindesay 			_AddRemovePackageFromLists(package);
859d75b4d61SAndrew Lindesay 		}
860c4199192SAndrew Lindesay 	}
861c4199192SAndrew Lindesay 
8620b69420bSAndrew Lindesay 	fFeaturedPackagesView->EndAddRemove();
8630b69420bSAndrew Lindesay 
864c4199192SAndrew Lindesay 	_AdoptModelControls();
865c4199192SAndrew Lindesay }
866c4199192SAndrew Lindesay 
867c4199192SAndrew Lindesay 
868c4199192SAndrew Lindesay void
869c4199192SAndrew Lindesay MainWindow::_AddRemovePackageFromLists(const PackageInfoRef& package)
870c4199192SAndrew Lindesay {
871c4199192SAndrew Lindesay 	bool matches;
872c4199192SAndrew Lindesay 
873c4199192SAndrew Lindesay 	{
874c4199192SAndrew Lindesay 		AutoLocker<BLocker> modelLocker(fModel.Lock());
875c4199192SAndrew Lindesay 		matches = fModel.MatchesFilter(package);
876c4199192SAndrew Lindesay 	}
877c4199192SAndrew Lindesay 
878c4199192SAndrew Lindesay 	if (matches) {
879c4199192SAndrew Lindesay 		if (package->IsProminent())
880c4199192SAndrew Lindesay 			fFeaturedPackagesView->AddPackage(package);
881c4199192SAndrew Lindesay 		fPackageListView->AddPackage(package);
882c4199192SAndrew Lindesay 	} else {
883c4199192SAndrew Lindesay 		fFeaturedPackagesView->RemovePackage(package);
884c4199192SAndrew Lindesay 		fPackageListView->RemovePackage(package);
885c4199192SAndrew Lindesay 	}
886c4199192SAndrew Lindesay }
887c4199192SAndrew Lindesay 
888c4199192SAndrew Lindesay 
889c4199192SAndrew Lindesay void
890133ebab6SAndrew Lindesay MainWindow::_IncrementViewCounter(const PackageInfoRef& package)
891133ebab6SAndrew Lindesay {
892133ebab6SAndrew Lindesay 	bool shouldIncrementViewCounter = false;
893133ebab6SAndrew Lindesay 
894133ebab6SAndrew Lindesay 	{
895133ebab6SAndrew Lindesay 		AutoLocker<BLocker> modelLocker(fModel.Lock());
896133ebab6SAndrew Lindesay 		bool canShareAnonymousUsageData = fModel.CanShareAnonymousUsageData();
897133ebab6SAndrew Lindesay 		if (canShareAnonymousUsageData && !package->Viewed()) {
898133ebab6SAndrew Lindesay 			package->SetViewed();
899133ebab6SAndrew Lindesay 			shouldIncrementViewCounter = true;
900133ebab6SAndrew Lindesay 		}
901133ebab6SAndrew Lindesay 	}
902133ebab6SAndrew Lindesay 
903133ebab6SAndrew Lindesay 	if (shouldIncrementViewCounter) {
904133ebab6SAndrew Lindesay 		ProcessCoordinator* bulkLoadCoordinator =
905133ebab6SAndrew Lindesay 			ProcessCoordinatorFactory::CreateIncrementViewCounter(
906133ebab6SAndrew Lindesay 				&fModel, package);
907133ebab6SAndrew Lindesay 		_AddProcessCoordinator(bulkLoadCoordinator);
908133ebab6SAndrew Lindesay 	}
909133ebab6SAndrew Lindesay }
910133ebab6SAndrew Lindesay 
911133ebab6SAndrew Lindesay 
912133ebab6SAndrew Lindesay void
91304c9d578SStephan Aßmus MainWindow::_AdoptPackage(const PackageInfoRef& package)
91404c9d578SStephan Aßmus {
91575ba9dbfSStephan Aßmus 	{
91675ba9dbfSStephan Aßmus 		BAutolock locker(fModel.Lock());
91704c9d578SStephan Aßmus 		fPackageInfoView->SetPackage(package);
9181986ab9fSStephan Aßmus 
919664372abSStephan Aßmus 		if (fFeaturedPackagesView != NULL)
920664372abSStephan Aßmus 			fFeaturedPackagesView->SelectPackage(package);
9211986ab9fSStephan Aßmus 		if (fPackageListView != NULL)
9221986ab9fSStephan Aßmus 			fPackageListView->SelectPackage(package);
92375ba9dbfSStephan Aßmus 	}
92404c9d578SStephan Aßmus 
925a9edb9bfSAndrew Lindesay 	_PopulatePackageAsync(false);
92604c9d578SStephan Aßmus }
92704c9d578SStephan Aßmus 
92804c9d578SStephan Aßmus 
92904c9d578SStephan Aßmus void
93004c9d578SStephan Aßmus MainWindow::_ClearPackage()
93104c9d578SStephan Aßmus {
93204c9d578SStephan Aßmus 	fPackageInfoView->Clear();
93304c9d578SStephan Aßmus }
93404c9d578SStephan Aßmus 
93504c9d578SStephan Aßmus 
93604c9d578SStephan Aßmus void
9373369e03dSAndrew Lindesay MainWindow::_StartBulkLoad(bool force)
93804c9d578SStephan Aßmus {
939c4199192SAndrew Lindesay 	if (fFeaturedPackagesView != NULL)
940c4199192SAndrew Lindesay 		fFeaturedPackagesView->Clear();
941c4199192SAndrew Lindesay 	if (fPackageListView != NULL)
942c4199192SAndrew Lindesay 		fPackageListView->Clear();
943c4199192SAndrew Lindesay 	fPackageInfoView->Clear();
944c4199192SAndrew Lindesay 
94510cd325cSAndrew Lindesay 	fRefreshRepositoriesItem->SetEnabled(false);
94610cd325cSAndrew Lindesay 	ProcessCoordinator* bulkLoadCoordinator =
94710cd325cSAndrew Lindesay 		ProcessCoordinatorFactory::CreateBulkLoadCoordinator(
9483369e03dSAndrew Lindesay 			this,
9493369e03dSAndrew Lindesay 				// PackageInfoListener
9503369e03dSAndrew Lindesay 			&fModel, force);
95110cd325cSAndrew Lindesay 	_AddProcessCoordinator(bulkLoadCoordinator);
95204c9d578SStephan Aßmus }
95304c9d578SStephan Aßmus 
95404c9d578SStephan Aßmus 
95504c9d578SStephan Aßmus void
95610cd325cSAndrew Lindesay MainWindow::_BulkLoadCompleteReceived(status_t errorStatus)
95704c9d578SStephan Aßmus {
95810cd325cSAndrew Lindesay 	if (errorStatus != B_OK) {
9593369e03dSAndrew Lindesay 		AppUtils::NotifySimpleError(
9601448ced0SHumdinger 			B_TRANSLATE("Package update error"),
9613369e03dSAndrew Lindesay 			B_TRANSLATE("While updating package data, a problem has arisen "
9623369e03dSAndrew Lindesay 				"that may cause data to be outdated or missing from the "
9633369e03dSAndrew Lindesay 				"application's display. Additional details regarding this "
9643369e03dSAndrew Lindesay 				"problem may be able to be obtained from the application "
965b21c9447SAndrew Lindesay 				"logs."
966b21c9447SAndrew Lindesay 				ALERT_MSG_LOGS_USER_GUIDE));
96704c9d578SStephan Aßmus 	}
96810cd325cSAndrew Lindesay 
9693369e03dSAndrew Lindesay 	fRefreshRepositoriesItem->SetEnabled(true);
97010cd325cSAndrew Lindesay 	_AdoptModel();
97110cd325cSAndrew Lindesay 	_UpdateAvailableRepositories();
972ccf707d0SAndrew Lindesay 
973ccf707d0SAndrew Lindesay 	// if after loading everything in, it transpires that there are no
974ccf707d0SAndrew Lindesay 	// featured packages then the featured packages should be disabled
975ccf707d0SAndrew Lindesay 	// and the user should be switched to the "all packages" view so
976ccf707d0SAndrew Lindesay 	// that they are not presented with a blank window!
977ccf707d0SAndrew Lindesay 
978ccf707d0SAndrew Lindesay 	bool hasProminentPackages = fModel.HasAnyProminentPackages();
979ccf707d0SAndrew Lindesay 	fListTabs->TabAt(TAB_PROMINENT_PACKAGES)->SetEnabled(hasProminentPackages);
980ccf707d0SAndrew Lindesay 	if (!hasProminentPackages
981ccf707d0SAndrew Lindesay 			&& fListTabs->Selection() == TAB_PROMINENT_PACKAGES) {
982ccf707d0SAndrew Lindesay 		fModel.SetPackageListViewMode(ALL);
983ccf707d0SAndrew Lindesay 		fListTabs->Select(TAB_ALL_PACKAGES);
984ccf707d0SAndrew Lindesay 	}
98504c9d578SStephan Aßmus }
98604c9d578SStephan Aßmus 
98704c9d578SStephan Aßmus 
9883369e03dSAndrew Lindesay void
98910cd325cSAndrew Lindesay MainWindow::_NotifyWorkStatusClear()
99004c9d578SStephan Aßmus {
99110cd325cSAndrew Lindesay 	BMessage message(MSG_WORK_STATUS_CLEAR);
99210cd325cSAndrew Lindesay 	this->PostMessage(&message, this);
99310cd325cSAndrew Lindesay }
99410cd325cSAndrew Lindesay 
99510cd325cSAndrew Lindesay 
99610cd325cSAndrew Lindesay void
99710cd325cSAndrew Lindesay MainWindow::_HandleWorkStatusClear()
99810cd325cSAndrew Lindesay {
99910cd325cSAndrew Lindesay 	fWorkStatusView->SetText("");
10003369e03dSAndrew Lindesay 	fWorkStatusView->SetIdle();
10013369e03dSAndrew Lindesay }
100204c9d578SStephan Aßmus 
100304c9d578SStephan Aßmus 
10043369e03dSAndrew Lindesay /*! Sends off a message to the Window so that it can change the status view
10053369e03dSAndrew Lindesay     on the front-end in the UI thread.
10063369e03dSAndrew Lindesay */
100704c9d578SStephan Aßmus 
10083369e03dSAndrew Lindesay void
10093369e03dSAndrew Lindesay MainWindow::_NotifyWorkStatusChange(const BString& text, float progress)
10103369e03dSAndrew Lindesay {
10113369e03dSAndrew Lindesay 	BMessage message(MSG_WORK_STATUS_CHANGE);
101204c9d578SStephan Aßmus 
10133369e03dSAndrew Lindesay 	if (!text.IsEmpty())
10143369e03dSAndrew Lindesay 		message.AddString(KEY_WORK_STATUS_TEXT, text);
10153369e03dSAndrew Lindesay 	message.AddFloat(KEY_WORK_STATUS_PROGRESS, progress);
101604c9d578SStephan Aßmus 
10173369e03dSAndrew Lindesay 	this->PostMessage(&message, this);
10183369e03dSAndrew Lindesay }
101904c9d578SStephan Aßmus 
10203369e03dSAndrew Lindesay 
1021*f32d5c5cSAndrew Lindesay // needs to be implemented to update details for added / removed packages.
1022*f32d5c5cSAndrew Lindesay // TODO: see ticket #15879
1023*f32d5c5cSAndrew Lindesay 
1024*f32d5c5cSAndrew Lindesay void
1025*f32d5c5cSAndrew Lindesay MainWindow::_HandleExternalPackageUpdateMessageReceived(const BMessage* message)
1026*f32d5c5cSAndrew Lindesay {
1027*f32d5c5cSAndrew Lindesay 	BStringList addedPackageNames;
1028*f32d5c5cSAndrew Lindesay 	BStringList removedPackageNames;
1029*f32d5c5cSAndrew Lindesay 
1030*f32d5c5cSAndrew Lindesay 	if (message->FindStrings("added package names",
1031*f32d5c5cSAndrew Lindesay 			&addedPackageNames) == B_OK) {
1032*f32d5c5cSAndrew Lindesay 		addedPackageNames.Sort();
1033*f32d5c5cSAndrew Lindesay 		for (int32 i = 0; i < addedPackageNames.CountStrings(); i++) {
1034*f32d5c5cSAndrew Lindesay 			HDINFO("added package name; %s",
1035*f32d5c5cSAndrew Lindesay 				addedPackageNames.StringAt(i).String());
1036*f32d5c5cSAndrew Lindesay 		}
1037*f32d5c5cSAndrew Lindesay 	}
1038*f32d5c5cSAndrew Lindesay 	else
1039*f32d5c5cSAndrew Lindesay 		HDINFO("no [added package names] key in inbound message");
1040*f32d5c5cSAndrew Lindesay 
1041*f32d5c5cSAndrew Lindesay 	if (message->FindStrings("removed package names",
1042*f32d5c5cSAndrew Lindesay 			&removedPackageNames) == B_OK) {
1043*f32d5c5cSAndrew Lindesay 		removedPackageNames.Sort();
1044*f32d5c5cSAndrew Lindesay 		for (int32 i = 0; i < removedPackageNames.CountStrings(); i++) {
1045*f32d5c5cSAndrew Lindesay 			HDINFO("removed package name; %s",
1046*f32d5c5cSAndrew Lindesay 				removedPackageNames.StringAt(i).String());
1047*f32d5c5cSAndrew Lindesay 		}
1048*f32d5c5cSAndrew Lindesay 	} else
1049*f32d5c5cSAndrew Lindesay 		HDINFO("no [removed package names] key in inbound message");
1050*f32d5c5cSAndrew Lindesay }
1051*f32d5c5cSAndrew Lindesay 
1052*f32d5c5cSAndrew Lindesay 
10533369e03dSAndrew Lindesay void
10543369e03dSAndrew Lindesay MainWindow::_HandleWorkStatusChangeMessageReceived(const BMessage* message)
10553369e03dSAndrew Lindesay {
10569883929bSAndrew Lindesay 	if (fWorkStatusView == NULL)
10579883929bSAndrew Lindesay 		return;
10589883929bSAndrew Lindesay 
10593369e03dSAndrew Lindesay 	BString text;
10603369e03dSAndrew Lindesay 	float progress;
10613369e03dSAndrew Lindesay 
10623369e03dSAndrew Lindesay 	if (message->FindString(KEY_WORK_STATUS_TEXT, &text) == B_OK)
10633369e03dSAndrew Lindesay 		fWorkStatusView->SetText(text);
10643369e03dSAndrew Lindesay 
1065a18f873fSAndrew Lindesay 	if (message->FindFloat(KEY_WORK_STATUS_PROGRESS, &progress) == B_OK) {
1066a18f873fSAndrew Lindesay 		if (progress < 0.0f)
1067a18f873fSAndrew Lindesay 			fWorkStatusView->SetBusy();
1068a18f873fSAndrew Lindesay 		else
10693369e03dSAndrew Lindesay 			fWorkStatusView->SetProgress(progress);
1070a18f873fSAndrew Lindesay 	} else {
1071a18f873fSAndrew Lindesay 		HDERROR("work status change missing progress on update message");
1072a18f873fSAndrew Lindesay 		fWorkStatusView->SetProgress(0.0f);
107304c9d578SStephan Aßmus 	}
107404c9d578SStephan Aßmus }
107504c9d578SStephan Aßmus 
107604c9d578SStephan Aßmus 
1077a9edb9bfSAndrew Lindesay /*! This method will cause the package to have its data refreshed from
1078a9edb9bfSAndrew Lindesay     the server application.  The refresh happens in the background; this method
1079a9edb9bfSAndrew Lindesay     is asynchronous.
1080a9edb9bfSAndrew Lindesay */
1081a9edb9bfSAndrew Lindesay 
1082a9edb9bfSAndrew Lindesay void
1083a9edb9bfSAndrew Lindesay MainWindow::_PopulatePackageAsync(bool forcePopulate)
1084a9edb9bfSAndrew Lindesay {
1085a9edb9bfSAndrew Lindesay 		// Trigger asynchronous package population from the web-app
1086a9edb9bfSAndrew Lindesay 	{
1087a9edb9bfSAndrew Lindesay 		AutoLocker<BLocker> lock(&fPackageToPopulateLock);
1088a9edb9bfSAndrew Lindesay 		fPackageToPopulate = fPackageInfoView->Package();
1089a9edb9bfSAndrew Lindesay 		fForcePopulatePackage = forcePopulate;
1090a9edb9bfSAndrew Lindesay 	}
1091a9edb9bfSAndrew Lindesay 	release_sem_etc(fPackageToPopulateSem, 1, 0);
1092a9edb9bfSAndrew Lindesay 
1093f96d1f4dSAndrew Lindesay 	HDDEBUG("pkg [%s] will be updated from the server.",
1094fa5c8097SAndrew Lindesay 		fPackageToPopulate->Name().String());
1095a9edb9bfSAndrew Lindesay }
1096a9edb9bfSAndrew Lindesay 
1097a9edb9bfSAndrew Lindesay 
1098a9edb9bfSAndrew Lindesay /*! This method will run in the background.  The thread will block until there
1099a9edb9bfSAndrew Lindesay     is a package to be updated.  When the thread unblocks, it will update the
1100a9edb9bfSAndrew Lindesay     package with information from the server.
1101a9edb9bfSAndrew Lindesay */
1102a9edb9bfSAndrew Lindesay 
110304c9d578SStephan Aßmus status_t
110404c9d578SStephan Aßmus MainWindow::_PopulatePackageWorker(void* arg)
110504c9d578SStephan Aßmus {
110604c9d578SStephan Aßmus 	MainWindow* window = reinterpret_cast<MainWindow*>(arg);
110704c9d578SStephan Aßmus 
110804c9d578SStephan Aßmus 	while (acquire_sem(window->fPackageToPopulateSem) == B_OK) {
110904c9d578SStephan Aßmus 		PackageInfoRef package;
1110a9edb9bfSAndrew Lindesay 		bool force;
111104c9d578SStephan Aßmus 		{
111204c9d578SStephan Aßmus 			AutoLocker<BLocker> lock(&window->fPackageToPopulateLock);
111304c9d578SStephan Aßmus 			package = window->fPackageToPopulate;
1114a9edb9bfSAndrew Lindesay 			force = window->fForcePopulatePackage;
111504c9d578SStephan Aßmus 		}
111604c9d578SStephan Aßmus 
1117779ab335SX512 		if (package.IsSet()) {
1118a9edb9bfSAndrew Lindesay 			uint32 populateFlags = Model::POPULATE_USER_RATINGS
1119a9edb9bfSAndrew Lindesay 				| Model::POPULATE_SCREEN_SHOTS
1120a9edb9bfSAndrew Lindesay 				| Model::POPULATE_CHANGELOG;
1121a9edb9bfSAndrew Lindesay 
1122a9edb9bfSAndrew Lindesay 			if (force)
1123a9edb9bfSAndrew Lindesay 				populateFlags |= Model::POPULATE_FORCE;
1124a9edb9bfSAndrew Lindesay 
1125a9edb9bfSAndrew Lindesay 			window->fModel.PopulatePackage(package, populateFlags);
1126a9edb9bfSAndrew Lindesay 
1127fa5c8097SAndrew Lindesay 			HDDEBUG("populating package [%s]", package->Name().String());
112804c9d578SStephan Aßmus 		}
112904c9d578SStephan Aßmus 	}
113004c9d578SStephan Aßmus 
113104c9d578SStephan Aßmus 	return 0;
113204c9d578SStephan Aßmus }
113304c9d578SStephan Aßmus 
113404c9d578SStephan Aßmus 
113504c9d578SStephan Aßmus void
1136133ebab6SAndrew Lindesay MainWindow::_OpenSettingsWindow()
1137133ebab6SAndrew Lindesay {
1138133ebab6SAndrew Lindesay 	SettingsWindow* window = new SettingsWindow(this, &fModel);
1139133ebab6SAndrew Lindesay 	window->Show();
1140133ebab6SAndrew Lindesay }
1141133ebab6SAndrew Lindesay 
1142133ebab6SAndrew Lindesay 
1143133ebab6SAndrew Lindesay void
11441bbda92dSStephan Aßmus MainWindow::_OpenLoginWindow(const BMessage& onSuccessMessage)
114504c9d578SStephan Aßmus {
114604c9d578SStephan Aßmus 	UserLoginWindow* window = new UserLoginWindow(this,
114704c9d578SStephan Aßmus 		BRect(0, 0, 500, 400), fModel);
11481bbda92dSStephan Aßmus 
11491bbda92dSStephan Aßmus 	if (onSuccessMessage.what != 0)
11501bbda92dSStephan Aßmus 		window->SetOnSuccessMessage(BMessenger(this), onSuccessMessage);
11511bbda92dSStephan Aßmus 
115204c9d578SStephan Aßmus 	window->Show();
115304c9d578SStephan Aßmus }
115404c9d578SStephan Aßmus 
11558f03a0f9SStephan Aßmus 
11568f03a0f9SStephan Aßmus void
115710cd325cSAndrew Lindesay MainWindow::_StartUserVerify()
115810cd325cSAndrew Lindesay {
115910cd325cSAndrew Lindesay 	if (!fModel.Nickname().IsEmpty()) {
116010cd325cSAndrew Lindesay 		_AddProcessCoordinator(
116110cd325cSAndrew Lindesay 			ProcessCoordinatorFactory::CreateUserDetailVerifierCoordinator(
116210cd325cSAndrew Lindesay 				this,
116310cd325cSAndrew Lindesay 					// UserDetailVerifierListener
116410cd325cSAndrew Lindesay 				&fModel) );
116510cd325cSAndrew Lindesay 	}
116610cd325cSAndrew Lindesay }
116710cd325cSAndrew Lindesay 
116810cd325cSAndrew Lindesay 
116910cd325cSAndrew Lindesay void
11708f03a0f9SStephan Aßmus MainWindow::_UpdateAuthorization()
11718f03a0f9SStephan Aßmus {
1172d2d4866dSAndrew Lindesay 	BString nickname(fModel.Nickname());
1173d2d4866dSAndrew Lindesay 	bool hasUser = !nickname.IsEmpty();
1174e0a26dceSStephan Aßmus 
11756d519fd1SStephan Aßmus 	if (fLogOutItem != NULL)
1176e0a26dceSStephan Aßmus 		fLogOutItem->SetEnabled(hasUser);
1177d2d4866dSAndrew Lindesay 	if (fUsersUserUsageConditionsMenuItem != NULL)
1178d2d4866dSAndrew Lindesay 		fUsersUserUsageConditionsMenuItem->SetEnabled(hasUser);
1179e0a26dceSStephan Aßmus 	if (fLogInItem != NULL) {
1180e0a26dceSStephan Aßmus 		if (hasUser)
1181e0a26dceSStephan Aßmus 			fLogInItem->SetLabel(B_TRANSLATE("Switch account" B_UTF8_ELLIPSIS));
1182e0a26dceSStephan Aßmus 		else
1183e0a26dceSStephan Aßmus 			fLogInItem->SetLabel(B_TRANSLATE("Log in" B_UTF8_ELLIPSIS));
1184e0a26dceSStephan Aßmus 	}
1185e0a26dceSStephan Aßmus 
1186e0a26dceSStephan Aßmus 	if (fUserMenu != NULL) {
1187e0a26dceSStephan Aßmus 		BString label;
1188d2d4866dSAndrew Lindesay 		if (hasUser) {
1189e0a26dceSStephan Aßmus 			label = B_TRANSLATE("Logged in as %User%");
1190d2d4866dSAndrew Lindesay 			label.ReplaceAll("%User%", nickname);
1191d2d4866dSAndrew Lindesay 		} else {
1192d2d4866dSAndrew Lindesay 			label = B_TRANSLATE("Not logged in");
1193e0a26dceSStephan Aßmus 		}
1194e0a26dceSStephan Aßmus 		fUserMenu->Superitem()->SetLabel(label);
1195e0a26dceSStephan Aßmus 	}
11968f03a0f9SStephan Aßmus }
11971bbda92dSStephan Aßmus 
11981bbda92dSStephan Aßmus 
11991bbda92dSStephan Aßmus void
1200b965ce70SHumdinger MainWindow::_UpdateAvailableRepositories()
1201b965ce70SHumdinger {
1202b965ce70SHumdinger 	fRepositoryMenu->RemoveItems(0, fRepositoryMenu->CountItems(), true);
1203b965ce70SHumdinger 
1204b965ce70SHumdinger 	fRepositoryMenu->AddItem(new BMenuItem(B_TRANSLATE("All repositories"),
1205b965ce70SHumdinger 		new BMessage(MSG_DEPOT_SELECTED)));
1206b965ce70SHumdinger 
1207b965ce70SHumdinger 	fRepositoryMenu->AddItem(new BSeparatorItem());
1208b965ce70SHumdinger 
1209b965ce70SHumdinger 	bool foundSelectedDepot = false;
121005880d13SAndrew Lindesay 	std::vector<DepotInfoRef> depots = _CreateSnapshotOfDepots();
121105880d13SAndrew Lindesay 	std::vector<DepotInfoRef>::iterator it;
1212d13c3d89SAndrew Lindesay 
121305880d13SAndrew Lindesay 	for (it = depots.begin(); it != depots.end(); it++) {
121405880d13SAndrew Lindesay 		DepotInfoRef depot = *it;
121505880d13SAndrew Lindesay 
121605880d13SAndrew Lindesay 		if (depot->Name().Length() != 0) {
1217b965ce70SHumdinger 			BMessage* message = new BMessage(MSG_DEPOT_SELECTED);
121805880d13SAndrew Lindesay 			message->AddString("name", depot->Name());
121905880d13SAndrew Lindesay 			BMenuItem* item = new(std::nothrow) BMenuItem(depot->Name(), message);
122005880d13SAndrew Lindesay 
122105880d13SAndrew Lindesay 			if (item == NULL)
122205880d13SAndrew Lindesay 				HDFATAL("memory exhaustion");
122305880d13SAndrew Lindesay 
1224b965ce70SHumdinger 			fRepositoryMenu->AddItem(item);
1225b965ce70SHumdinger 
122605880d13SAndrew Lindesay 			if (depot->Name() == fModel.Depot()) {
1227b965ce70SHumdinger 				item->SetMarked(true);
1228b965ce70SHumdinger 				foundSelectedDepot = true;
1229b965ce70SHumdinger 			}
1230b965ce70SHumdinger 		}
1231d13c3d89SAndrew Lindesay 	}
1232b965ce70SHumdinger 
1233b965ce70SHumdinger 	if (!foundSelectedDepot)
1234b965ce70SHumdinger 		fRepositoryMenu->ItemAt(0)->SetMarked(true);
1235b965ce70SHumdinger }
1236b965ce70SHumdinger 
1237b965ce70SHumdinger 
1238a9edb9bfSAndrew Lindesay bool
1239a9edb9bfSAndrew Lindesay MainWindow::_SelectedPackageHasWebAppRepositoryCode()
1240a9edb9bfSAndrew Lindesay {
1241a9edb9bfSAndrew Lindesay 	const PackageInfoRef& package = fPackageInfoView->Package();
12426ab878c0SAndrew Lindesay 	const BString depotName = package->DepotName();
1243a9edb9bfSAndrew Lindesay 
12446ab878c0SAndrew Lindesay 	if (depotName.IsEmpty()) {
1245fa5c8097SAndrew Lindesay 		HDDEBUG("the package [%s] has no depot name", package->Name().String());
12466ab878c0SAndrew Lindesay 	} else {
12476ab878c0SAndrew Lindesay 		const DepotInfo* depot = fModel.DepotForName(depotName);
1248a9edb9bfSAndrew Lindesay 
12496ab878c0SAndrew Lindesay 		if (depot == NULL) {
1250f96d1f4dSAndrew Lindesay 			HDINFO("the depot [%s] was not able to be found",
1251fa5c8097SAndrew Lindesay 				depotName.String());
12526ab878c0SAndrew Lindesay 		} else {
12536ab878c0SAndrew Lindesay 			BString repositoryCode = depot->WebAppRepositoryCode();
1254a9edb9bfSAndrew Lindesay 
12556ab878c0SAndrew Lindesay 			if (repositoryCode.IsEmpty()) {
1256f96d1f4dSAndrew Lindesay 				HDINFO("the depot [%s] has no web app repository code",
1257fa5c8097SAndrew Lindesay 					depotName.String());
1258fa5c8097SAndrew Lindesay 			} else
12596ab878c0SAndrew Lindesay 				return true;
12606ab878c0SAndrew Lindesay 		}
12616ab878c0SAndrew Lindesay 	}
12626ab878c0SAndrew Lindesay 
12636ab878c0SAndrew Lindesay 	return false;
1264a9edb9bfSAndrew Lindesay }
1265a9edb9bfSAndrew Lindesay 
1266a9edb9bfSAndrew Lindesay 
1267b965ce70SHumdinger void
12681bbda92dSStephan Aßmus MainWindow::_RatePackage()
12691bbda92dSStephan Aßmus {
1270a9edb9bfSAndrew Lindesay 	if (!_SelectedPackageHasWebAppRepositoryCode()) {
1271a9edb9bfSAndrew Lindesay 		BAlert* alert = new(std::nothrow) BAlert(
1272cbadcae1SHumdinger 			B_TRANSLATE("Rating not possible"),
1273cbadcae1SHumdinger 			B_TRANSLATE("This package doesn't seem to be on the HaikuDepot "
1274cbadcae1SHumdinger 				"Server, so it's not possible to create a new rating "
1275cbadcae1SHumdinger 				"or edit an existing rating."),
1276a9edb9bfSAndrew Lindesay 			B_TRANSLATE("OK"));
1277a9edb9bfSAndrew Lindesay 		alert->Go();
1278a9edb9bfSAndrew Lindesay     	return;
1279a9edb9bfSAndrew Lindesay 	}
1280a9edb9bfSAndrew Lindesay 
1281d2d4866dSAndrew Lindesay 	if (fModel.Nickname().IsEmpty()) {
12821bbda92dSStephan Aßmus 		BAlert* alert = new(std::nothrow) BAlert(
12831bbda92dSStephan Aßmus 			B_TRANSLATE("Not logged in"),
12841bbda92dSStephan Aßmus 			B_TRANSLATE("You need to be logged into an account before you "
12851bbda92dSStephan Aßmus 				"can rate packages."),
12861bbda92dSStephan Aßmus 			B_TRANSLATE("Cancel"),
12871bbda92dSStephan Aßmus 			B_TRANSLATE("Login or Create account"));
12881bbda92dSStephan Aßmus 
12891bbda92dSStephan Aßmus 		if (alert == NULL)
12901bbda92dSStephan Aßmus 			return;
12911bbda92dSStephan Aßmus 
12921bbda92dSStephan Aßmus 		int32 choice = alert->Go();
12931bbda92dSStephan Aßmus 		if (choice == 1)
12941bbda92dSStephan Aßmus 			_OpenLoginWindow(BMessage(MSG_RATE_PACKAGE));
12951bbda92dSStephan Aßmus 		return;
12961bbda92dSStephan Aßmus 	}
12971bbda92dSStephan Aßmus 
12981bbda92dSStephan Aßmus 	// TODO: Allow only one RatePackageWindow
12991bbda92dSStephan Aßmus 	// TODO: Mechanism for remembering the window frame
13001bbda92dSStephan Aßmus 	RatePackageWindow* window = new RatePackageWindow(this,
13011bbda92dSStephan Aßmus 		BRect(0, 0, 500, 400), fModel);
13021bbda92dSStephan Aßmus 	window->SetPackage(fPackageInfoView->Package());
13031bbda92dSStephan Aßmus 	window->Show();
13041bbda92dSStephan Aßmus }
1305d5ef985eSStephan Aßmus 
1306d5ef985eSStephan Aßmus 
1307d5ef985eSStephan Aßmus void
1308d5ef985eSStephan Aßmus MainWindow::_ShowScreenshot()
1309d5ef985eSStephan Aßmus {
1310d5ef985eSStephan Aßmus 	// TODO: Mechanism for remembering the window frame
1311d5ef985eSStephan Aßmus 	if (fScreenshotWindow == NULL)
1312d5ef985eSStephan Aßmus 		fScreenshotWindow = new ScreenshotWindow(this, BRect(0, 0, 500, 400));
1313d5ef985eSStephan Aßmus 
1314d5ef985eSStephan Aßmus 	if (fScreenshotWindow->LockWithTimeout(1000) != B_OK)
1315d5ef985eSStephan Aßmus 		return;
1316d5ef985eSStephan Aßmus 
1317d5ef985eSStephan Aßmus 	fScreenshotWindow->SetPackage(fPackageInfoView->Package());
1318d5ef985eSStephan Aßmus 
1319d5ef985eSStephan Aßmus 	if (fScreenshotWindow->IsHidden())
1320d5ef985eSStephan Aßmus 		fScreenshotWindow->Show();
1321d5ef985eSStephan Aßmus 	else
1322d5ef985eSStephan Aßmus 		fScreenshotWindow->Activate();
1323d5ef985eSStephan Aßmus 
1324d5ef985eSStephan Aßmus 	fScreenshotWindow->Unlock();
1325d5ef985eSStephan Aßmus }
132601339a54SAndrew Lindesay 
132701339a54SAndrew Lindesay 
132801339a54SAndrew Lindesay void
1329d2d4866dSAndrew Lindesay MainWindow::_ViewUserUsageConditions(
1330d2d4866dSAndrew Lindesay 	UserUsageConditionsSelectionMode mode)
133101339a54SAndrew Lindesay {
133201339a54SAndrew Lindesay 	UserUsageConditionsWindow* window = new UserUsageConditionsWindow(
1333d2d4866dSAndrew Lindesay 		fModel, mode);
133401339a54SAndrew Lindesay 	window->Show();
133501339a54SAndrew Lindesay }
133610cd325cSAndrew Lindesay 
133710cd325cSAndrew Lindesay 
133810cd325cSAndrew Lindesay void
133910cd325cSAndrew Lindesay MainWindow::UserCredentialsFailed()
134010cd325cSAndrew Lindesay {
134110cd325cSAndrew Lindesay 	BString message = B_TRANSLATE("The password previously "
134210cd325cSAndrew Lindesay 		"supplied for the user [%Nickname%] is not currently "
134310cd325cSAndrew Lindesay 		"valid. The user will be logged-out of this application "
134410cd325cSAndrew Lindesay 		"and you should login again with your updated password.");
134510cd325cSAndrew Lindesay 	message.ReplaceAll("%Nickname%", fModel.Nickname());
134610cd325cSAndrew Lindesay 
134710cd325cSAndrew Lindesay 	AppUtils::NotifySimpleError(B_TRANSLATE("Login issue"),
134810cd325cSAndrew Lindesay 		message);
134910cd325cSAndrew Lindesay 
135010cd325cSAndrew Lindesay 	{
135110cd325cSAndrew Lindesay 		AutoLocker<BLocker> locker(fModel.Lock());
135210cd325cSAndrew Lindesay 		fModel.SetNickname("");
135310cd325cSAndrew Lindesay 	}
135410cd325cSAndrew Lindesay }
135510cd325cSAndrew Lindesay 
135610cd325cSAndrew Lindesay 
135710cd325cSAndrew Lindesay /*! \brief This method is invoked from the UserDetailVerifierProcess on a
135810cd325cSAndrew Lindesay 		   background thread.  For this reason it lodges a message into itself
135910cd325cSAndrew Lindesay 		   which can then be handled on the main thread.
136010cd325cSAndrew Lindesay */
136110cd325cSAndrew Lindesay 
136210cd325cSAndrew Lindesay void
136310cd325cSAndrew Lindesay MainWindow::UserUsageConditionsNotLatest(const UserDetail& userDetail)
136410cd325cSAndrew Lindesay {
136510cd325cSAndrew Lindesay 	BMessage message(MSG_USER_USAGE_CONDITIONS_NOT_LATEST);
136610cd325cSAndrew Lindesay 	BMessage detailsMessage;
136710cd325cSAndrew Lindesay 	if (userDetail.Archive(&detailsMessage, true) != B_OK
136810cd325cSAndrew Lindesay 			|| message.AddMessage("userDetail", &detailsMessage) != B_OK) {
1369fa5c8097SAndrew Lindesay 		HDERROR("unable to archive the user detail into a message");
137010cd325cSAndrew Lindesay 	}
137110cd325cSAndrew Lindesay 	else
137210cd325cSAndrew Lindesay 		BMessenger(this).SendMessage(&message);
137310cd325cSAndrew Lindesay }
137410cd325cSAndrew Lindesay 
137510cd325cSAndrew Lindesay 
137610cd325cSAndrew Lindesay void
137710cd325cSAndrew Lindesay MainWindow::_HandleUserUsageConditionsNotLatest(
137810cd325cSAndrew Lindesay 	const UserDetail& userDetail)
137910cd325cSAndrew Lindesay {
138010cd325cSAndrew Lindesay 	ToLatestUserUsageConditionsWindow* window =
138110cd325cSAndrew Lindesay 		new ToLatestUserUsageConditionsWindow(this, fModel, userDetail);
138210cd325cSAndrew Lindesay 	window->Show();
138310cd325cSAndrew Lindesay }
138410cd325cSAndrew Lindesay 
138510cd325cSAndrew Lindesay 
138610cd325cSAndrew Lindesay void
138710cd325cSAndrew Lindesay MainWindow::_AddProcessCoordinator(ProcessCoordinator* item)
138810cd325cSAndrew Lindesay {
138910cd325cSAndrew Lindesay 	AutoLocker<BLocker> lock(&fCoordinatorLock);
139010cd325cSAndrew Lindesay 
1391a18f873fSAndrew Lindesay 	item->SetListener(this);
1392a18f873fSAndrew Lindesay 
1393779ab335SX512 	if (!fCoordinator.IsSet()) {
139410cd325cSAndrew Lindesay 		if (acquire_sem(fCoordinatorRunningSem) != B_OK)
139510cd325cSAndrew Lindesay 			debugger("unable to acquire the process coordinator sem");
1396f96d1f4dSAndrew Lindesay 		HDINFO("adding and starting a process coordinator [%s]",
1397fa5c8097SAndrew Lindesay 			item->Name().String());
1398f95ec23eSAndrew Lindesay 		fCoordinator = BReference<ProcessCoordinator>(item);
139910cd325cSAndrew Lindesay 		fCoordinator->Start();
140010cd325cSAndrew Lindesay 	}
140110cd325cSAndrew Lindesay 	else {
1402f96d1f4dSAndrew Lindesay 		HDINFO("adding process coordinator [%s] to the queue",
140310cd325cSAndrew Lindesay 			item->Name().String());
140410cd325cSAndrew Lindesay 		fCoordinatorQueue.push(item);
140510cd325cSAndrew Lindesay 	}
140610cd325cSAndrew Lindesay }
140710cd325cSAndrew Lindesay 
140810cd325cSAndrew Lindesay 
140910cd325cSAndrew Lindesay void
141010cd325cSAndrew Lindesay MainWindow::_SpinUntilProcessCoordinatorComplete()
141110cd325cSAndrew Lindesay {
141210cd325cSAndrew Lindesay 	while (true) {
141310cd325cSAndrew Lindesay 		if (acquire_sem(fCoordinatorRunningSem) != B_OK)
141410cd325cSAndrew Lindesay 			debugger("unable to acquire the process coordinator sem");
141510cd325cSAndrew Lindesay 		if (release_sem(fCoordinatorRunningSem) != B_OK)
141610cd325cSAndrew Lindesay 			debugger("unable to release the process coordinator sem");
141710cd325cSAndrew Lindesay 		{
141810cd325cSAndrew Lindesay 			AutoLocker<BLocker> lock(&fCoordinatorLock);
1419779ab335SX512 			if (!fCoordinator.IsSet())
142010cd325cSAndrew Lindesay 				return;
142110cd325cSAndrew Lindesay 		}
142210cd325cSAndrew Lindesay 	}
142310cd325cSAndrew Lindesay }
142410cd325cSAndrew Lindesay 
142510cd325cSAndrew Lindesay 
142610cd325cSAndrew Lindesay void
142710cd325cSAndrew Lindesay MainWindow::_StopProcessCoordinators()
142810cd325cSAndrew Lindesay {
1429fa5c8097SAndrew Lindesay 	HDINFO("will stop all process coordinators");
143010cd325cSAndrew Lindesay 
143110cd325cSAndrew Lindesay 	{
143210cd325cSAndrew Lindesay 		AutoLocker<BLocker> lock(&fCoordinatorLock);
143310cd325cSAndrew Lindesay 
143410cd325cSAndrew Lindesay 		while (!fCoordinatorQueue.empty()) {
1435f96d1f4dSAndrew Lindesay 			BReference<ProcessCoordinator> processCoordinator
1436f96d1f4dSAndrew Lindesay 				= fCoordinatorQueue.front();
1437f96d1f4dSAndrew Lindesay 			HDINFO("will drop queued process coordinator [%s]",
1438fa5c8097SAndrew Lindesay 				processCoordinator->Name().String());
143910cd325cSAndrew Lindesay 			fCoordinatorQueue.pop();
144010cd325cSAndrew Lindesay 		}
144110cd325cSAndrew Lindesay 
1442779ab335SX512 		if (fCoordinator.IsSet()) {
144310cd325cSAndrew Lindesay 			fCoordinator->Stop();
144410cd325cSAndrew Lindesay 		}
144510cd325cSAndrew Lindesay 	}
144610cd325cSAndrew Lindesay 
1447fa5c8097SAndrew Lindesay 	HDINFO("will wait until the process coordinator has stopped");
144810cd325cSAndrew Lindesay 
144910cd325cSAndrew Lindesay 	_SpinUntilProcessCoordinatorComplete();
145010cd325cSAndrew Lindesay 
1451fa5c8097SAndrew Lindesay 	HDINFO("did stop all process coordinators");
145210cd325cSAndrew Lindesay }
145310cd325cSAndrew Lindesay 
145410cd325cSAndrew Lindesay 
145510cd325cSAndrew Lindesay /*! This method is called when there is some change in the bulk load process
145610cd325cSAndrew Lindesay 	or other process coordinator.
145710cd325cSAndrew Lindesay 	A change may mean that a new process has started / stopped etc... or it
145810cd325cSAndrew Lindesay 	may mean that the entire coordinator has finished.
145910cd325cSAndrew Lindesay */
146010cd325cSAndrew Lindesay 
146110cd325cSAndrew Lindesay void
146210cd325cSAndrew Lindesay MainWindow::CoordinatorChanged(ProcessCoordinatorState& coordinatorState)
146310cd325cSAndrew Lindesay {
146410cd325cSAndrew Lindesay 	AutoLocker<BLocker> lock(&fCoordinatorLock);
146510cd325cSAndrew Lindesay 
1466f95ec23eSAndrew Lindesay 	if (fCoordinator.Get() == coordinatorState.Coordinator()) {
146710cd325cSAndrew Lindesay 		if (!coordinatorState.IsRunning()) {
146810cd325cSAndrew Lindesay 			if (release_sem(fCoordinatorRunningSem) != B_OK)
146910cd325cSAndrew Lindesay 				debugger("unable to release the process coordinator sem");
1470f96d1f4dSAndrew Lindesay 			HDINFO("process coordinator [%s] did complete",
1471fa5c8097SAndrew Lindesay 				fCoordinator->Name().String());
147210cd325cSAndrew Lindesay 			// complete the last one that just finished
147310cd325cSAndrew Lindesay 			BMessage* message = fCoordinator->Message();
147410cd325cSAndrew Lindesay 
147510cd325cSAndrew Lindesay 			if (message != NULL) {
147610cd325cSAndrew Lindesay 				BMessenger messenger(this);
147710cd325cSAndrew Lindesay 				message->AddInt64(KEY_ERROR_STATUS,
147810cd325cSAndrew Lindesay 					(int64) fCoordinator->ErrorStatus());
147910cd325cSAndrew Lindesay 				messenger.SendMessage(message);
148010cd325cSAndrew Lindesay 			}
148110cd325cSAndrew Lindesay 
1482f95ec23eSAndrew Lindesay 			fCoordinator = BReference<ProcessCoordinator>(NULL);
1483f95ec23eSAndrew Lindesay 				// will delete the old process coordinator if it is not used
1484f95ec23eSAndrew Lindesay 				// elsewhere.
148510cd325cSAndrew Lindesay 
148610cd325cSAndrew Lindesay 			// now schedule the next one.
148710cd325cSAndrew Lindesay 			if (!fCoordinatorQueue.empty()) {
148810cd325cSAndrew Lindesay 				if (acquire_sem(fCoordinatorRunningSem) != B_OK)
148910cd325cSAndrew Lindesay 					debugger("unable to acquire the process coordinator sem");
149010cd325cSAndrew Lindesay 				fCoordinator = fCoordinatorQueue.front();
1491f96d1f4dSAndrew Lindesay 				HDINFO("starting next process coordinator [%s]",
149210cd325cSAndrew Lindesay 					fCoordinator->Name().String());
149310cd325cSAndrew Lindesay 				fCoordinatorQueue.pop();
149410cd325cSAndrew Lindesay 				fCoordinator->Start();
149510cd325cSAndrew Lindesay 			}
149610cd325cSAndrew Lindesay 			else {
149710cd325cSAndrew Lindesay 				_NotifyWorkStatusClear();
149810cd325cSAndrew Lindesay 			}
149910cd325cSAndrew Lindesay 		}
150010cd325cSAndrew Lindesay 		else {
150110cd325cSAndrew Lindesay 			_NotifyWorkStatusChange(coordinatorState.Message(),
150210cd325cSAndrew Lindesay 				coordinatorState.Progress());
150310cd325cSAndrew Lindesay 				// show the progress to the user.
150410cd325cSAndrew Lindesay 		}
1505fa5c8097SAndrew Lindesay 	} else
1506fa5c8097SAndrew Lindesay 		HDINFO("! unknown process coordinator changed");
150710cd325cSAndrew Lindesay }
1508ccf707d0SAndrew Lindesay 
1509ccf707d0SAndrew Lindesay 
1510ccf707d0SAndrew Lindesay static package_list_view_mode
1511ccf707d0SAndrew Lindesay main_window_tab_to_package_list_view_mode(int32 tab)
1512ccf707d0SAndrew Lindesay {
1513ccf707d0SAndrew Lindesay 	if (tab == TAB_PROMINENT_PACKAGES)
1514ccf707d0SAndrew Lindesay 		return PROMINENT;
1515ccf707d0SAndrew Lindesay 	return ALL;
1516ccf707d0SAndrew Lindesay }
1517ccf707d0SAndrew Lindesay 
1518ccf707d0SAndrew Lindesay 
1519ccf707d0SAndrew Lindesay void
1520ccf707d0SAndrew Lindesay MainWindow::_HandleChangePackageListViewMode()
1521ccf707d0SAndrew Lindesay {
1522ccf707d0SAndrew Lindesay 	package_list_view_mode tabMode = main_window_tab_to_package_list_view_mode(
1523ccf707d0SAndrew Lindesay 		fListTabs->Selection());
1524ccf707d0SAndrew Lindesay 	package_list_view_mode modelMode = fModel.PackageListViewMode();
1525ccf707d0SAndrew Lindesay 
1526ccf707d0SAndrew Lindesay 	if (tabMode != modelMode) {
1527ccf707d0SAndrew Lindesay 		BAutolock locker(fModel.Lock());
1528ccf707d0SAndrew Lindesay 		fModel.SetPackageListViewMode(tabMode);
1529ccf707d0SAndrew Lindesay 	}
1530ccf707d0SAndrew Lindesay }
153105880d13SAndrew Lindesay 
153205880d13SAndrew Lindesay 
153305880d13SAndrew Lindesay std::vector<DepotInfoRef>
153405880d13SAndrew Lindesay MainWindow::_CreateSnapshotOfDepots()
153505880d13SAndrew Lindesay {
153605880d13SAndrew Lindesay 	std::vector<DepotInfoRef> result;
153705880d13SAndrew Lindesay 	BAutolock locker(fModel.Lock());
153805880d13SAndrew Lindesay 	int32 countDepots = fModel.CountDepots();
153905880d13SAndrew Lindesay 	for(int32 i = 0; i < countDepots; i++)
154005880d13SAndrew Lindesay 		result.push_back(fModel.DepotAtIndex(i));
154105880d13SAndrew Lindesay 	return result;
154205880d13SAndrew Lindesay }
1543