xref: /haiku/src/apps/haikudepot/ui/MainWindow.cpp (revision 467ffecdbb58da0d122cde10a69c426925bf4e2f)
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"
5195c7b018SAndrew Lindesay #include "ShuttingDownWindow.h"
5210cd325cSAndrew Lindesay #include "ToLatestUserUsageConditionsWindow.h"
5304c9d578SStephan Aßmus #include "UserLoginWindow.h"
5401339a54SAndrew Lindesay #include "UserUsageConditionsWindow.h"
55125d42d9SJulian Harnath #include "WorkStatusView.h"
5604c9d578SStephan Aßmus 
5704c9d578SStephan Aßmus 
5804c9d578SStephan Aßmus #undef B_TRANSLATION_CONTEXT
5904c9d578SStephan Aßmus #define B_TRANSLATION_CONTEXT "MainWindow"
6004c9d578SStephan Aßmus 
6104c9d578SStephan Aßmus 
6204c9d578SStephan Aßmus enum {
635bf2b6ebSBrian Hill 	MSG_REFRESH_REPOS						= 'mrrp',
645bf2b6ebSBrian Hill 	MSG_MANAGE_REPOS						= 'mmrp',
65d144f952SAugustin Cavalier 	MSG_SOFTWARE_UPDATER					= 'mswu',
66133ebab6SAndrew Lindesay 	MSG_SETTINGS							= 'stgs',
6704c9d578SStephan Aßmus 	MSG_LOG_IN								= 'lgin',
688f03a0f9SStephan Aßmus 	MSG_AUTHORIZATION_CHANGED				= 'athc',
6989b16bb4SAndrew Lindesay 	MSG_CATEGORIES_LIST_CHANGED				= 'clic',
70da651104SStephan Aßmus 	MSG_PACKAGE_CHANGED						= 'pchd',
713369e03dSAndrew Lindesay 	MSG_WORK_STATUS_CHANGE					= 'wsch',
723369e03dSAndrew Lindesay 	MSG_WORK_STATUS_CLEAR					= 'wscl',
73fdec4227SStephan Aßmus 
74ccf707d0SAndrew Lindesay 	MSG_CHANGE_PACKAGE_LIST_VIEW_MODE		= 'cplm',
75fdec4227SStephan Aßmus 	MSG_SHOW_AVAILABLE_PACKAGES				= 'savl',
76fdec4227SStephan Aßmus 	MSG_SHOW_INSTALLED_PACKAGES				= 'sins',
7704c9d578SStephan Aßmus 	MSG_SHOW_SOURCE_PACKAGES				= 'ssrc',
7804c9d578SStephan Aßmus 	MSG_SHOW_DEVELOP_PACKAGES				= 'sdvl'
7904c9d578SStephan Aßmus };
8004c9d578SStephan Aßmus 
8110cd325cSAndrew Lindesay #define KEY_ERROR_STATUS				"errorStatus"
82ccf707d0SAndrew Lindesay 
83ccf707d0SAndrew Lindesay #define TAB_PROMINENT_PACKAGES	0
84ccf707d0SAndrew Lindesay #define TAB_ALL_PACKAGES		1
8504c9d578SStephan Aßmus 
8604c9d578SStephan Aßmus using namespace BPackageKit;
8704c9d578SStephan Aßmus using namespace BPackageKit::BManager::BPrivate;
8804c9d578SStephan Aßmus 
8904c9d578SStephan Aßmus 
9004c9d578SStephan Aßmus typedef std::map<BString, PackageInfoRef> PackageInfoMap;
9104c9d578SStephan Aßmus 
9204c9d578SStephan Aßmus 
9304c9d578SStephan Aßmus struct RefreshWorkerParameters {
9404c9d578SStephan Aßmus 	MainWindow* window;
9504c9d578SStephan Aßmus 	bool forceRefresh;
9604c9d578SStephan Aßmus 
9704c9d578SStephan Aßmus 	RefreshWorkerParameters(MainWindow* window, bool forceRefresh)
9804c9d578SStephan Aßmus 		:
9904c9d578SStephan Aßmus 		window(window),
10004c9d578SStephan Aßmus 		forceRefresh(forceRefresh)
10104c9d578SStephan Aßmus 	{
10204c9d578SStephan Aßmus 	}
10304c9d578SStephan Aßmus };
10404c9d578SStephan Aßmus 
10504c9d578SStephan Aßmus 
10689b16bb4SAndrew Lindesay class MainWindowModelListener : public ModelListener {
1078f03a0f9SStephan Aßmus public:
10889b16bb4SAndrew Lindesay 	MainWindowModelListener(const BMessenger& messenger)
1098f03a0f9SStephan Aßmus 		:
1108f03a0f9SStephan Aßmus 		fMessenger(messenger)
1118f03a0f9SStephan Aßmus 	{
1128f03a0f9SStephan Aßmus 	}
1138f03a0f9SStephan Aßmus 
1148f03a0f9SStephan Aßmus 	virtual void AuthorizationChanged()
1158f03a0f9SStephan Aßmus 	{
1168f03a0f9SStephan Aßmus 		if (fMessenger.IsValid())
1178f03a0f9SStephan Aßmus 			fMessenger.SendMessage(MSG_AUTHORIZATION_CHANGED);
1188f03a0f9SStephan Aßmus 	}
1198f03a0f9SStephan Aßmus 
12089b16bb4SAndrew Lindesay 	virtual void CategoryListChanged()
12189b16bb4SAndrew Lindesay 	{
12289b16bb4SAndrew Lindesay 		if (fMessenger.IsValid())
12389b16bb4SAndrew Lindesay 			fMessenger.SendMessage(MSG_CATEGORIES_LIST_CHANGED);
12489b16bb4SAndrew Lindesay 	}
12589b16bb4SAndrew Lindesay 
1268f03a0f9SStephan Aßmus private:
1278f03a0f9SStephan Aßmus 	BMessenger	fMessenger;
1288f03a0f9SStephan Aßmus };
1298f03a0f9SStephan Aßmus 
1308f03a0f9SStephan Aßmus 
131f7c2983eSAxel Dörfler MainWindow::MainWindow(const BMessage& settings)
13204c9d578SStephan Aßmus 	:
133f7c2983eSAxel Dörfler 	BWindow(BRect(50, 50, 650, 550), B_TRANSLATE_SYSTEM_NAME("HaikuDepot"),
13404c9d578SStephan Aßmus 		B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
13504c9d578SStephan Aßmus 		B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS),
136d5ef985eSStephan Aßmus 	fScreenshotWindow(NULL),
13795c7b018SAndrew Lindesay 	fShuttingDownWindow(NULL),
138e0a26dceSStephan Aßmus 	fUserMenu(NULL),
139e0a26dceSStephan Aßmus 	fLogInItem(NULL),
140e0a26dceSStephan Aßmus 	fLogOutItem(NULL),
141976cadf1SAndrew Lindesay 	fUsersUserUsageConditionsMenuItem(NULL),
14289b16bb4SAndrew Lindesay 	fModelListener(new MainWindowModelListener(BMessenger(this)), true),
14310cd325cSAndrew Lindesay 	fCoordinator(NULL),
14495c7b018SAndrew Lindesay 	fShouldCloseWhenNoProcessesToCoordinate(false),
1453369e03dSAndrew Lindesay 	fSinglePackageMode(false)
14604c9d578SStephan Aßmus {
14710cd325cSAndrew Lindesay 	if ((fCoordinatorRunningSem = create_sem(1, "ProcessCoordinatorSem")) < B_OK)
14810cd325cSAndrew Lindesay 		debugger("unable to create the process coordinator semaphore");
14910cd325cSAndrew Lindesay 
150cbadcae1SHumdinger 	BMenuBar* menuBar = new BMenuBar("Main Menu");
15104c9d578SStephan Aßmus 	_BuildMenu(menuBar);
15204c9d578SStephan Aßmus 
153cbadcae1SHumdinger 	BMenuBar* userMenuBar = new BMenuBar("User Menu");
154e0a26dceSStephan Aßmus 	_BuildUserMenu(userMenuBar);
155e0a26dceSStephan Aßmus 	set_small_font(userMenuBar);
156e0a26dceSStephan Aßmus 	userMenuBar->SetExplicitMaxSize(BSize(B_SIZE_UNSET,
157e0a26dceSStephan Aßmus 		menuBar->MaxSize().height));
158e0a26dceSStephan Aßmus 
15904c9d578SStephan Aßmus 	fFilterView = new FilterView();
160f0e491d3SAndrew Lindesay 	fFeaturedPackagesView = new FeaturedPackagesView(fModel);
161f0e491d3SAndrew Lindesay 	fPackageListView = new PackageListView(&fModel);
162f0e491d3SAndrew Lindesay 	fPackageInfoView = new PackageInfoView(&fModel, this);
16304c9d578SStephan Aßmus 
16404c9d578SStephan Aßmus 	fSplitView = new BSplitView(B_VERTICAL, 5.0f);
16504c9d578SStephan Aßmus 
166125d42d9SJulian Harnath 	fWorkStatusView = new WorkStatusView("work status");
167125d42d9SJulian Harnath 	fPackageListView->AttachWorkStatusView(fWorkStatusView);
168125d42d9SJulian Harnath 
169e00a489bSAugustin Cavalier 	fListTabs = new TabView(BMessenger(this),
170ccf707d0SAndrew Lindesay 		BMessage(MSG_CHANGE_PACKAGE_LIST_VIEW_MODE), "list tabs");
171e00a489bSAugustin Cavalier 	fListTabs->AddTab(fFeaturedPackagesView);
172e00a489bSAugustin Cavalier 	fListTabs->AddTab(fPackageListView);
1734b930ccaSStephan Aßmus 
17404c9d578SStephan Aßmus 	BLayoutBuilder::Group<>(this, B_VERTICAL, 0.0f)
175e0a26dceSStephan Aßmus 		.AddGroup(B_HORIZONTAL, 0.0f)
176e0a26dceSStephan Aßmus 			.Add(menuBar, 1.0f)
177e0a26dceSStephan Aßmus 			.Add(userMenuBar, 0.0f)
178e0a26dceSStephan Aßmus 		.End()
17904c9d578SStephan Aßmus 		.Add(fFilterView)
18004c9d578SStephan Aßmus 		.AddSplit(fSplitView)
18104c9d578SStephan Aßmus 			.AddGroup(B_VERTICAL)
182e00a489bSAugustin Cavalier 				.Add(fListTabs)
18304c9d578SStephan Aßmus 				.SetInsets(
18404c9d578SStephan Aßmus 					B_USE_DEFAULT_SPACING, 0.0f,
18504c9d578SStephan Aßmus 					B_USE_DEFAULT_SPACING, 0.0f)
18604c9d578SStephan Aßmus 			.End()
18704c9d578SStephan Aßmus 			.Add(fPackageInfoView)
18804c9d578SStephan Aßmus 		.End()
189125d42d9SJulian Harnath 		.Add(fWorkStatusView)
19004c9d578SStephan Aßmus 	;
19104c9d578SStephan Aßmus 
19204c9d578SStephan Aßmus 	fSplitView->SetCollapsible(0, false);
19304c9d578SStephan Aßmus 	fSplitView->SetCollapsible(1, false);
19404c9d578SStephan Aßmus 
1958f03a0f9SStephan Aßmus 	fModel.AddListener(fModelListener);
1968f03a0f9SStephan Aßmus 
19704c9d578SStephan Aßmus 	BMessage columnSettings;
19804c9d578SStephan Aßmus 	if (settings.FindMessage("column settings", &columnSettings) == B_OK)
19904c9d578SStephan Aßmus 		fPackageListView->LoadState(&columnSettings);
20004c9d578SStephan Aßmus 
201ccf707d0SAndrew Lindesay 	_RestoreModelSettings(settings);
202133ebab6SAndrew Lindesay 	_MaybePromptCanShareAnonymousUserData(settings);
20304c9d578SStephan Aßmus 
204ccf707d0SAndrew Lindesay 	if (fModel.PackageListViewMode() == PROMINENT)
205ccf707d0SAndrew Lindesay 		fListTabs->Select(TAB_PROMINENT_PACKAGES);
2062997e05bSStephan Aßmus 	else
207ccf707d0SAndrew Lindesay 		fListTabs->Select(TAB_ALL_PACKAGES);
2082997e05bSStephan Aßmus 
209d2d4866dSAndrew Lindesay 	_RestoreNickname(settings);
21010cd325cSAndrew Lindesay 	_UpdateAuthorization();
211f7c2983eSAxel Dörfler 	_RestoreWindowFrame(settings);
212f7c2983eSAxel Dörfler 
2138f03a0f9SStephan Aßmus 	// start worker threads
21404c9d578SStephan Aßmus 	BPackageRoster().StartWatching(this,
21504c9d578SStephan Aßmus 		B_WATCH_PACKAGE_INSTALLATION_LOCATIONS);
21604c9d578SStephan Aßmus 
21763975654SStephan Aßmus 	_InitWorkerThreads();
2189883929bSAndrew Lindesay 	_AdoptModel();
2199883929bSAndrew Lindesay 	_StartBulkLoad();
22004c9d578SStephan Aßmus }
22104c9d578SStephan Aßmus 
22204c9d578SStephan Aßmus 
223afe7affbSAndrew Lindesay MainWindow::MainWindow(const BMessage& settings, PackageInfoRef& package)
2246d519fd1SStephan Aßmus 	:
225f7c2983eSAxel Dörfler 	BWindow(BRect(50, 50, 650, 350), B_TRANSLATE_SYSTEM_NAME("HaikuDepot"),
2266d519fd1SStephan Aßmus 		B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
2276d519fd1SStephan Aßmus 		B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS),
2289883929bSAndrew Lindesay 	fFeaturedPackagesView(NULL),
2299883929bSAndrew Lindesay 	fPackageListView(NULL),
230d78bfd8dSJulian Harnath 	fWorkStatusView(NULL),
231d5ef985eSStephan Aßmus 	fScreenshotWindow(NULL),
23295c7b018SAndrew Lindesay 	fShuttingDownWindow(NULL),
233e0a26dceSStephan Aßmus 	fUserMenu(NULL),
234e0a26dceSStephan Aßmus 	fLogInItem(NULL),
2356d519fd1SStephan Aßmus 	fLogOutItem(NULL),
236976cadf1SAndrew Lindesay 	fUsersUserUsageConditionsMenuItem(NULL),
23789b16bb4SAndrew Lindesay 	fModelListener(new MainWindowModelListener(BMessenger(this)), true),
23810cd325cSAndrew Lindesay 	fCoordinator(NULL),
23995c7b018SAndrew Lindesay 	fShouldCloseWhenNoProcessesToCoordinate(false),
2403369e03dSAndrew Lindesay 	fSinglePackageMode(true)
2416d519fd1SStephan Aßmus {
24210cd325cSAndrew Lindesay 	if ((fCoordinatorRunningSem = create_sem(1, "ProcessCoordinatorSem")) < B_OK)
24310cd325cSAndrew Lindesay 		debugger("unable to create the process coordinator semaphore");
24410cd325cSAndrew Lindesay 
2456d519fd1SStephan Aßmus 	fFilterView = new FilterView();
246f0e491d3SAndrew Lindesay 	fPackageInfoView = new PackageInfoView(&fModel, this);
24787016f8fSAndrew Lindesay 	fWorkStatusView = new WorkStatusView("work status");
2486d519fd1SStephan Aßmus 
2496d519fd1SStephan Aßmus 	BLayoutBuilder::Group<>(this, B_VERTICAL)
2506d519fd1SStephan Aßmus 		.Add(fPackageInfoView)
25187016f8fSAndrew Lindesay 		.Add(fWorkStatusView)
2526d519fd1SStephan Aßmus 		.SetInsets(0, B_USE_WINDOW_INSETS, 0, 0)
2536d519fd1SStephan Aßmus 	;
2546d519fd1SStephan Aßmus 
2556d519fd1SStephan Aßmus 	fModel.AddListener(fModelListener);
2566d519fd1SStephan Aßmus 
257afe7affbSAndrew Lindesay 	// add the single package into the model so that any internal
258afe7affbSAndrew Lindesay 	// business logic is able to find the package.
259afe7affbSAndrew Lindesay 	DepotInfoRef depot(new DepotInfo("single-pkg-depot"), true);
260afe7affbSAndrew Lindesay 	depot->AddPackage(package);
261afe7affbSAndrew Lindesay 	fModel.MergeOrAddDepot(depot);
262afe7affbSAndrew Lindesay 
2636d519fd1SStephan Aßmus 	// Restore settings
264d2d4866dSAndrew Lindesay 	_RestoreNickname(settings);
265ccf707d0SAndrew Lindesay 	_UpdateAuthorization();
266f7c2983eSAxel Dörfler 	_RestoreWindowFrame(settings);
2676d519fd1SStephan Aßmus 
2686d519fd1SStephan Aßmus 	fPackageInfoView->SetPackage(package);
26963975654SStephan Aßmus 
270afe7affbSAndrew Lindesay 	// start worker threads
271afe7affbSAndrew Lindesay 	BPackageRoster().StartWatching(this,
272afe7affbSAndrew Lindesay 		B_WATCH_PACKAGE_INSTALLATION_LOCATIONS);
273afe7affbSAndrew Lindesay 
27463975654SStephan Aßmus 	_InitWorkerThreads();
2756d519fd1SStephan Aßmus }
2766d519fd1SStephan Aßmus 
2776d519fd1SStephan Aßmus 
27804c9d578SStephan Aßmus MainWindow::~MainWindow()
27904c9d578SStephan Aßmus {
28010cd325cSAndrew Lindesay 	_SpinUntilProcessCoordinatorComplete();
28110cd325cSAndrew Lindesay 	delete_sem(fCoordinatorRunningSem);
28210cd325cSAndrew Lindesay 	fCoordinatorRunningSem = 0;
28310cd325cSAndrew Lindesay 
28404c9d578SStephan Aßmus 	BPackageRoster().StopWatching(this);
28504c9d578SStephan Aßmus 
28695c7b018SAndrew Lindesay 	if (fScreenshotWindow != NULL) {
28795c7b018SAndrew Lindesay 		if (fScreenshotWindow->Lock())
288d5ef985eSStephan Aßmus 			fScreenshotWindow->Quit();
28904c9d578SStephan Aßmus 	}
29004c9d578SStephan Aßmus 
29195c7b018SAndrew Lindesay 	if (fShuttingDownWindow != NULL) {
29295c7b018SAndrew Lindesay 		if (fShuttingDownWindow->Lock())
29395c7b018SAndrew Lindesay 			fShuttingDownWindow->Quit();
29495c7b018SAndrew Lindesay 	}
295d5562247SAugustin Cavalier 
296a3866854SAugustin Cavalier 	delete_sem(fPackageToPopulateSem);
297a3866854SAugustin Cavalier 	wait_for_thread(fPopulatePackageWorker, NULL);
298a3866854SAugustin Cavalier 
2994329a83fSAugustin Cavalier 	// We must clear the model early to release references.
300d5562247SAugustin Cavalier 	fModel.Clear();
30195c7b018SAndrew Lindesay }
30295c7b018SAndrew Lindesay 
30304c9d578SStephan Aßmus 
30404c9d578SStephan Aßmus bool
30504c9d578SStephan Aßmus MainWindow::QuitRequested()
30604c9d578SStephan Aßmus {
30704c9d578SStephan Aßmus 
30810cd325cSAndrew Lindesay 	_StopProcessCoordinators();
3093369e03dSAndrew Lindesay 
31095c7b018SAndrew Lindesay 	// If there are any processes in flight we need to be careful to make
31195c7b018SAndrew Lindesay 	// sure that they are cleanly completed before actually quitting.  By
31295c7b018SAndrew Lindesay 	// turning on the `fShouldCloseWhenNoProcessesToCoordinate` flag, when
31395c7b018SAndrew Lindesay 	// the process coordination has completed then it will detect this and
31495c7b018SAndrew Lindesay 	// quit again.
31595c7b018SAndrew Lindesay 
31695c7b018SAndrew Lindesay 	{
31795c7b018SAndrew Lindesay 		AutoLocker<BLocker> lock(&fCoordinatorLock);
31895c7b018SAndrew Lindesay 		fShouldCloseWhenNoProcessesToCoordinate = true;
31995c7b018SAndrew Lindesay 
32095c7b018SAndrew Lindesay 		if (fCoordinator.IsSet()) {
32195c7b018SAndrew Lindesay 			HDINFO("a coordinator is running --> will wait before quitting...");
32295c7b018SAndrew Lindesay 
32395c7b018SAndrew Lindesay 			if (fShuttingDownWindow == NULL)
32495c7b018SAndrew Lindesay 				fShuttingDownWindow = new ShuttingDownWindow(this);
32595c7b018SAndrew Lindesay 			fShuttingDownWindow->Show();
32695c7b018SAndrew Lindesay 
32795c7b018SAndrew Lindesay 			return false;
32895c7b018SAndrew Lindesay 		}
32995c7b018SAndrew Lindesay 	}
33095c7b018SAndrew Lindesay 
33195c7b018SAndrew Lindesay 	BMessage settings;
33295c7b018SAndrew Lindesay 	StoreSettings(settings);
33395c7b018SAndrew Lindesay 	BMessage message(MSG_MAIN_WINDOW_CLOSED);
33495c7b018SAndrew Lindesay 	message.AddMessage(KEY_WINDOW_SETTINGS, &settings);
33595c7b018SAndrew Lindesay 	be_app->PostMessage(&message);
33695c7b018SAndrew Lindesay 
33795c7b018SAndrew Lindesay 	if (fShuttingDownWindow != NULL) {
33895c7b018SAndrew Lindesay 		if (fShuttingDownWindow->Lock())
33995c7b018SAndrew Lindesay 			fShuttingDownWindow->Quit();
34095c7b018SAndrew Lindesay 		fShuttingDownWindow = NULL;
34195c7b018SAndrew Lindesay 	}
34295c7b018SAndrew Lindesay 
34304c9d578SStephan Aßmus 	return true;
34404c9d578SStephan Aßmus }
34504c9d578SStephan Aßmus 
34604c9d578SStephan Aßmus 
34704c9d578SStephan Aßmus void
34804c9d578SStephan Aßmus MainWindow::MessageReceived(BMessage* message)
34904c9d578SStephan Aßmus {
35004c9d578SStephan Aßmus 	switch (message->what) {
3513369e03dSAndrew Lindesay 		case MSG_BULK_LOAD_DONE:
35210cd325cSAndrew Lindesay 		{
35310cd325cSAndrew Lindesay 			int64 errorStatus64;
35410cd325cSAndrew Lindesay 			if (message->FindInt64(KEY_ERROR_STATUS, &errorStatus64) == B_OK)
35510cd325cSAndrew Lindesay 				_BulkLoadCompleteReceived((status_t) errorStatus64);
35610cd325cSAndrew Lindesay 			else
357fa5c8097SAndrew Lindesay 				HDERROR("expected [%s] value in message", KEY_ERROR_STATUS);
35804c9d578SStephan Aßmus 			break;
35910cd325cSAndrew Lindesay 		}
36004c9d578SStephan Aßmus 		case B_SIMPLE_DATA:
36104c9d578SStephan Aßmus 		case B_REFS_RECEIVED:
36204c9d578SStephan Aßmus 			// TODO: ?
36304c9d578SStephan Aßmus 			break;
36404c9d578SStephan Aßmus 
36504c9d578SStephan Aßmus 		case B_PACKAGE_UPDATE:
366f32d5c5cSAndrew Lindesay 			_HandleExternalPackageUpdateMessageReceived(message);
36704c9d578SStephan Aßmus 			break;
36804c9d578SStephan Aßmus 
3695bf2b6ebSBrian Hill 		case MSG_REFRESH_REPOS:
3703369e03dSAndrew Lindesay 			_StartBulkLoad(true);
3713369e03dSAndrew Lindesay 			break;
3723369e03dSAndrew Lindesay 
37310cd325cSAndrew Lindesay 		case MSG_WORK_STATUS_CLEAR:
37410cd325cSAndrew Lindesay 			_HandleWorkStatusClear();
37510cd325cSAndrew Lindesay 			break;
37610cd325cSAndrew Lindesay 
3773369e03dSAndrew Lindesay 		case MSG_WORK_STATUS_CHANGE:
3783369e03dSAndrew Lindesay 			_HandleWorkStatusChangeMessageReceived(message);
37904c9d578SStephan Aßmus 			break;
38004c9d578SStephan Aßmus 
3815bf2b6ebSBrian Hill 		case MSG_MANAGE_REPOS:
3825bf2b6ebSBrian Hill 			be_roster->Launch("application/x-vnd.Haiku-Repositories");
3835bf2b6ebSBrian Hill 			break;
3845bf2b6ebSBrian Hill 
385d144f952SAugustin Cavalier 		case MSG_SOFTWARE_UPDATER:
386d144f952SAugustin Cavalier 			be_roster->Launch("application/x-vnd.haiku-softwareupdater");
387d144f952SAugustin Cavalier 			break;
388d144f952SAugustin Cavalier 
38904c9d578SStephan Aßmus 		case MSG_LOG_IN:
3901bbda92dSStephan Aßmus 			_OpenLoginWindow(BMessage());
39104c9d578SStephan Aßmus 			break;
39204c9d578SStephan Aßmus 
393133ebab6SAndrew Lindesay 		case MSG_SETTINGS:
394133ebab6SAndrew Lindesay 			_OpenSettingsWindow();
395133ebab6SAndrew Lindesay 			break;
396133ebab6SAndrew Lindesay 
3978f03a0f9SStephan Aßmus 		case MSG_LOG_OUT:
398d2d4866dSAndrew Lindesay 			fModel.SetNickname("");
3998f03a0f9SStephan Aßmus 			break;
4008f03a0f9SStephan Aßmus 
40101339a54SAndrew Lindesay 		case MSG_VIEW_LATEST_USER_USAGE_CONDITIONS:
402d2d4866dSAndrew Lindesay 			_ViewUserUsageConditions(LATEST);
403d2d4866dSAndrew Lindesay 			break;
404d2d4866dSAndrew Lindesay 
405d2d4866dSAndrew Lindesay 		case MSG_VIEW_USERS_USER_USAGE_CONDITIONS:
406d2d4866dSAndrew Lindesay 			_ViewUserUsageConditions(USER);
40701339a54SAndrew Lindesay 			break;
40801339a54SAndrew Lindesay 
4098f03a0f9SStephan Aßmus 		case MSG_AUTHORIZATION_CHANGED:
41010cd325cSAndrew Lindesay 			_StartUserVerify();
4118f03a0f9SStephan Aßmus 			_UpdateAuthorization();
4128f03a0f9SStephan Aßmus 			break;
4138f03a0f9SStephan Aßmus 
41489b16bb4SAndrew Lindesay 		case MSG_CATEGORIES_LIST_CHANGED:
41589b16bb4SAndrew Lindesay 			fFilterView->AdoptModel(fModel);
41689b16bb4SAndrew Lindesay 			break;
41789b16bb4SAndrew Lindesay 
418ccf707d0SAndrew Lindesay 		case MSG_CHANGE_PACKAGE_LIST_VIEW_MODE:
419ccf707d0SAndrew Lindesay 			_HandleChangePackageListViewMode();
4204fade61fSStephan Aßmus 			break;
4214fade61fSStephan Aßmus 
422fdec4227SStephan Aßmus 		case MSG_SHOW_AVAILABLE_PACKAGES:
423fdec4227SStephan Aßmus 			{
424fdec4227SStephan Aßmus 				BAutolock locker(fModel.Lock());
425fdec4227SStephan Aßmus 				fModel.SetShowAvailablePackages(
426fdec4227SStephan Aßmus 					!fModel.ShowAvailablePackages());
427fdec4227SStephan Aßmus 			}
428fdec4227SStephan Aßmus 			_AdoptModel();
429fdec4227SStephan Aßmus 			break;
430fdec4227SStephan Aßmus 
431fdec4227SStephan Aßmus 		case MSG_SHOW_INSTALLED_PACKAGES:
432fdec4227SStephan Aßmus 			{
433fdec4227SStephan Aßmus 				BAutolock locker(fModel.Lock());
434fdec4227SStephan Aßmus 				fModel.SetShowInstalledPackages(
435fdec4227SStephan Aßmus 					!fModel.ShowInstalledPackages());
436fdec4227SStephan Aßmus 			}
437fdec4227SStephan Aßmus 			_AdoptModel();
438fdec4227SStephan Aßmus 			break;
439fdec4227SStephan Aßmus 
44004c9d578SStephan Aßmus 		case MSG_SHOW_SOURCE_PACKAGES:
44104c9d578SStephan Aßmus 			{
44204c9d578SStephan Aßmus 				BAutolock locker(fModel.Lock());
44304c9d578SStephan Aßmus 				fModel.SetShowSourcePackages(!fModel.ShowSourcePackages());
44404c9d578SStephan Aßmus 			}
44504c9d578SStephan Aßmus 			_AdoptModel();
44604c9d578SStephan Aßmus 			break;
44704c9d578SStephan Aßmus 
44804c9d578SStephan Aßmus 		case MSG_SHOW_DEVELOP_PACKAGES:
44904c9d578SStephan Aßmus 			{
45004c9d578SStephan Aßmus 				BAutolock locker(fModel.Lock());
45104c9d578SStephan Aßmus 				fModel.SetShowDevelopPackages(!fModel.ShowDevelopPackages());
45204c9d578SStephan Aßmus 			}
45304c9d578SStephan Aßmus 			_AdoptModel();
45404c9d578SStephan Aßmus 			break;
45504c9d578SStephan Aßmus 
456a9edb9bfSAndrew Lindesay 			// this may be triggered by, for example, a user rating being added
457a9edb9bfSAndrew Lindesay 			// or having been altered.
458a9edb9bfSAndrew Lindesay 		case MSG_SERVER_DATA_CHANGED:
459a9edb9bfSAndrew Lindesay 		{
460a9edb9bfSAndrew Lindesay 			BString name;
461a9edb9bfSAndrew Lindesay 			if (message->FindString("name", &name) == B_OK) {
462a9edb9bfSAndrew Lindesay 				BAutolock locker(fModel.Lock());
463a9edb9bfSAndrew Lindesay 				if (fPackageInfoView->Package()->Name() == name) {
464a9edb9bfSAndrew Lindesay 					_PopulatePackageAsync(true);
465a9edb9bfSAndrew Lindesay 				} else {
466f96d1f4dSAndrew Lindesay 					HDDEBUG("pkg [%s] is updated on the server, but is "
467f96d1f4dSAndrew Lindesay 						"not selected so will not be updated.",
468fa5c8097SAndrew Lindesay 						name.String());
469a9edb9bfSAndrew Lindesay 				}
470a9edb9bfSAndrew Lindesay 			}
471a9edb9bfSAndrew Lindesay         	break;
472a9edb9bfSAndrew Lindesay         }
473a9edb9bfSAndrew Lindesay 
47404c9d578SStephan Aßmus 		case MSG_PACKAGE_SELECTED:
47504c9d578SStephan Aßmus 		{
47672992391SStephan Aßmus 			BString name;
47772992391SStephan Aßmus 			if (message->FindString("name", &name) == B_OK) {
478c4199192SAndrew Lindesay 				PackageInfoRef package;
479c4199192SAndrew Lindesay 				{
48075ba9dbfSStephan Aßmus 					BAutolock locker(fModel.Lock());
481c4199192SAndrew Lindesay 					package = fModel.PackageForName(name);
482c4199192SAndrew Lindesay 				}
4836f07feadSAndrew Lindesay 				if (!package.IsSet() || name != package->Name())
484c4199192SAndrew Lindesay 					debugger("unable to find the named package");
485133ebab6SAndrew Lindesay 				else {
48604c9d578SStephan Aßmus 					_AdoptPackage(package);
487133ebab6SAndrew Lindesay 					_IncrementViewCounter(package);
488133ebab6SAndrew Lindesay 				}
48904c9d578SStephan Aßmus 			} else {
49004c9d578SStephan Aßmus 				_ClearPackage();
49104c9d578SStephan Aßmus 			}
49204c9d578SStephan Aßmus 			break;
49304c9d578SStephan Aßmus 		}
49404c9d578SStephan Aßmus 
49504c9d578SStephan Aßmus 		case MSG_CATEGORY_SELECTED:
49604c9d578SStephan Aßmus 		{
49789b16bb4SAndrew Lindesay 			BString code;
49889b16bb4SAndrew Lindesay 			if (message->FindString("code", &code) != B_OK)
49989b16bb4SAndrew Lindesay 				code = "";
50004c9d578SStephan Aßmus 			{
50104c9d578SStephan Aßmus 				BAutolock locker(fModel.Lock());
50289b16bb4SAndrew Lindesay 				fModel.SetCategory(code);
50304c9d578SStephan Aßmus 			}
50404c9d578SStephan Aßmus 			_AdoptModel();
50504c9d578SStephan Aßmus 			break;
50604c9d578SStephan Aßmus 		}
50704c9d578SStephan Aßmus 
50804c9d578SStephan Aßmus 		case MSG_DEPOT_SELECTED:
50904c9d578SStephan Aßmus 		{
51004c9d578SStephan Aßmus 			BString name;
51104c9d578SStephan Aßmus 			if (message->FindString("name", &name) != B_OK)
51204c9d578SStephan Aßmus 				name = "";
51304c9d578SStephan Aßmus 			{
51404c9d578SStephan Aßmus 				BAutolock locker(fModel.Lock());
51504c9d578SStephan Aßmus 				fModel.SetDepot(name);
51604c9d578SStephan Aßmus 			}
51704c9d578SStephan Aßmus 			_AdoptModel();
518b965ce70SHumdinger 			_UpdateAvailableRepositories();
51904c9d578SStephan Aßmus 			break;
52004c9d578SStephan Aßmus 		}
52104c9d578SStephan Aßmus 
52204c9d578SStephan Aßmus 		case MSG_SEARCH_TERMS_MODIFIED:
52304c9d578SStephan Aßmus 		{
52404c9d578SStephan Aßmus 			// TODO: Do this with a delay!
52504c9d578SStephan Aßmus 			BString searchTerms;
52604c9d578SStephan Aßmus 			if (message->FindString("search terms", &searchTerms) != B_OK)
52704c9d578SStephan Aßmus 				searchTerms = "";
52804c9d578SStephan Aßmus 			{
52904c9d578SStephan Aßmus 				BAutolock locker(fModel.Lock());
53004c9d578SStephan Aßmus 				fModel.SetSearchTerms(searchTerms);
53104c9d578SStephan Aßmus 			}
53204c9d578SStephan Aßmus 			_AdoptModel();
53304c9d578SStephan Aßmus 			break;
53404c9d578SStephan Aßmus 		}
53504c9d578SStephan Aßmus 
536da651104SStephan Aßmus 		case MSG_PACKAGE_CHANGED:
53704c9d578SStephan Aßmus 		{
53804c9d578SStephan Aßmus 			PackageInfo* info;
53904c9d578SStephan Aßmus 			if (message->FindPointer("package", (void**)&info) == B_OK) {
54004c9d578SStephan Aßmus 				PackageInfoRef ref(info, true);
5410b69420bSAndrew Lindesay 				fFeaturedPackagesView->BeginAddRemove();
542c4199192SAndrew Lindesay 				_AddRemovePackageFromLists(ref);
5430b69420bSAndrew Lindesay 				fFeaturedPackagesView->EndAddRemove();
54410cd325cSAndrew Lindesay 			}
54504c9d578SStephan Aßmus 			break;
54604c9d578SStephan Aßmus 		}
54704c9d578SStephan Aßmus 
54804c9d578SStephan Aßmus 		case MSG_RATE_PACKAGE:
5491bbda92dSStephan Aßmus 			_RatePackage();
55004c9d578SStephan Aßmus 			break;
55104c9d578SStephan Aßmus 
552d5ef985eSStephan Aßmus 		case MSG_SHOW_SCREENSHOT:
553d5ef985eSStephan Aßmus 			_ShowScreenshot();
554d5ef985eSStephan Aßmus 			break;
555d5ef985eSStephan Aßmus 
556125d42d9SJulian Harnath 		case MSG_PACKAGE_WORKER_BUSY:
557125d42d9SJulian Harnath 		{
558125d42d9SJulian Harnath 			BString reason;
559125d42d9SJulian Harnath 			status_t status = message->FindString("reason", &reason);
560125d42d9SJulian Harnath 			if (status != B_OK)
561125d42d9SJulian Harnath 				break;
562125d42d9SJulian Harnath 			fWorkStatusView->SetBusy(reason);
563125d42d9SJulian Harnath 			break;
564125d42d9SJulian Harnath 		}
565125d42d9SJulian Harnath 
566125d42d9SJulian Harnath 		case MSG_PACKAGE_WORKER_IDLE:
567125d42d9SJulian Harnath 			fWorkStatusView->SetIdle();
568125d42d9SJulian Harnath 			break;
569125d42d9SJulian Harnath 
57010cd325cSAndrew Lindesay 		case MSG_USER_USAGE_CONDITIONS_NOT_LATEST:
57110cd325cSAndrew Lindesay 		{
57210cd325cSAndrew Lindesay 			BMessage userDetailMsg;
57310cd325cSAndrew Lindesay 			if (message->FindMessage("userDetail", &userDetailMsg) != B_OK) {
57410cd325cSAndrew Lindesay 				debugger("expected the [userDetail] data to be carried in the "
57510cd325cSAndrew Lindesay 					"message.");
57610cd325cSAndrew Lindesay 			}
57710cd325cSAndrew Lindesay 			UserDetail userDetail(&userDetailMsg);
57810cd325cSAndrew Lindesay 			_HandleUserUsageConditionsNotLatest(userDetail);
57910cd325cSAndrew Lindesay 			break;
58010cd325cSAndrew Lindesay 		}
58110cd325cSAndrew Lindesay 
58204c9d578SStephan Aßmus 		default:
58304c9d578SStephan Aßmus 			BWindow::MessageReceived(message);
58404c9d578SStephan Aßmus 			break;
58504c9d578SStephan Aßmus 	}
58604c9d578SStephan Aßmus }
58704c9d578SStephan Aßmus 
58804c9d578SStephan Aßmus 
589ccf707d0SAndrew Lindesay static const char*
590ccf707d0SAndrew Lindesay main_window_package_list_view_mode_str(package_list_view_mode mode)
591ccf707d0SAndrew Lindesay {
592ccf707d0SAndrew Lindesay 	if (mode == PROMINENT)
593ccf707d0SAndrew Lindesay 		return "PROMINENT";
594ccf707d0SAndrew Lindesay 	return "ALL";
595ccf707d0SAndrew Lindesay }
596ccf707d0SAndrew Lindesay 
597ccf707d0SAndrew Lindesay 
598ccf707d0SAndrew Lindesay static package_list_view_mode
599ccf707d0SAndrew Lindesay main_window_str_to_package_list_view_mode(const BString& str)
600ccf707d0SAndrew Lindesay {
601ccf707d0SAndrew Lindesay 	if (str == "PROMINENT")
602ccf707d0SAndrew Lindesay 		return PROMINENT;
603ccf707d0SAndrew Lindesay 	return ALL;
604ccf707d0SAndrew Lindesay }
605ccf707d0SAndrew Lindesay 
606ccf707d0SAndrew Lindesay 
60704c9d578SStephan Aßmus void
60804c9d578SStephan Aßmus MainWindow::StoreSettings(BMessage& settings) const
60904c9d578SStephan Aßmus {
610f7c2983eSAxel Dörfler 	settings.AddRect(_WindowFrameName(), Frame());
611f7c2983eSAxel Dörfler 	if (!fSinglePackageMode) {
61204c9d578SStephan Aßmus 		settings.AddRect("window frame", Frame());
61304c9d578SStephan Aßmus 
61404c9d578SStephan Aßmus 		BMessage columnSettings;
6159883929bSAndrew Lindesay 		if (fPackageListView != NULL)
61604c9d578SStephan Aßmus 			fPackageListView->SaveState(&columnSettings);
61704c9d578SStephan Aßmus 
61804c9d578SStephan Aßmus 		settings.AddMessage("column settings", &columnSettings);
61904c9d578SStephan Aßmus 
620133ebab6SAndrew Lindesay 		settings.AddString(SETTING_PACKAGE_LIST_VIEW_MODE,
621ccf707d0SAndrew Lindesay 			main_window_package_list_view_mode_str(
622ccf707d0SAndrew Lindesay 				fModel.PackageListViewMode()));
623133ebab6SAndrew Lindesay 		settings.AddBool(SETTING_SHOW_AVAILABLE_PACKAGES,
6242997e05bSStephan Aßmus 			fModel.ShowAvailablePackages());
625133ebab6SAndrew Lindesay 		settings.AddBool(SETTING_SHOW_INSTALLED_PACKAGES,
6262997e05bSStephan Aßmus 			fModel.ShowInstalledPackages());
627133ebab6SAndrew Lindesay 		settings.AddBool(SETTING_SHOW_DEVELOP_PACKAGES,
628133ebab6SAndrew Lindesay 			fModel.ShowDevelopPackages());
629133ebab6SAndrew Lindesay 		settings.AddBool(SETTING_SHOW_SOURCE_PACKAGES,
630133ebab6SAndrew Lindesay 			fModel.ShowSourcePackages());
631133ebab6SAndrew Lindesay 		settings.AddBool(SETTING_CAN_SHARE_ANONYMOUS_USER_DATA,
632133ebab6SAndrew Lindesay 			fModel.CanShareAnonymousUsageData());
6336d519fd1SStephan Aßmus 	}
6348f03a0f9SStephan Aßmus 
635d2d4866dSAndrew Lindesay 	settings.AddString("username", fModel.Nickname());
63604c9d578SStephan Aßmus }
63704c9d578SStephan Aßmus 
63804c9d578SStephan Aßmus 
63904c9d578SStephan Aßmus void
640a18f873fSAndrew Lindesay MainWindow::Consume(ProcessCoordinator *item)
641a18f873fSAndrew Lindesay {
642a18f873fSAndrew Lindesay 	_AddProcessCoordinator(item);
643a18f873fSAndrew Lindesay }
644a18f873fSAndrew Lindesay 
645a18f873fSAndrew Lindesay 
646a18f873fSAndrew Lindesay void
64704c9d578SStephan Aßmus MainWindow::PackageChanged(const PackageInfoEvent& event)
64804c9d578SStephan Aßmus {
649a9edb9bfSAndrew Lindesay 	uint32 watchedChanges = PKG_CHANGED_STATE | PKG_CHANGED_PROMINENCE;
650a9edb9bfSAndrew Lindesay 	if ((event.Changes() & watchedChanges) != 0) {
65104c9d578SStephan Aßmus 		PackageInfoRef ref(event.Package());
652da651104SStephan Aßmus 		BMessage message(MSG_PACKAGE_CHANGED);
65304c9d578SStephan Aßmus 		message.AddPointer("package", ref.Get());
65404c9d578SStephan Aßmus 		ref.Detach();
65504c9d578SStephan Aßmus 			// reference needs to be released by MessageReceived();
65604c9d578SStephan Aßmus 		PostMessage(&message);
65704c9d578SStephan Aßmus 	}
65804c9d578SStephan Aßmus }
65904c9d578SStephan Aßmus 
66004c9d578SStephan Aßmus 
66104c9d578SStephan Aßmus void
66204c9d578SStephan Aßmus MainWindow::_BuildMenu(BMenuBar* menuBar)
66304c9d578SStephan Aßmus {
6640b6928f1SHumdinger 	BMenu* menu = new BMenu(B_TRANSLATE_SYSTEM_NAME("HaikuDepot"));
6653369e03dSAndrew Lindesay 	fRefreshRepositoriesItem = new BMenuItem(
6663369e03dSAndrew Lindesay 		B_TRANSLATE("Refresh repositories"), new BMessage(MSG_REFRESH_REPOS));
6673369e03dSAndrew Lindesay 	menu->AddItem(fRefreshRepositoriesItem);
668d7f78130SHumdinger 	menu->AddItem(new BMenuItem(B_TRANSLATE("Manage repositories"
669d7f78130SHumdinger 		B_UTF8_ELLIPSIS), new BMessage(MSG_MANAGE_REPOS)));
670d144f952SAugustin Cavalier 	menu->AddItem(new BMenuItem(B_TRANSLATE("Check for updates"
671d144f952SAugustin Cavalier 		B_UTF8_ELLIPSIS), new BMessage(MSG_SOFTWARE_UPDATER)));
6720b6928f1SHumdinger 	menu->AddSeparatorItem();
6730b6928f1SHumdinger 	menu->AddItem(new BMenuItem(B_TRANSLATE("Settings" B_UTF8_ELLIPSIS),
674e1ae57abSJoachim Mairböck 		new BMessage(MSG_SETTINGS), ','));
6750b6928f1SHumdinger 	menu->AddItem(new BMenuItem(B_TRANSLATE("Quit"),
6760b6928f1SHumdinger 		new BMessage(B_QUIT_REQUESTED), 'Q'));
67704c9d578SStephan Aßmus 	menuBar->AddItem(menu);
67804c9d578SStephan Aßmus 
679b965ce70SHumdinger 	fRepositoryMenu = new BMenu(B_TRANSLATE("Repositories"));
680b965ce70SHumdinger 	menuBar->AddItem(fRepositoryMenu);
681b965ce70SHumdinger 
6824fade61fSStephan Aßmus 	menu = new BMenu(B_TRANSLATE("Show"));
6834fade61fSStephan Aßmus 
684fdec4227SStephan Aßmus 	fShowAvailablePackagesItem = new BMenuItem(
6854fade61fSStephan Aßmus 		B_TRANSLATE("Available packages"),
686fdec4227SStephan Aßmus 		new BMessage(MSG_SHOW_AVAILABLE_PACKAGES));
687fdec4227SStephan Aßmus 	menu->AddItem(fShowAvailablePackagesItem);
688fdec4227SStephan Aßmus 
689fdec4227SStephan Aßmus 	fShowInstalledPackagesItem = new BMenuItem(
6904fade61fSStephan Aßmus 		B_TRANSLATE("Installed packages"),
691fdec4227SStephan Aßmus 		new BMessage(MSG_SHOW_INSTALLED_PACKAGES));
692fdec4227SStephan Aßmus 	menu->AddItem(fShowInstalledPackagesItem);
693fdec4227SStephan Aßmus 
694fdec4227SStephan Aßmus 	menu->AddSeparatorItem();
695fdec4227SStephan Aßmus 
696fdec4227SStephan Aßmus 	fShowDevelopPackagesItem = new BMenuItem(
6974fade61fSStephan Aßmus 		B_TRANSLATE("Develop packages"),
698fdec4227SStephan Aßmus 		new BMessage(MSG_SHOW_DEVELOP_PACKAGES));
699fdec4227SStephan Aßmus 	menu->AddItem(fShowDevelopPackagesItem);
700fdec4227SStephan Aßmus 
701fdec4227SStephan Aßmus 	fShowSourcePackagesItem = new BMenuItem(
7024fade61fSStephan Aßmus 		B_TRANSLATE("Source packages"),
703fdec4227SStephan Aßmus 		new BMessage(MSG_SHOW_SOURCE_PACKAGES));
704fdec4227SStephan Aßmus 	menu->AddItem(fShowSourcePackagesItem);
705fdec4227SStephan Aßmus 
706fdec4227SStephan Aßmus 	menuBar->AddItem(menu);
70704c9d578SStephan Aßmus }
70804c9d578SStephan Aßmus 
70904c9d578SStephan Aßmus 
71004c9d578SStephan Aßmus void
711e0a26dceSStephan Aßmus MainWindow::_BuildUserMenu(BMenuBar* menuBar)
712e0a26dceSStephan Aßmus {
713e0a26dceSStephan Aßmus 	fUserMenu = new BMenu(B_TRANSLATE("Not logged in"));
714e0a26dceSStephan Aßmus 
715e0a26dceSStephan Aßmus 	fLogInItem = new BMenuItem(B_TRANSLATE("Log in" B_UTF8_ELLIPSIS),
716e0a26dceSStephan Aßmus 		new BMessage(MSG_LOG_IN));
717e0a26dceSStephan Aßmus 	fUserMenu->AddItem(fLogInItem);
718e0a26dceSStephan Aßmus 
719e0a26dceSStephan Aßmus 	fLogOutItem = new BMenuItem(B_TRANSLATE("Log out"),
720e0a26dceSStephan Aßmus 		new BMessage(MSG_LOG_OUT));
721e0a26dceSStephan Aßmus 	fUserMenu->AddItem(fLogOutItem);
722e0a26dceSStephan Aßmus 
7230c82f64bSAndrew Lindesay 	BMenuItem *latestUserUsageConditionsMenuItem =
7241448ced0SHumdinger 		new BMenuItem(B_TRANSLATE("View latest usage conditions"
72501339a54SAndrew Lindesay 			B_UTF8_ELLIPSIS),
72601339a54SAndrew Lindesay 			new BMessage(MSG_VIEW_LATEST_USER_USAGE_CONDITIONS));
7270c82f64bSAndrew Lindesay 	fUserMenu->AddItem(latestUserUsageConditionsMenuItem);
72801339a54SAndrew Lindesay 
729d2d4866dSAndrew Lindesay 	fUsersUserUsageConditionsMenuItem =
730d2d4866dSAndrew Lindesay 		new BMenuItem(B_TRANSLATE("View agreed usage conditions"
731d2d4866dSAndrew Lindesay 			B_UTF8_ELLIPSIS),
732d2d4866dSAndrew Lindesay 			new BMessage(MSG_VIEW_USERS_USER_USAGE_CONDITIONS));
733d2d4866dSAndrew Lindesay 	fUserMenu->AddItem(fUsersUserUsageConditionsMenuItem);
734d2d4866dSAndrew Lindesay 
735e0a26dceSStephan Aßmus 	menuBar->AddItem(fUserMenu);
736e0a26dceSStephan Aßmus }
737e0a26dceSStephan Aßmus 
738e0a26dceSStephan Aßmus 
739e0a26dceSStephan Aßmus void
740d2d4866dSAndrew Lindesay MainWindow::_RestoreNickname(const BMessage& settings)
741f7c2983eSAxel Dörfler {
742d2d4866dSAndrew Lindesay 	BString nickname;
743d2d4866dSAndrew Lindesay 	if (settings.FindString("username", &nickname) == B_OK
744d2d4866dSAndrew Lindesay 		&& nickname.Length() > 0) {
745d2d4866dSAndrew Lindesay 		fModel.SetNickname(nickname);
746f7c2983eSAxel Dörfler 	}
747f7c2983eSAxel Dörfler }
748f7c2983eSAxel Dörfler 
749f7c2983eSAxel Dörfler 
750f7c2983eSAxel Dörfler const char*
751f7c2983eSAxel Dörfler MainWindow::_WindowFrameName() const
752f7c2983eSAxel Dörfler {
753f7c2983eSAxel Dörfler 	if (fSinglePackageMode)
754f7c2983eSAxel Dörfler 		return "small window frame";
755f7c2983eSAxel Dörfler 
756f7c2983eSAxel Dörfler 	return "window frame";
757f7c2983eSAxel Dörfler }
758f7c2983eSAxel Dörfler 
759f7c2983eSAxel Dörfler 
760f7c2983eSAxel Dörfler void
761f7c2983eSAxel Dörfler MainWindow::_RestoreWindowFrame(const BMessage& settings)
762f7c2983eSAxel Dörfler {
763f7c2983eSAxel Dörfler 	BRect frame = Frame();
764f7c2983eSAxel Dörfler 
765f7c2983eSAxel Dörfler 	BRect windowFrame;
766f7c2983eSAxel Dörfler 	bool fromSettings = false;
767f7c2983eSAxel Dörfler 	if (settings.FindRect(_WindowFrameName(), &windowFrame) == B_OK) {
768f7c2983eSAxel Dörfler 		frame = windowFrame;
769f7c2983eSAxel Dörfler 		fromSettings = true;
770f7c2983eSAxel Dörfler 	} else if (!fSinglePackageMode) {
771f7c2983eSAxel Dörfler 		// Resize to occupy a certain screen size
772f7c2983eSAxel Dörfler 		BRect screenFrame = BScreen(this).Frame();
773f7c2983eSAxel Dörfler 		float width = frame.Width();
774f7c2983eSAxel Dörfler 		float height = frame.Height();
775f7c2983eSAxel Dörfler 		if (width < screenFrame.Width() * .666f
776f7c2983eSAxel Dörfler 			&& height < screenFrame.Height() * .666f) {
777f7c2983eSAxel Dörfler 			frame.bottom = frame.top + screenFrame.Height() * .666f;
778f7c2983eSAxel Dörfler 			frame.right = frame.left
779f7c2983eSAxel Dörfler 				+ std::min(screenFrame.Width() * .666f, height * 7 / 5);
780f7c2983eSAxel Dörfler 		}
781f7c2983eSAxel Dörfler 	}
782f7c2983eSAxel Dörfler 
783f7c2983eSAxel Dörfler 	MoveTo(frame.LeftTop());
784f7c2983eSAxel Dörfler 	ResizeTo(frame.Width(), frame.Height());
785f7c2983eSAxel Dörfler 
786f7c2983eSAxel Dörfler 	if (fromSettings)
7878e96ec34SAxel Dörfler 		MoveOnScreen();
788f7c2983eSAxel Dörfler 	else
789f7c2983eSAxel Dörfler 		CenterOnScreen();
790f7c2983eSAxel Dörfler }
791f7c2983eSAxel Dörfler 
792f7c2983eSAxel Dörfler 
793f7c2983eSAxel Dörfler void
794ccf707d0SAndrew Lindesay MainWindow::_RestoreModelSettings(const BMessage& settings)
795ccf707d0SAndrew Lindesay {
796ccf707d0SAndrew Lindesay 	BString packageListViewMode;
797133ebab6SAndrew Lindesay 	if (settings.FindString(SETTING_PACKAGE_LIST_VIEW_MODE,
798ccf707d0SAndrew Lindesay 			&packageListViewMode) == B_OK) {
799ccf707d0SAndrew Lindesay 		fModel.SetPackageListViewMode(
800ccf707d0SAndrew Lindesay 			main_window_str_to_package_list_view_mode(packageListViewMode));
801ccf707d0SAndrew Lindesay 	}
802ccf707d0SAndrew Lindesay 
803ccf707d0SAndrew Lindesay 	bool showOption;
804133ebab6SAndrew Lindesay 	if (settings.FindBool(SETTING_SHOW_AVAILABLE_PACKAGES, &showOption) == B_OK)
805ccf707d0SAndrew Lindesay 		fModel.SetShowAvailablePackages(showOption);
806133ebab6SAndrew Lindesay 	if (settings.FindBool(SETTING_SHOW_INSTALLED_PACKAGES, &showOption) == B_OK)
807ccf707d0SAndrew Lindesay 		fModel.SetShowInstalledPackages(showOption);
808133ebab6SAndrew Lindesay 	if (settings.FindBool(SETTING_SHOW_DEVELOP_PACKAGES, &showOption) == B_OK)
809ccf707d0SAndrew Lindesay 		fModel.SetShowDevelopPackages(showOption);
810133ebab6SAndrew Lindesay 	if (settings.FindBool(SETTING_SHOW_SOURCE_PACKAGES, &showOption) == B_OK)
811ccf707d0SAndrew Lindesay 		fModel.SetShowSourcePackages(showOption);
812133ebab6SAndrew Lindesay 	if (settings.FindBool(SETTING_CAN_SHARE_ANONYMOUS_USER_DATA,
813133ebab6SAndrew Lindesay 			&showOption) == B_OK) {
814133ebab6SAndrew Lindesay 		fModel.SetCanShareAnonymousUsageData(showOption);
815133ebab6SAndrew Lindesay 	}
816133ebab6SAndrew Lindesay }
817133ebab6SAndrew Lindesay 
818133ebab6SAndrew Lindesay 
819133ebab6SAndrew Lindesay void
820133ebab6SAndrew Lindesay MainWindow::_MaybePromptCanShareAnonymousUserData(const BMessage& settings)
821133ebab6SAndrew Lindesay {
822133ebab6SAndrew Lindesay 	bool showOption;
823133ebab6SAndrew Lindesay 	if (settings.FindBool(SETTING_CAN_SHARE_ANONYMOUS_USER_DATA,
824133ebab6SAndrew Lindesay 			&showOption) == B_NAME_NOT_FOUND) {
825133ebab6SAndrew Lindesay 		_PromptCanShareAnonymousUserData();
826133ebab6SAndrew Lindesay 	}
827133ebab6SAndrew Lindesay }
828133ebab6SAndrew Lindesay 
829133ebab6SAndrew Lindesay 
830133ebab6SAndrew Lindesay void
831133ebab6SAndrew Lindesay MainWindow::_PromptCanShareAnonymousUserData()
832133ebab6SAndrew Lindesay {
833133ebab6SAndrew Lindesay 	BAlert* alert = new(std::nothrow) BAlert(
834133ebab6SAndrew Lindesay 		B_TRANSLATE("Sending anonymous usage data"),
835133ebab6SAndrew Lindesay 		B_TRANSLATE("Would it be acceptable to send anonymous usage data to the"
836133ebab6SAndrew Lindesay 			" HaikuDepotServer system from this computer? You can change your"
837133ebab6SAndrew Lindesay 			" preference in the \"Settings\" window later."),
838133ebab6SAndrew Lindesay 		B_TRANSLATE("No"),
839133ebab6SAndrew Lindesay 		B_TRANSLATE("Yes"));
840133ebab6SAndrew Lindesay 
841133ebab6SAndrew Lindesay 	int32 result = alert->Go();
842133ebab6SAndrew Lindesay 	fModel.SetCanShareAnonymousUsageData(1 == result);
843ccf707d0SAndrew Lindesay }
844ccf707d0SAndrew Lindesay 
845ccf707d0SAndrew Lindesay 
846ccf707d0SAndrew Lindesay void
84763975654SStephan Aßmus MainWindow::_InitWorkerThreads()
84863975654SStephan Aßmus {
84963975654SStephan Aßmus 	fPackageToPopulateSem = create_sem(0, "PopulatePackage");
85063975654SStephan Aßmus 	if (fPackageToPopulateSem >= 0) {
85163975654SStephan Aßmus 		fPopulatePackageWorker = spawn_thread(&_PopulatePackageWorker,
85263975654SStephan Aßmus 			"Package Populator", B_NORMAL_PRIORITY, this);
85363975654SStephan Aßmus 		if (fPopulatePackageWorker >= 0)
85463975654SStephan Aßmus 			resume_thread(fPopulatePackageWorker);
85509f82905SStephan Aßmus 	} else
85609f82905SStephan Aßmus 		fPopulatePackageWorker = -1;
85763975654SStephan Aßmus }
85863975654SStephan Aßmus 
85963975654SStephan Aßmus 
86063975654SStephan Aßmus void
861c4199192SAndrew Lindesay MainWindow::_AdoptModelControls()
86204c9d578SStephan Aßmus {
8639883929bSAndrew Lindesay 	if (fSinglePackageMode)
8649883929bSAndrew Lindesay 		return;
8659883929bSAndrew Lindesay 
86604c9d578SStephan Aßmus 	BAutolock locker(fModel.Lock());
867fdec4227SStephan Aßmus 	fShowAvailablePackagesItem->SetMarked(fModel.ShowAvailablePackages());
868fdec4227SStephan Aßmus 	fShowInstalledPackagesItem->SetMarked(fModel.ShowInstalledPackages());
869fdec4227SStephan Aßmus 	fShowSourcePackagesItem->SetMarked(fModel.ShowSourcePackages());
870fdec4227SStephan Aßmus 	fShowDevelopPackagesItem->SetMarked(fModel.ShowDevelopPackages());
871da651104SStephan Aßmus 
872ccf707d0SAndrew Lindesay 	if (fModel.PackageListViewMode() == PROMINENT)
873ccf707d0SAndrew Lindesay 		fListTabs->Select(TAB_PROMINENT_PACKAGES);
8744fade61fSStephan Aßmus 	else
875ccf707d0SAndrew Lindesay 		fListTabs->Select(TAB_ALL_PACKAGES);
876b965ce70SHumdinger 
877b965ce70SHumdinger 	fFilterView->AdoptModel(fModel);
87804c9d578SStephan Aßmus }
87904c9d578SStephan Aßmus 
88004c9d578SStephan Aßmus 
88104c9d578SStephan Aßmus void
882c4199192SAndrew Lindesay MainWindow::_AdoptModel()
883c4199192SAndrew Lindesay {
884fa5c8097SAndrew Lindesay 	HDTRACE("adopting model to main window ui");
885c4199192SAndrew Lindesay 
886c4199192SAndrew Lindesay 	if (fSinglePackageMode)
887c4199192SAndrew Lindesay 		return;
888c4199192SAndrew Lindesay 
88905880d13SAndrew Lindesay 	std::vector<DepotInfoRef> depots = _CreateSnapshotOfDepots();
89005880d13SAndrew Lindesay 	std::vector<DepotInfoRef>::iterator it;
8910b69420bSAndrew Lindesay 
8920b69420bSAndrew Lindesay 	fFeaturedPackagesView->BeginAddRemove();
8930b69420bSAndrew Lindesay 
89405880d13SAndrew Lindesay 	for (it = depots.begin(); it != depots.end(); it++) {
89505880d13SAndrew Lindesay 		DepotInfoRef depotInfoRef = *it;
896d75b4d61SAndrew Lindesay 		for (int i = 0; i < depotInfoRef->CountPackages(); i++) {
897d75b4d61SAndrew Lindesay 			PackageInfoRef package = depotInfoRef->PackageAtIndex(i);
898d75b4d61SAndrew Lindesay 			_AddRemovePackageFromLists(package);
899d75b4d61SAndrew Lindesay 		}
900c4199192SAndrew Lindesay 	}
901c4199192SAndrew Lindesay 
9020b69420bSAndrew Lindesay 	fFeaturedPackagesView->EndAddRemove();
9030b69420bSAndrew Lindesay 
904c4199192SAndrew Lindesay 	_AdoptModelControls();
905c4199192SAndrew Lindesay }
906c4199192SAndrew Lindesay 
907c4199192SAndrew Lindesay 
908c4199192SAndrew Lindesay void
909c4199192SAndrew Lindesay MainWindow::_AddRemovePackageFromLists(const PackageInfoRef& package)
910c4199192SAndrew Lindesay {
911c4199192SAndrew Lindesay 	bool matches;
912c4199192SAndrew Lindesay 
913c4199192SAndrew Lindesay 	{
914c4199192SAndrew Lindesay 		AutoLocker<BLocker> modelLocker(fModel.Lock());
915c4199192SAndrew Lindesay 		matches = fModel.MatchesFilter(package);
916c4199192SAndrew Lindesay 	}
917c4199192SAndrew Lindesay 
918c4199192SAndrew Lindesay 	if (matches) {
919c4199192SAndrew Lindesay 		if (package->IsProminent())
920c4199192SAndrew Lindesay 			fFeaturedPackagesView->AddPackage(package);
921c4199192SAndrew Lindesay 		fPackageListView->AddPackage(package);
922c4199192SAndrew Lindesay 	} else {
923c4199192SAndrew Lindesay 		fFeaturedPackagesView->RemovePackage(package);
924c4199192SAndrew Lindesay 		fPackageListView->RemovePackage(package);
925c4199192SAndrew Lindesay 	}
926c4199192SAndrew Lindesay }
927c4199192SAndrew Lindesay 
928c4199192SAndrew Lindesay 
929c4199192SAndrew Lindesay void
930133ebab6SAndrew Lindesay MainWindow::_IncrementViewCounter(const PackageInfoRef& package)
931133ebab6SAndrew Lindesay {
932*467ffecdSAugustin Cavalier 	// Temporarily disabled, see tickets #16879 and #17689.
933*467ffecdSAugustin Cavalier #if 0
934133ebab6SAndrew Lindesay 	bool shouldIncrementViewCounter = false;
935133ebab6SAndrew Lindesay 
936133ebab6SAndrew Lindesay 	{
937133ebab6SAndrew Lindesay 		AutoLocker<BLocker> modelLocker(fModel.Lock());
938133ebab6SAndrew Lindesay 		bool canShareAnonymousUsageData = fModel.CanShareAnonymousUsageData();
939133ebab6SAndrew Lindesay 		if (canShareAnonymousUsageData && !package->Viewed()) {
940133ebab6SAndrew Lindesay 			package->SetViewed();
941133ebab6SAndrew Lindesay 			shouldIncrementViewCounter = true;
942133ebab6SAndrew Lindesay 		}
943133ebab6SAndrew Lindesay 	}
944133ebab6SAndrew Lindesay 
945133ebab6SAndrew Lindesay 	if (shouldIncrementViewCounter) {
946*467ffecdSAugustin Cavalier 		ProcessCoordinator* incrementViewCoordinator =
947133ebab6SAndrew Lindesay 			ProcessCoordinatorFactory::CreateIncrementViewCounter(
948133ebab6SAndrew Lindesay 				&fModel, package);
949*467ffecdSAugustin Cavalier 		_AddProcessCoordinator(incrementViewCoordinator);
950133ebab6SAndrew Lindesay 	}
951*467ffecdSAugustin Cavalier #endif
952133ebab6SAndrew Lindesay }
953133ebab6SAndrew Lindesay 
954133ebab6SAndrew Lindesay 
955133ebab6SAndrew Lindesay void
95604c9d578SStephan Aßmus MainWindow::_AdoptPackage(const PackageInfoRef& package)
95704c9d578SStephan Aßmus {
95875ba9dbfSStephan Aßmus 	{
95975ba9dbfSStephan Aßmus 		BAutolock locker(fModel.Lock());
96004c9d578SStephan Aßmus 		fPackageInfoView->SetPackage(package);
9611986ab9fSStephan Aßmus 
962664372abSStephan Aßmus 		if (fFeaturedPackagesView != NULL)
963664372abSStephan Aßmus 			fFeaturedPackagesView->SelectPackage(package);
9641986ab9fSStephan Aßmus 		if (fPackageListView != NULL)
9651986ab9fSStephan Aßmus 			fPackageListView->SelectPackage(package);
96675ba9dbfSStephan Aßmus 	}
96704c9d578SStephan Aßmus 
968a9edb9bfSAndrew Lindesay 	_PopulatePackageAsync(false);
96904c9d578SStephan Aßmus }
97004c9d578SStephan Aßmus 
97104c9d578SStephan Aßmus 
97204c9d578SStephan Aßmus void
97304c9d578SStephan Aßmus MainWindow::_ClearPackage()
97404c9d578SStephan Aßmus {
97504c9d578SStephan Aßmus 	fPackageInfoView->Clear();
97604c9d578SStephan Aßmus }
97704c9d578SStephan Aßmus 
97804c9d578SStephan Aßmus 
97904c9d578SStephan Aßmus void
9803369e03dSAndrew Lindesay MainWindow::_StartBulkLoad(bool force)
98104c9d578SStephan Aßmus {
982c4199192SAndrew Lindesay 	if (fFeaturedPackagesView != NULL)
983c4199192SAndrew Lindesay 		fFeaturedPackagesView->Clear();
984c4199192SAndrew Lindesay 	if (fPackageListView != NULL)
985c4199192SAndrew Lindesay 		fPackageListView->Clear();
986c4199192SAndrew Lindesay 	fPackageInfoView->Clear();
987c4199192SAndrew Lindesay 
98810cd325cSAndrew Lindesay 	fRefreshRepositoriesItem->SetEnabled(false);
98910cd325cSAndrew Lindesay 	ProcessCoordinator* bulkLoadCoordinator =
99010cd325cSAndrew Lindesay 		ProcessCoordinatorFactory::CreateBulkLoadCoordinator(
9913369e03dSAndrew Lindesay 			this,
9923369e03dSAndrew Lindesay 				// PackageInfoListener
9933369e03dSAndrew Lindesay 			&fModel, force);
99410cd325cSAndrew Lindesay 	_AddProcessCoordinator(bulkLoadCoordinator);
99504c9d578SStephan Aßmus }
99604c9d578SStephan Aßmus 
99704c9d578SStephan Aßmus 
99804c9d578SStephan Aßmus void
99910cd325cSAndrew Lindesay MainWindow::_BulkLoadCompleteReceived(status_t errorStatus)
100004c9d578SStephan Aßmus {
100110cd325cSAndrew Lindesay 	if (errorStatus != B_OK) {
10023369e03dSAndrew Lindesay 		AppUtils::NotifySimpleError(
10031448ced0SHumdinger 			B_TRANSLATE("Package update error"),
10043369e03dSAndrew Lindesay 			B_TRANSLATE("While updating package data, a problem has arisen "
10053369e03dSAndrew Lindesay 				"that may cause data to be outdated or missing from the "
10063369e03dSAndrew Lindesay 				"application's display. Additional details regarding this "
10073369e03dSAndrew Lindesay 				"problem may be able to be obtained from the application "
1008b21c9447SAndrew Lindesay 				"logs."
1009b21c9447SAndrew Lindesay 				ALERT_MSG_LOGS_USER_GUIDE));
101004c9d578SStephan Aßmus 	}
101110cd325cSAndrew Lindesay 
10123369e03dSAndrew Lindesay 	fRefreshRepositoriesItem->SetEnabled(true);
101310cd325cSAndrew Lindesay 	_AdoptModel();
101410cd325cSAndrew Lindesay 	_UpdateAvailableRepositories();
1015ccf707d0SAndrew Lindesay 
1016ccf707d0SAndrew Lindesay 	// if after loading everything in, it transpires that there are no
1017ccf707d0SAndrew Lindesay 	// featured packages then the featured packages should be disabled
1018ccf707d0SAndrew Lindesay 	// and the user should be switched to the "all packages" view so
1019ccf707d0SAndrew Lindesay 	// that they are not presented with a blank window!
1020ccf707d0SAndrew Lindesay 
1021ccf707d0SAndrew Lindesay 	bool hasProminentPackages = fModel.HasAnyProminentPackages();
1022ccf707d0SAndrew Lindesay 	fListTabs->TabAt(TAB_PROMINENT_PACKAGES)->SetEnabled(hasProminentPackages);
1023ccf707d0SAndrew Lindesay 	if (!hasProminentPackages
1024ccf707d0SAndrew Lindesay 			&& fListTabs->Selection() == TAB_PROMINENT_PACKAGES) {
1025ccf707d0SAndrew Lindesay 		fModel.SetPackageListViewMode(ALL);
1026ccf707d0SAndrew Lindesay 		fListTabs->Select(TAB_ALL_PACKAGES);
1027ccf707d0SAndrew Lindesay 	}
102804c9d578SStephan Aßmus }
102904c9d578SStephan Aßmus 
103004c9d578SStephan Aßmus 
10313369e03dSAndrew Lindesay void
103210cd325cSAndrew Lindesay MainWindow::_NotifyWorkStatusClear()
103304c9d578SStephan Aßmus {
103410cd325cSAndrew Lindesay 	BMessage message(MSG_WORK_STATUS_CLEAR);
103510cd325cSAndrew Lindesay 	this->PostMessage(&message, this);
103610cd325cSAndrew Lindesay }
103710cd325cSAndrew Lindesay 
103810cd325cSAndrew Lindesay 
103910cd325cSAndrew Lindesay void
104010cd325cSAndrew Lindesay MainWindow::_HandleWorkStatusClear()
104110cd325cSAndrew Lindesay {
104210cd325cSAndrew Lindesay 	fWorkStatusView->SetText("");
10433369e03dSAndrew Lindesay 	fWorkStatusView->SetIdle();
10443369e03dSAndrew Lindesay }
104504c9d578SStephan Aßmus 
104604c9d578SStephan Aßmus 
10473369e03dSAndrew Lindesay /*! Sends off a message to the Window so that it can change the status view
10483369e03dSAndrew Lindesay     on the front-end in the UI thread.
10493369e03dSAndrew Lindesay */
105004c9d578SStephan Aßmus 
10513369e03dSAndrew Lindesay void
10523369e03dSAndrew Lindesay MainWindow::_NotifyWorkStatusChange(const BString& text, float progress)
10533369e03dSAndrew Lindesay {
10543369e03dSAndrew Lindesay 	BMessage message(MSG_WORK_STATUS_CHANGE);
105504c9d578SStephan Aßmus 
10563369e03dSAndrew Lindesay 	if (!text.IsEmpty())
10573369e03dSAndrew Lindesay 		message.AddString(KEY_WORK_STATUS_TEXT, text);
10583369e03dSAndrew Lindesay 	message.AddFloat(KEY_WORK_STATUS_PROGRESS, progress);
105904c9d578SStephan Aßmus 
10603369e03dSAndrew Lindesay 	this->PostMessage(&message, this);
10613369e03dSAndrew Lindesay }
106204c9d578SStephan Aßmus 
10633369e03dSAndrew Lindesay 
1064f32d5c5cSAndrew Lindesay void
1065f32d5c5cSAndrew Lindesay MainWindow::_HandleExternalPackageUpdateMessageReceived(const BMessage* message)
1066f32d5c5cSAndrew Lindesay {
1067f32d5c5cSAndrew Lindesay 	BStringList addedPackageNames;
1068f32d5c5cSAndrew Lindesay 	BStringList removedPackageNames;
1069f32d5c5cSAndrew Lindesay 
1070f32d5c5cSAndrew Lindesay 	if (message->FindStrings("added package names",
1071f32d5c5cSAndrew Lindesay 			&addedPackageNames) == B_OK) {
1072f32d5c5cSAndrew Lindesay 		addedPackageNames.Sort();
10730ebb9177SAndrew Lindesay 		AutoLocker<BLocker> locker(fModel.Lock());
10740ebb9177SAndrew Lindesay 		fModel.SetStateForPackagesByName(addedPackageNames, ACTIVATED);
1075f32d5c5cSAndrew Lindesay 	}
1076f32d5c5cSAndrew Lindesay 	else
1077f32d5c5cSAndrew Lindesay 		HDINFO("no [added package names] key in inbound message");
1078f32d5c5cSAndrew Lindesay 
1079f32d5c5cSAndrew Lindesay 	if (message->FindStrings("removed package names",
1080f32d5c5cSAndrew Lindesay 			&removedPackageNames) == B_OK) {
1081f32d5c5cSAndrew Lindesay 		removedPackageNames.Sort();
10820ebb9177SAndrew Lindesay 		AutoLocker<BLocker> locker(fModel.Lock());
10830ebb9177SAndrew Lindesay 		fModel.SetStateForPackagesByName(addedPackageNames, UNINSTALLED);
1084f32d5c5cSAndrew Lindesay 	} else
1085f32d5c5cSAndrew Lindesay 		HDINFO("no [removed package names] key in inbound message");
1086f32d5c5cSAndrew Lindesay }
1087f32d5c5cSAndrew Lindesay 
1088f32d5c5cSAndrew Lindesay 
10893369e03dSAndrew Lindesay void
10903369e03dSAndrew Lindesay MainWindow::_HandleWorkStatusChangeMessageReceived(const BMessage* message)
10913369e03dSAndrew Lindesay {
10929883929bSAndrew Lindesay 	if (fWorkStatusView == NULL)
10939883929bSAndrew Lindesay 		return;
10949883929bSAndrew Lindesay 
10953369e03dSAndrew Lindesay 	BString text;
10963369e03dSAndrew Lindesay 	float progress;
10973369e03dSAndrew Lindesay 
10983369e03dSAndrew Lindesay 	if (message->FindString(KEY_WORK_STATUS_TEXT, &text) == B_OK)
10993369e03dSAndrew Lindesay 		fWorkStatusView->SetText(text);
11003369e03dSAndrew Lindesay 
1101a18f873fSAndrew Lindesay 	if (message->FindFloat(KEY_WORK_STATUS_PROGRESS, &progress) == B_OK) {
1102a18f873fSAndrew Lindesay 		if (progress < 0.0f)
1103a18f873fSAndrew Lindesay 			fWorkStatusView->SetBusy();
1104a18f873fSAndrew Lindesay 		else
11053369e03dSAndrew Lindesay 			fWorkStatusView->SetProgress(progress);
1106a18f873fSAndrew Lindesay 	} else {
1107a18f873fSAndrew Lindesay 		HDERROR("work status change missing progress on update message");
1108a18f873fSAndrew Lindesay 		fWorkStatusView->SetProgress(0.0f);
110904c9d578SStephan Aßmus 	}
111004c9d578SStephan Aßmus }
111104c9d578SStephan Aßmus 
111204c9d578SStephan Aßmus 
1113a9edb9bfSAndrew Lindesay /*! This method will cause the package to have its data refreshed from
1114a9edb9bfSAndrew Lindesay     the server application.  The refresh happens in the background; this method
1115a9edb9bfSAndrew Lindesay     is asynchronous.
1116a9edb9bfSAndrew Lindesay */
1117a9edb9bfSAndrew Lindesay 
1118a9edb9bfSAndrew Lindesay void
1119a9edb9bfSAndrew Lindesay MainWindow::_PopulatePackageAsync(bool forcePopulate)
1120a9edb9bfSAndrew Lindesay {
1121a9edb9bfSAndrew Lindesay 		// Trigger asynchronous package population from the web-app
1122a9edb9bfSAndrew Lindesay 	{
1123a9edb9bfSAndrew Lindesay 		AutoLocker<BLocker> lock(&fPackageToPopulateLock);
1124a9edb9bfSAndrew Lindesay 		fPackageToPopulate = fPackageInfoView->Package();
1125a9edb9bfSAndrew Lindesay 		fForcePopulatePackage = forcePopulate;
1126a9edb9bfSAndrew Lindesay 	}
1127a9edb9bfSAndrew Lindesay 	release_sem_etc(fPackageToPopulateSem, 1, 0);
1128a9edb9bfSAndrew Lindesay 
1129f96d1f4dSAndrew Lindesay 	HDDEBUG("pkg [%s] will be updated from the server.",
1130fa5c8097SAndrew Lindesay 		fPackageToPopulate->Name().String());
1131a9edb9bfSAndrew Lindesay }
1132a9edb9bfSAndrew Lindesay 
1133a9edb9bfSAndrew Lindesay 
1134a9edb9bfSAndrew Lindesay /*! This method will run in the background.  The thread will block until there
1135a9edb9bfSAndrew Lindesay     is a package to be updated.  When the thread unblocks, it will update the
1136a9edb9bfSAndrew Lindesay     package with information from the server.
1137a9edb9bfSAndrew Lindesay */
1138a9edb9bfSAndrew Lindesay 
113904c9d578SStephan Aßmus status_t
114004c9d578SStephan Aßmus MainWindow::_PopulatePackageWorker(void* arg)
114104c9d578SStephan Aßmus {
114204c9d578SStephan Aßmus 	MainWindow* window = reinterpret_cast<MainWindow*>(arg);
114304c9d578SStephan Aßmus 
114404c9d578SStephan Aßmus 	while (acquire_sem(window->fPackageToPopulateSem) == B_OK) {
114504c9d578SStephan Aßmus 		PackageInfoRef package;
1146a9edb9bfSAndrew Lindesay 		bool force;
114704c9d578SStephan Aßmus 		{
114804c9d578SStephan Aßmus 			AutoLocker<BLocker> lock(&window->fPackageToPopulateLock);
114904c9d578SStephan Aßmus 			package = window->fPackageToPopulate;
1150a9edb9bfSAndrew Lindesay 			force = window->fForcePopulatePackage;
115104c9d578SStephan Aßmus 		}
115204c9d578SStephan Aßmus 
1153779ab335SX512 		if (package.IsSet()) {
1154a9edb9bfSAndrew Lindesay 			uint32 populateFlags = Model::POPULATE_USER_RATINGS
1155a9edb9bfSAndrew Lindesay 				| Model::POPULATE_SCREEN_SHOTS
1156a9edb9bfSAndrew Lindesay 				| Model::POPULATE_CHANGELOG;
1157a9edb9bfSAndrew Lindesay 
1158a9edb9bfSAndrew Lindesay 			if (force)
1159a9edb9bfSAndrew Lindesay 				populateFlags |= Model::POPULATE_FORCE;
1160a9edb9bfSAndrew Lindesay 
1161a9edb9bfSAndrew Lindesay 			window->fModel.PopulatePackage(package, populateFlags);
1162a9edb9bfSAndrew Lindesay 
1163fa5c8097SAndrew Lindesay 			HDDEBUG("populating package [%s]", package->Name().String());
116404c9d578SStephan Aßmus 		}
116504c9d578SStephan Aßmus 	}
116604c9d578SStephan Aßmus 
116704c9d578SStephan Aßmus 	return 0;
116804c9d578SStephan Aßmus }
116904c9d578SStephan Aßmus 
117004c9d578SStephan Aßmus 
117104c9d578SStephan Aßmus void
1172133ebab6SAndrew Lindesay MainWindow::_OpenSettingsWindow()
1173133ebab6SAndrew Lindesay {
1174133ebab6SAndrew Lindesay 	SettingsWindow* window = new SettingsWindow(this, &fModel);
1175133ebab6SAndrew Lindesay 	window->Show();
1176133ebab6SAndrew Lindesay }
1177133ebab6SAndrew Lindesay 
1178133ebab6SAndrew Lindesay 
1179133ebab6SAndrew Lindesay void
11801bbda92dSStephan Aßmus MainWindow::_OpenLoginWindow(const BMessage& onSuccessMessage)
118104c9d578SStephan Aßmus {
118204c9d578SStephan Aßmus 	UserLoginWindow* window = new UserLoginWindow(this,
118304c9d578SStephan Aßmus 		BRect(0, 0, 500, 400), fModel);
11841bbda92dSStephan Aßmus 
11851bbda92dSStephan Aßmus 	if (onSuccessMessage.what != 0)
11861bbda92dSStephan Aßmus 		window->SetOnSuccessMessage(BMessenger(this), onSuccessMessage);
11871bbda92dSStephan Aßmus 
118804c9d578SStephan Aßmus 	window->Show();
118904c9d578SStephan Aßmus }
119004c9d578SStephan Aßmus 
11918f03a0f9SStephan Aßmus 
11928f03a0f9SStephan Aßmus void
119310cd325cSAndrew Lindesay MainWindow::_StartUserVerify()
119410cd325cSAndrew Lindesay {
119510cd325cSAndrew Lindesay 	if (!fModel.Nickname().IsEmpty()) {
119610cd325cSAndrew Lindesay 		_AddProcessCoordinator(
119710cd325cSAndrew Lindesay 			ProcessCoordinatorFactory::CreateUserDetailVerifierCoordinator(
119810cd325cSAndrew Lindesay 				this,
119910cd325cSAndrew Lindesay 					// UserDetailVerifierListener
120010cd325cSAndrew Lindesay 				&fModel) );
120110cd325cSAndrew Lindesay 	}
120210cd325cSAndrew Lindesay }
120310cd325cSAndrew Lindesay 
120410cd325cSAndrew Lindesay 
120510cd325cSAndrew Lindesay void
12068f03a0f9SStephan Aßmus MainWindow::_UpdateAuthorization()
12078f03a0f9SStephan Aßmus {
1208d2d4866dSAndrew Lindesay 	BString nickname(fModel.Nickname());
1209d2d4866dSAndrew Lindesay 	bool hasUser = !nickname.IsEmpty();
1210e0a26dceSStephan Aßmus 
12116d519fd1SStephan Aßmus 	if (fLogOutItem != NULL)
1212e0a26dceSStephan Aßmus 		fLogOutItem->SetEnabled(hasUser);
1213d2d4866dSAndrew Lindesay 	if (fUsersUserUsageConditionsMenuItem != NULL)
1214d2d4866dSAndrew Lindesay 		fUsersUserUsageConditionsMenuItem->SetEnabled(hasUser);
1215e0a26dceSStephan Aßmus 	if (fLogInItem != NULL) {
1216e0a26dceSStephan Aßmus 		if (hasUser)
1217e0a26dceSStephan Aßmus 			fLogInItem->SetLabel(B_TRANSLATE("Switch account" B_UTF8_ELLIPSIS));
1218e0a26dceSStephan Aßmus 		else
1219e0a26dceSStephan Aßmus 			fLogInItem->SetLabel(B_TRANSLATE("Log in" B_UTF8_ELLIPSIS));
1220e0a26dceSStephan Aßmus 	}
1221e0a26dceSStephan Aßmus 
1222e0a26dceSStephan Aßmus 	if (fUserMenu != NULL) {
1223e0a26dceSStephan Aßmus 		BString label;
1224d2d4866dSAndrew Lindesay 		if (hasUser) {
1225e0a26dceSStephan Aßmus 			label = B_TRANSLATE("Logged in as %User%");
1226d2d4866dSAndrew Lindesay 			label.ReplaceAll("%User%", nickname);
1227d2d4866dSAndrew Lindesay 		} else {
1228d2d4866dSAndrew Lindesay 			label = B_TRANSLATE("Not logged in");
1229e0a26dceSStephan Aßmus 		}
1230e0a26dceSStephan Aßmus 		fUserMenu->Superitem()->SetLabel(label);
1231e0a26dceSStephan Aßmus 	}
12328f03a0f9SStephan Aßmus }
12331bbda92dSStephan Aßmus 
12341bbda92dSStephan Aßmus 
12351bbda92dSStephan Aßmus void
1236b965ce70SHumdinger MainWindow::_UpdateAvailableRepositories()
1237b965ce70SHumdinger {
1238b965ce70SHumdinger 	fRepositoryMenu->RemoveItems(0, fRepositoryMenu->CountItems(), true);
1239b965ce70SHumdinger 
1240b965ce70SHumdinger 	fRepositoryMenu->AddItem(new BMenuItem(B_TRANSLATE("All repositories"),
1241b965ce70SHumdinger 		new BMessage(MSG_DEPOT_SELECTED)));
1242b965ce70SHumdinger 
1243b965ce70SHumdinger 	fRepositoryMenu->AddItem(new BSeparatorItem());
1244b965ce70SHumdinger 
1245b965ce70SHumdinger 	bool foundSelectedDepot = false;
124605880d13SAndrew Lindesay 	std::vector<DepotInfoRef> depots = _CreateSnapshotOfDepots();
124705880d13SAndrew Lindesay 	std::vector<DepotInfoRef>::iterator it;
1248d13c3d89SAndrew Lindesay 
124905880d13SAndrew Lindesay 	for (it = depots.begin(); it != depots.end(); it++) {
125005880d13SAndrew Lindesay 		DepotInfoRef depot = *it;
125105880d13SAndrew Lindesay 
125205880d13SAndrew Lindesay 		if (depot->Name().Length() != 0) {
1253b965ce70SHumdinger 			BMessage* message = new BMessage(MSG_DEPOT_SELECTED);
125405880d13SAndrew Lindesay 			message->AddString("name", depot->Name());
125505880d13SAndrew Lindesay 			BMenuItem* item = new(std::nothrow) BMenuItem(depot->Name(), message);
125605880d13SAndrew Lindesay 
125705880d13SAndrew Lindesay 			if (item == NULL)
125805880d13SAndrew Lindesay 				HDFATAL("memory exhaustion");
125905880d13SAndrew Lindesay 
1260b965ce70SHumdinger 			fRepositoryMenu->AddItem(item);
1261b965ce70SHumdinger 
126205880d13SAndrew Lindesay 			if (depot->Name() == fModel.Depot()) {
1263b965ce70SHumdinger 				item->SetMarked(true);
1264b965ce70SHumdinger 				foundSelectedDepot = true;
1265b965ce70SHumdinger 			}
1266b965ce70SHumdinger 		}
1267d13c3d89SAndrew Lindesay 	}
1268b965ce70SHumdinger 
1269b965ce70SHumdinger 	if (!foundSelectedDepot)
1270b965ce70SHumdinger 		fRepositoryMenu->ItemAt(0)->SetMarked(true);
1271b965ce70SHumdinger }
1272b965ce70SHumdinger 
1273b965ce70SHumdinger 
1274a9edb9bfSAndrew Lindesay bool
1275a9edb9bfSAndrew Lindesay MainWindow::_SelectedPackageHasWebAppRepositoryCode()
1276a9edb9bfSAndrew Lindesay {
1277a9edb9bfSAndrew Lindesay 	const PackageInfoRef& package = fPackageInfoView->Package();
12786ab878c0SAndrew Lindesay 	const BString depotName = package->DepotName();
1279a9edb9bfSAndrew Lindesay 
12806ab878c0SAndrew Lindesay 	if (depotName.IsEmpty()) {
1281fa5c8097SAndrew Lindesay 		HDDEBUG("the package [%s] has no depot name", package->Name().String());
12826ab878c0SAndrew Lindesay 	} else {
12836ab878c0SAndrew Lindesay 		const DepotInfo* depot = fModel.DepotForName(depotName);
1284a9edb9bfSAndrew Lindesay 
12856ab878c0SAndrew Lindesay 		if (depot == NULL) {
1286f96d1f4dSAndrew Lindesay 			HDINFO("the depot [%s] was not able to be found",
1287fa5c8097SAndrew Lindesay 				depotName.String());
12886ab878c0SAndrew Lindesay 		} else {
12896ab878c0SAndrew Lindesay 			BString repositoryCode = depot->WebAppRepositoryCode();
1290a9edb9bfSAndrew Lindesay 
12916ab878c0SAndrew Lindesay 			if (repositoryCode.IsEmpty()) {
1292f96d1f4dSAndrew Lindesay 				HDINFO("the depot [%s] has no web app repository code",
1293fa5c8097SAndrew Lindesay 					depotName.String());
1294fa5c8097SAndrew Lindesay 			} else
12956ab878c0SAndrew Lindesay 				return true;
12966ab878c0SAndrew Lindesay 		}
12976ab878c0SAndrew Lindesay 	}
12986ab878c0SAndrew Lindesay 
12996ab878c0SAndrew Lindesay 	return false;
1300a9edb9bfSAndrew Lindesay }
1301a9edb9bfSAndrew Lindesay 
1302a9edb9bfSAndrew Lindesay 
1303b965ce70SHumdinger void
13041bbda92dSStephan Aßmus MainWindow::_RatePackage()
13051bbda92dSStephan Aßmus {
1306a9edb9bfSAndrew Lindesay 	if (!_SelectedPackageHasWebAppRepositoryCode()) {
1307a9edb9bfSAndrew Lindesay 		BAlert* alert = new(std::nothrow) BAlert(
1308cbadcae1SHumdinger 			B_TRANSLATE("Rating not possible"),
1309cbadcae1SHumdinger 			B_TRANSLATE("This package doesn't seem to be on the HaikuDepot "
1310cbadcae1SHumdinger 				"Server, so it's not possible to create a new rating "
1311cbadcae1SHumdinger 				"or edit an existing rating."),
1312a9edb9bfSAndrew Lindesay 			B_TRANSLATE("OK"));
1313a9edb9bfSAndrew Lindesay 		alert->Go();
1314a9edb9bfSAndrew Lindesay     	return;
1315a9edb9bfSAndrew Lindesay 	}
1316a9edb9bfSAndrew Lindesay 
1317d2d4866dSAndrew Lindesay 	if (fModel.Nickname().IsEmpty()) {
13181bbda92dSStephan Aßmus 		BAlert* alert = new(std::nothrow) BAlert(
13191bbda92dSStephan Aßmus 			B_TRANSLATE("Not logged in"),
13201bbda92dSStephan Aßmus 			B_TRANSLATE("You need to be logged into an account before you "
13211bbda92dSStephan Aßmus 				"can rate packages."),
13221bbda92dSStephan Aßmus 			B_TRANSLATE("Cancel"),
13231bbda92dSStephan Aßmus 			B_TRANSLATE("Login or Create account"));
13241bbda92dSStephan Aßmus 
13251bbda92dSStephan Aßmus 		if (alert == NULL)
13261bbda92dSStephan Aßmus 			return;
13271bbda92dSStephan Aßmus 
13281bbda92dSStephan Aßmus 		int32 choice = alert->Go();
13291bbda92dSStephan Aßmus 		if (choice == 1)
13301bbda92dSStephan Aßmus 			_OpenLoginWindow(BMessage(MSG_RATE_PACKAGE));
13311bbda92dSStephan Aßmus 		return;
13321bbda92dSStephan Aßmus 	}
13331bbda92dSStephan Aßmus 
13341bbda92dSStephan Aßmus 	// TODO: Allow only one RatePackageWindow
13351bbda92dSStephan Aßmus 	// TODO: Mechanism for remembering the window frame
13361bbda92dSStephan Aßmus 	RatePackageWindow* window = new RatePackageWindow(this,
13371bbda92dSStephan Aßmus 		BRect(0, 0, 500, 400), fModel);
13381bbda92dSStephan Aßmus 	window->SetPackage(fPackageInfoView->Package());
13391bbda92dSStephan Aßmus 	window->Show();
13401bbda92dSStephan Aßmus }
1341d5ef985eSStephan Aßmus 
1342d5ef985eSStephan Aßmus 
1343d5ef985eSStephan Aßmus void
1344d5ef985eSStephan Aßmus MainWindow::_ShowScreenshot()
1345d5ef985eSStephan Aßmus {
1346d5ef985eSStephan Aßmus 	// TODO: Mechanism for remembering the window frame
1347d5ef985eSStephan Aßmus 	if (fScreenshotWindow == NULL)
1348d5ef985eSStephan Aßmus 		fScreenshotWindow = new ScreenshotWindow(this, BRect(0, 0, 500, 400));
1349d5ef985eSStephan Aßmus 
1350d5ef985eSStephan Aßmus 	if (fScreenshotWindow->LockWithTimeout(1000) != B_OK)
1351d5ef985eSStephan Aßmus 		return;
1352d5ef985eSStephan Aßmus 
1353d5ef985eSStephan Aßmus 	fScreenshotWindow->SetPackage(fPackageInfoView->Package());
1354d5ef985eSStephan Aßmus 
1355d5ef985eSStephan Aßmus 	if (fScreenshotWindow->IsHidden())
1356d5ef985eSStephan Aßmus 		fScreenshotWindow->Show();
1357d5ef985eSStephan Aßmus 	else
1358d5ef985eSStephan Aßmus 		fScreenshotWindow->Activate();
1359d5ef985eSStephan Aßmus 
1360d5ef985eSStephan Aßmus 	fScreenshotWindow->Unlock();
1361d5ef985eSStephan Aßmus }
136201339a54SAndrew Lindesay 
136301339a54SAndrew Lindesay 
136401339a54SAndrew Lindesay void
1365d2d4866dSAndrew Lindesay MainWindow::_ViewUserUsageConditions(
1366d2d4866dSAndrew Lindesay 	UserUsageConditionsSelectionMode mode)
136701339a54SAndrew Lindesay {
136801339a54SAndrew Lindesay 	UserUsageConditionsWindow* window = new UserUsageConditionsWindow(
1369d2d4866dSAndrew Lindesay 		fModel, mode);
137001339a54SAndrew Lindesay 	window->Show();
137101339a54SAndrew Lindesay }
137210cd325cSAndrew Lindesay 
137310cd325cSAndrew Lindesay 
137410cd325cSAndrew Lindesay void
137510cd325cSAndrew Lindesay MainWindow::UserCredentialsFailed()
137610cd325cSAndrew Lindesay {
137710cd325cSAndrew Lindesay 	BString message = B_TRANSLATE("The password previously "
137810cd325cSAndrew Lindesay 		"supplied for the user [%Nickname%] is not currently "
137910cd325cSAndrew Lindesay 		"valid. The user will be logged-out of this application "
138010cd325cSAndrew Lindesay 		"and you should login again with your updated password.");
138110cd325cSAndrew Lindesay 	message.ReplaceAll("%Nickname%", fModel.Nickname());
138210cd325cSAndrew Lindesay 
138310cd325cSAndrew Lindesay 	AppUtils::NotifySimpleError(B_TRANSLATE("Login issue"),
138410cd325cSAndrew Lindesay 		message);
138510cd325cSAndrew Lindesay 
138610cd325cSAndrew Lindesay 	{
138710cd325cSAndrew Lindesay 		AutoLocker<BLocker> locker(fModel.Lock());
138810cd325cSAndrew Lindesay 		fModel.SetNickname("");
138910cd325cSAndrew Lindesay 	}
139010cd325cSAndrew Lindesay }
139110cd325cSAndrew Lindesay 
139210cd325cSAndrew Lindesay 
139310cd325cSAndrew Lindesay /*! \brief This method is invoked from the UserDetailVerifierProcess on a
139410cd325cSAndrew Lindesay 		   background thread.  For this reason it lodges a message into itself
139510cd325cSAndrew Lindesay 		   which can then be handled on the main thread.
139610cd325cSAndrew Lindesay */
139710cd325cSAndrew Lindesay 
139810cd325cSAndrew Lindesay void
139910cd325cSAndrew Lindesay MainWindow::UserUsageConditionsNotLatest(const UserDetail& userDetail)
140010cd325cSAndrew Lindesay {
140110cd325cSAndrew Lindesay 	BMessage message(MSG_USER_USAGE_CONDITIONS_NOT_LATEST);
140210cd325cSAndrew Lindesay 	BMessage detailsMessage;
140310cd325cSAndrew Lindesay 	if (userDetail.Archive(&detailsMessage, true) != B_OK
140410cd325cSAndrew Lindesay 			|| message.AddMessage("userDetail", &detailsMessage) != B_OK) {
1405fa5c8097SAndrew Lindesay 		HDERROR("unable to archive the user detail into a message");
140610cd325cSAndrew Lindesay 	}
140710cd325cSAndrew Lindesay 	else
140810cd325cSAndrew Lindesay 		BMessenger(this).SendMessage(&message);
140910cd325cSAndrew Lindesay }
141010cd325cSAndrew Lindesay 
141110cd325cSAndrew Lindesay 
141210cd325cSAndrew Lindesay void
141310cd325cSAndrew Lindesay MainWindow::_HandleUserUsageConditionsNotLatest(
141410cd325cSAndrew Lindesay 	const UserDetail& userDetail)
141510cd325cSAndrew Lindesay {
141610cd325cSAndrew Lindesay 	ToLatestUserUsageConditionsWindow* window =
141710cd325cSAndrew Lindesay 		new ToLatestUserUsageConditionsWindow(this, fModel, userDetail);
141810cd325cSAndrew Lindesay 	window->Show();
141910cd325cSAndrew Lindesay }
142010cd325cSAndrew Lindesay 
142110cd325cSAndrew Lindesay 
142210cd325cSAndrew Lindesay void
142310cd325cSAndrew Lindesay MainWindow::_AddProcessCoordinator(ProcessCoordinator* item)
142410cd325cSAndrew Lindesay {
14257d7de135SAugustin Cavalier 	BReference<ProcessCoordinator> itemRef(item, true);
142610cd325cSAndrew Lindesay 	AutoLocker<BLocker> lock(&fCoordinatorLock);
142710cd325cSAndrew Lindesay 
142895c7b018SAndrew Lindesay 	if (fShouldCloseWhenNoProcessesToCoordinate) {
142995c7b018SAndrew Lindesay 		HDINFO("system shutting down --> new process coordinator [%s] rejected",
143095c7b018SAndrew Lindesay 			item->Name().String());
143195c7b018SAndrew Lindesay 		return;
143295c7b018SAndrew Lindesay 	}
143395c7b018SAndrew Lindesay 
1434a18f873fSAndrew Lindesay 	item->SetListener(this);
1435a18f873fSAndrew Lindesay 
1436779ab335SX512 	if (!fCoordinator.IsSet()) {
143710cd325cSAndrew Lindesay 		if (acquire_sem(fCoordinatorRunningSem) != B_OK)
143810cd325cSAndrew Lindesay 			debugger("unable to acquire the process coordinator sem");
1439f96d1f4dSAndrew Lindesay 		HDINFO("adding and starting a process coordinator [%s]",
1440fa5c8097SAndrew Lindesay 			item->Name().String());
14417d7de135SAugustin Cavalier 		fCoordinator = itemRef;
144210cd325cSAndrew Lindesay 		fCoordinator->Start();
14437d7de135SAugustin Cavalier 	} else {
1444f96d1f4dSAndrew Lindesay 		HDINFO("adding process coordinator [%s] to the queue",
144510cd325cSAndrew Lindesay 			item->Name().String());
144610cd325cSAndrew Lindesay 		fCoordinatorQueue.push(item);
144710cd325cSAndrew Lindesay 	}
144810cd325cSAndrew Lindesay }
144910cd325cSAndrew Lindesay 
145010cd325cSAndrew Lindesay 
145110cd325cSAndrew Lindesay void
145210cd325cSAndrew Lindesay MainWindow::_SpinUntilProcessCoordinatorComplete()
145310cd325cSAndrew Lindesay {
145410cd325cSAndrew Lindesay 	while (true) {
145510cd325cSAndrew Lindesay 		if (acquire_sem(fCoordinatorRunningSem) != B_OK)
145610cd325cSAndrew Lindesay 			debugger("unable to acquire the process coordinator sem");
145710cd325cSAndrew Lindesay 		if (release_sem(fCoordinatorRunningSem) != B_OK)
145810cd325cSAndrew Lindesay 			debugger("unable to release the process coordinator sem");
145910cd325cSAndrew Lindesay 		{
146010cd325cSAndrew Lindesay 			AutoLocker<BLocker> lock(&fCoordinatorLock);
1461779ab335SX512 			if (!fCoordinator.IsSet())
146210cd325cSAndrew Lindesay 				return;
146310cd325cSAndrew Lindesay 		}
146410cd325cSAndrew Lindesay 	}
146510cd325cSAndrew Lindesay }
146610cd325cSAndrew Lindesay 
146710cd325cSAndrew Lindesay 
146810cd325cSAndrew Lindesay void
146910cd325cSAndrew Lindesay MainWindow::_StopProcessCoordinators()
147010cd325cSAndrew Lindesay {
147195c7b018SAndrew Lindesay 	HDINFO("will stop all queued process coordinators");
147210cd325cSAndrew Lindesay 	AutoLocker<BLocker> lock(&fCoordinatorLock);
147310cd325cSAndrew Lindesay 
147410cd325cSAndrew Lindesay 	while (!fCoordinatorQueue.empty()) {
1475f96d1f4dSAndrew Lindesay 		BReference<ProcessCoordinator> processCoordinator
1476f96d1f4dSAndrew Lindesay 			= fCoordinatorQueue.front();
1477f96d1f4dSAndrew Lindesay 		HDINFO("will drop queued process coordinator [%s]",
1478fa5c8097SAndrew Lindesay 			processCoordinator->Name().String());
147910cd325cSAndrew Lindesay 		fCoordinatorQueue.pop();
148010cd325cSAndrew Lindesay 	}
148110cd325cSAndrew Lindesay 
148295c7b018SAndrew Lindesay 	if (fCoordinator.IsSet())
148395c7b018SAndrew Lindesay 		fCoordinator->RequestStop();
148410cd325cSAndrew Lindesay }
148510cd325cSAndrew Lindesay 
148610cd325cSAndrew Lindesay 
148710cd325cSAndrew Lindesay /*! This method is called when there is some change in the bulk load process
148810cd325cSAndrew Lindesay 	or other process coordinator.
148910cd325cSAndrew Lindesay 	A change may mean that a new process has started / stopped etc... or it
149010cd325cSAndrew Lindesay 	may mean that the entire coordinator has finished.
149110cd325cSAndrew Lindesay */
149210cd325cSAndrew Lindesay 
149310cd325cSAndrew Lindesay void
149410cd325cSAndrew Lindesay MainWindow::CoordinatorChanged(ProcessCoordinatorState& coordinatorState)
149510cd325cSAndrew Lindesay {
149610cd325cSAndrew Lindesay 	AutoLocker<BLocker> lock(&fCoordinatorLock);
149710cd325cSAndrew Lindesay 
1498f95ec23eSAndrew Lindesay 	if (fCoordinator.Get() == coordinatorState.Coordinator()) {
149910cd325cSAndrew Lindesay 		if (!coordinatorState.IsRunning()) {
150010cd325cSAndrew Lindesay 			if (release_sem(fCoordinatorRunningSem) != B_OK)
150110cd325cSAndrew Lindesay 				debugger("unable to release the process coordinator sem");
1502f96d1f4dSAndrew Lindesay 			HDINFO("process coordinator [%s] did complete",
1503fa5c8097SAndrew Lindesay 				fCoordinator->Name().String());
150410cd325cSAndrew Lindesay 			// complete the last one that just finished
150510cd325cSAndrew Lindesay 			BMessage* message = fCoordinator->Message();
150610cd325cSAndrew Lindesay 
150710cd325cSAndrew Lindesay 			if (message != NULL) {
150810cd325cSAndrew Lindesay 				BMessenger messenger(this);
150910cd325cSAndrew Lindesay 				message->AddInt64(KEY_ERROR_STATUS,
151010cd325cSAndrew Lindesay 					(int64) fCoordinator->ErrorStatus());
151110cd325cSAndrew Lindesay 				messenger.SendMessage(message);
151210cd325cSAndrew Lindesay 			}
151310cd325cSAndrew Lindesay 
1514f95ec23eSAndrew Lindesay 			fCoordinator = BReference<ProcessCoordinator>(NULL);
1515f95ec23eSAndrew Lindesay 				// will delete the old process coordinator if it is not used
1516f95ec23eSAndrew Lindesay 				// elsewhere.
151710cd325cSAndrew Lindesay 
151810cd325cSAndrew Lindesay 			// now schedule the next one.
151910cd325cSAndrew Lindesay 			if (!fCoordinatorQueue.empty()) {
152010cd325cSAndrew Lindesay 				if (acquire_sem(fCoordinatorRunningSem) != B_OK)
152110cd325cSAndrew Lindesay 					debugger("unable to acquire the process coordinator sem");
152210cd325cSAndrew Lindesay 				fCoordinator = fCoordinatorQueue.front();
1523f96d1f4dSAndrew Lindesay 				HDINFO("starting next process coordinator [%s]",
152410cd325cSAndrew Lindesay 					fCoordinator->Name().String());
152510cd325cSAndrew Lindesay 				fCoordinatorQueue.pop();
152610cd325cSAndrew Lindesay 				fCoordinator->Start();
152710cd325cSAndrew Lindesay 			}
152810cd325cSAndrew Lindesay 			else {
152910cd325cSAndrew Lindesay 				_NotifyWorkStatusClear();
153095c7b018SAndrew Lindesay 				if (fShouldCloseWhenNoProcessesToCoordinate) {
153195c7b018SAndrew Lindesay 					HDINFO("no more processes to coord --> will quit");
153295c7b018SAndrew Lindesay 					BMessage message(B_QUIT_REQUESTED);
153395c7b018SAndrew Lindesay 					PostMessage(&message);
153495c7b018SAndrew Lindesay 				}
153510cd325cSAndrew Lindesay 			}
153610cd325cSAndrew Lindesay 		}
153710cd325cSAndrew Lindesay 		else {
153810cd325cSAndrew Lindesay 			_NotifyWorkStatusChange(coordinatorState.Message(),
153910cd325cSAndrew Lindesay 				coordinatorState.Progress());
154010cd325cSAndrew Lindesay 				// show the progress to the user.
154110cd325cSAndrew Lindesay 		}
154295c7b018SAndrew Lindesay 	} else {
154395c7b018SAndrew Lindesay 		_NotifyWorkStatusClear();
1544fa5c8097SAndrew Lindesay 		HDINFO("! unknown process coordinator changed");
154510cd325cSAndrew Lindesay 	}
154695c7b018SAndrew Lindesay }
1547ccf707d0SAndrew Lindesay 
1548ccf707d0SAndrew Lindesay 
1549ccf707d0SAndrew Lindesay static package_list_view_mode
1550ccf707d0SAndrew Lindesay main_window_tab_to_package_list_view_mode(int32 tab)
1551ccf707d0SAndrew Lindesay {
1552ccf707d0SAndrew Lindesay 	if (tab == TAB_PROMINENT_PACKAGES)
1553ccf707d0SAndrew Lindesay 		return PROMINENT;
1554ccf707d0SAndrew Lindesay 	return ALL;
1555ccf707d0SAndrew Lindesay }
1556ccf707d0SAndrew Lindesay 
1557ccf707d0SAndrew Lindesay 
1558ccf707d0SAndrew Lindesay void
1559ccf707d0SAndrew Lindesay MainWindow::_HandleChangePackageListViewMode()
1560ccf707d0SAndrew Lindesay {
1561ccf707d0SAndrew Lindesay 	package_list_view_mode tabMode = main_window_tab_to_package_list_view_mode(
1562ccf707d0SAndrew Lindesay 		fListTabs->Selection());
1563ccf707d0SAndrew Lindesay 	package_list_view_mode modelMode = fModel.PackageListViewMode();
1564ccf707d0SAndrew Lindesay 
1565ccf707d0SAndrew Lindesay 	if (tabMode != modelMode) {
1566ccf707d0SAndrew Lindesay 		BAutolock locker(fModel.Lock());
1567ccf707d0SAndrew Lindesay 		fModel.SetPackageListViewMode(tabMode);
1568ccf707d0SAndrew Lindesay 	}
1569ccf707d0SAndrew Lindesay }
157005880d13SAndrew Lindesay 
157105880d13SAndrew Lindesay 
157205880d13SAndrew Lindesay std::vector<DepotInfoRef>
157305880d13SAndrew Lindesay MainWindow::_CreateSnapshotOfDepots()
157405880d13SAndrew Lindesay {
157505880d13SAndrew Lindesay 	std::vector<DepotInfoRef> result;
157605880d13SAndrew Lindesay 	BAutolock locker(fModel.Lock());
157705880d13SAndrew Lindesay 	int32 countDepots = fModel.CountDepots();
157805880d13SAndrew Lindesay 	for(int32 i = 0; i < countDepots; i++)
157905880d13SAndrew Lindesay 		result.push_back(fModel.DepotAtIndex(i));
158005880d13SAndrew Lindesay 	return result;
158105880d13SAndrew Lindesay }
1582