xref: /haiku/src/apps/haikudepot/ui/MainWindow.cpp (revision c078962803230aa4e37330a125accf955e4d8287)
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.
688af15cfSAndrew Lindesay  * Copyright 2016-2024, 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 #include "MainWindow.h"
1104c9d578SStephan Aßmus 
1204c9d578SStephan Aßmus #include <map>
133b17d8ddSAndrew Lindesay #include <vector>
1404c9d578SStephan Aßmus 
1504c9d578SStephan Aßmus #include <stdio.h>
1604c9d578SStephan Aßmus #include <Alert.h>
1704c9d578SStephan Aßmus #include <Autolock.h>
1804c9d578SStephan Aßmus #include <Application.h>
1904c9d578SStephan Aßmus #include <Button.h>
2004c9d578SStephan Aßmus #include <Catalog.h>
214b930ccaSStephan Aßmus #include <CardLayout.h>
2204c9d578SStephan Aßmus #include <LayoutBuilder.h>
2304c9d578SStephan Aßmus #include <MenuBar.h>
2404c9d578SStephan Aßmus #include <MenuItem.h>
2584674570SAndrew Lindesay #include <MessageRunner.h>
2604c9d578SStephan Aßmus #include <Messenger.h>
275bf2b6ebSBrian Hill #include <Roster.h>
28f7c2983eSAxel Dörfler #include <Screen.h>
2904c9d578SStephan Aßmus #include <ScrollView.h>
3004c9d578SStephan Aßmus #include <StringList.h>
310a9c9029SStephan Aßmus #include <StringView.h>
3204c9d578SStephan Aßmus #include <TabView.h>
3304c9d578SStephan Aßmus 
343369e03dSAndrew Lindesay #include "AppUtils.h"
3504c9d578SStephan Aßmus #include "AutoDeleter.h"
3604c9d578SStephan Aßmus #include "AutoLocker.h"
3704c9d578SStephan Aßmus #include "DecisionProvider.h"
384b930ccaSStephan Aßmus #include "FeaturedPackagesView.h"
3904c9d578SStephan Aßmus #include "FilterView.h"
40d668d227SAndrew Lindesay #include "LocaleUtils.h"
41d13c3d89SAndrew Lindesay #include "Logger.h"
4204c9d578SStephan Aßmus #include "PackageInfoView.h"
4304c9d578SStephan Aßmus #include "PackageListView.h"
4404c9d578SStephan Aßmus #include "PackageManager.h"
45*c0789628SAndrew Lindesay #include "PackageUtils.h"
463369e03dSAndrew Lindesay #include "ProcessCoordinator.h"
473369e03dSAndrew Lindesay #include "ProcessCoordinatorFactory.h"
4804c9d578SStephan Aßmus #include "RatePackageWindow.h"
494b3c808eSAndrew Lindesay #include "RatingUtils.h"
50d5ef985eSStephan Aßmus #include "ScreenshotWindow.h"
51133ebab6SAndrew Lindesay #include "SettingsWindow.h"
5295c7b018SAndrew Lindesay #include "ShuttingDownWindow.h"
5310cd325cSAndrew Lindesay #include "ToLatestUserUsageConditionsWindow.h"
5404c9d578SStephan Aßmus #include "UserLoginWindow.h"
5501339a54SAndrew Lindesay #include "UserUsageConditionsWindow.h"
56125d42d9SJulian Harnath #include "WorkStatusView.h"
57d668d227SAndrew Lindesay #include "support.h"
5804c9d578SStephan Aßmus 
5904c9d578SStephan Aßmus 
6004c9d578SStephan Aßmus #undef B_TRANSLATION_CONTEXT
6104c9d578SStephan Aßmus #define B_TRANSLATION_CONTEXT "MainWindow"
6204c9d578SStephan Aßmus 
6304c9d578SStephan Aßmus 
6404c9d578SStephan Aßmus enum {
655bf2b6ebSBrian Hill 	MSG_REFRESH_REPOS						= 'mrrp',
665bf2b6ebSBrian Hill 	MSG_MANAGE_REPOS						= 'mmrp',
67d144f952SAugustin Cavalier 	MSG_SOFTWARE_UPDATER					= 'mswu',
68133ebab6SAndrew Lindesay 	MSG_SETTINGS							= 'stgs',
6904c9d578SStephan Aßmus 	MSG_LOG_IN								= 'lgin',
708f03a0f9SStephan Aßmus 	MSG_AUTHORIZATION_CHANGED				= 'athc',
7189b16bb4SAndrew Lindesay 	MSG_CATEGORIES_LIST_CHANGED				= 'clic',
72da651104SStephan Aßmus 	MSG_PACKAGE_CHANGED						= 'pchd',
73409af934SAndrew Lindesay 	MSG_PROCESS_COORDINATOR_CHANGED			= 'pccd',
743369e03dSAndrew Lindesay 	MSG_WORK_STATUS_CHANGE					= 'wsch',
753369e03dSAndrew Lindesay 	MSG_WORK_STATUS_CLEAR					= 'wscl',
7684674570SAndrew Lindesay 	MSG_INCREMENT_VIEW_COUNTER				= 'icrv',
7788af15cfSAndrew Lindesay 	MSG_SCREENSHOT_CACHED					= 'ssca',
78fdec4227SStephan Aßmus 
79ccf707d0SAndrew Lindesay 	MSG_CHANGE_PACKAGE_LIST_VIEW_MODE		= 'cplm',
80fdec4227SStephan Aßmus 	MSG_SHOW_AVAILABLE_PACKAGES				= 'savl',
81fdec4227SStephan Aßmus 	MSG_SHOW_INSTALLED_PACKAGES				= 'sins',
8204c9d578SStephan Aßmus 	MSG_SHOW_SOURCE_PACKAGES				= 'ssrc',
8304c9d578SStephan Aßmus 	MSG_SHOW_DEVELOP_PACKAGES				= 'sdvl'
8404c9d578SStephan Aßmus };
8504c9d578SStephan Aßmus 
8610cd325cSAndrew Lindesay #define KEY_ERROR_STATUS				"errorStatus"
87ccf707d0SAndrew Lindesay 
8884674570SAndrew Lindesay const bigtime_t kIncrementViewCounterDelayMicros = 3 * 1000 * 1000;
8984674570SAndrew Lindesay 
90ccf707d0SAndrew Lindesay #define TAB_PROMINENT_PACKAGES	0
91ccf707d0SAndrew Lindesay #define TAB_ALL_PACKAGES		1
9204c9d578SStephan Aßmus 
9304c9d578SStephan Aßmus using namespace BPackageKit;
9404c9d578SStephan Aßmus using namespace BPackageKit::BManager::BPrivate;
9504c9d578SStephan Aßmus 
9604c9d578SStephan Aßmus 
9704c9d578SStephan Aßmus typedef std::map<BString, PackageInfoRef> PackageInfoMap;
9804c9d578SStephan Aßmus 
9904c9d578SStephan Aßmus 
10004c9d578SStephan Aßmus struct RefreshWorkerParameters {
10104c9d578SStephan Aßmus 	MainWindow* window;
10204c9d578SStephan Aßmus 	bool forceRefresh;
10304c9d578SStephan Aßmus 
RefreshWorkerParametersRefreshWorkerParameters10404c9d578SStephan Aßmus 	RefreshWorkerParameters(MainWindow* window, bool forceRefresh)
10504c9d578SStephan Aßmus 		:
10604c9d578SStephan Aßmus 		window(window),
10704c9d578SStephan Aßmus 		forceRefresh(forceRefresh)
10804c9d578SStephan Aßmus 	{
10904c9d578SStephan Aßmus 	}
11004c9d578SStephan Aßmus };
11104c9d578SStephan Aßmus 
11204c9d578SStephan Aßmus 
11389b16bb4SAndrew Lindesay class MainWindowModelListener : public ModelListener {
1148f03a0f9SStephan Aßmus public:
MainWindowModelListener(const BMessenger & messenger)11589b16bb4SAndrew Lindesay 	MainWindowModelListener(const BMessenger& messenger)
1168f03a0f9SStephan Aßmus 		:
1178f03a0f9SStephan Aßmus 		fMessenger(messenger)
1188f03a0f9SStephan Aßmus 	{
1198f03a0f9SStephan Aßmus 	}
1208f03a0f9SStephan Aßmus 
AuthorizationChanged()1218f03a0f9SStephan Aßmus 	virtual void AuthorizationChanged()
1228f03a0f9SStephan Aßmus 	{
1238f03a0f9SStephan Aßmus 		if (fMessenger.IsValid())
1248f03a0f9SStephan Aßmus 			fMessenger.SendMessage(MSG_AUTHORIZATION_CHANGED);
1258f03a0f9SStephan Aßmus 	}
1268f03a0f9SStephan Aßmus 
CategoryListChanged()12789b16bb4SAndrew Lindesay 	virtual void CategoryListChanged()
12889b16bb4SAndrew Lindesay 	{
12989b16bb4SAndrew Lindesay 		if (fMessenger.IsValid())
13089b16bb4SAndrew Lindesay 			fMessenger.SendMessage(MSG_CATEGORIES_LIST_CHANGED);
13189b16bb4SAndrew Lindesay 	}
13289b16bb4SAndrew Lindesay 
ScreenshotCached(const ScreenshotCoordinate & coordinate)13388af15cfSAndrew Lindesay 	virtual void ScreenshotCached(const ScreenshotCoordinate& coordinate)
13488af15cfSAndrew Lindesay 	{
13588af15cfSAndrew Lindesay 		if (fMessenger.IsValid()) {
13688af15cfSAndrew Lindesay 			BMessage message(MSG_SCREENSHOT_CACHED);
13788af15cfSAndrew Lindesay 			if (coordinate.Archive(&message) != B_OK)
13888af15cfSAndrew Lindesay 				debugger("unable to serialize a screenshot coordinate");
13988af15cfSAndrew Lindesay 			fMessenger.SendMessage(&message);
14088af15cfSAndrew Lindesay 		}
14188af15cfSAndrew Lindesay 	}
14288af15cfSAndrew Lindesay 
1438f03a0f9SStephan Aßmus private:
1448f03a0f9SStephan Aßmus 	BMessenger	fMessenger;
1458f03a0f9SStephan Aßmus };
1468f03a0f9SStephan Aßmus 
1478f03a0f9SStephan Aßmus 
148409af934SAndrew Lindesay class MainWindowPackageInfoListener : public PackageInfoListener {
149409af934SAndrew Lindesay public:
MainWindowPackageInfoListener(MainWindow * mainWindow)150409af934SAndrew Lindesay 	MainWindowPackageInfoListener(MainWindow* mainWindow)
151409af934SAndrew Lindesay 		:
152409af934SAndrew Lindesay 		fMainWindow(mainWindow)
153409af934SAndrew Lindesay 	{
154409af934SAndrew Lindesay 	}
155409af934SAndrew Lindesay 
~MainWindowPackageInfoListener()156409af934SAndrew Lindesay 	~MainWindowPackageInfoListener()
157409af934SAndrew Lindesay 	{
158409af934SAndrew Lindesay 	}
159409af934SAndrew Lindesay 
160409af934SAndrew Lindesay private:
161409af934SAndrew Lindesay 	// PackageInfoListener
PackageChanged(const PackageInfoEvent & event)162409af934SAndrew Lindesay 	virtual	void PackageChanged(const PackageInfoEvent& event)
163409af934SAndrew Lindesay 	{
164409af934SAndrew Lindesay 		fMainWindow->PackageChanged(event);
165409af934SAndrew Lindesay 	}
166409af934SAndrew Lindesay 
167409af934SAndrew Lindesay private:
168409af934SAndrew Lindesay 	MainWindow*	fMainWindow;
169409af934SAndrew Lindesay };
170409af934SAndrew Lindesay 
171409af934SAndrew Lindesay 
MainWindow(const BMessage & settings)172f7c2983eSAxel Dörfler MainWindow::MainWindow(const BMessage& settings)
17304c9d578SStephan Aßmus 	:
174f7c2983eSAxel Dörfler 	BWindow(BRect(50, 50, 650, 550), B_TRANSLATE_SYSTEM_NAME("HaikuDepot"),
17504c9d578SStephan Aßmus 		B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
17604c9d578SStephan Aßmus 		B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS),
177d5ef985eSStephan Aßmus 	fScreenshotWindow(NULL),
17895c7b018SAndrew Lindesay 	fShuttingDownWindow(NULL),
179e0a26dceSStephan Aßmus 	fUserMenu(NULL),
180e0a26dceSStephan Aßmus 	fLogInItem(NULL),
181e0a26dceSStephan Aßmus 	fLogOutItem(NULL),
182976cadf1SAndrew Lindesay 	fUsersUserUsageConditionsMenuItem(NULL),
18389b16bb4SAndrew Lindesay 	fModelListener(new MainWindowModelListener(BMessenger(this)), true),
18410cd325cSAndrew Lindesay 	fCoordinator(NULL),
18595c7b018SAndrew Lindesay 	fShouldCloseWhenNoProcessesToCoordinate(false),
18684674570SAndrew Lindesay 	fSinglePackageMode(false),
18784674570SAndrew Lindesay 	fIncrementViewCounterDelayedRunner(NULL)
18804c9d578SStephan Aßmus {
18910cd325cSAndrew Lindesay 	if ((fCoordinatorRunningSem = create_sem(1, "ProcessCoordinatorSem")) < B_OK)
19010cd325cSAndrew Lindesay 		debugger("unable to create the process coordinator semaphore");
19110cd325cSAndrew Lindesay 
192ad2df681SAndrew Lindesay 	_InitPreferredLanguage();
193ad2df681SAndrew Lindesay 
194409af934SAndrew Lindesay 	fPackageInfoListener = PackageInfoListenerRef(
195409af934SAndrew Lindesay 		new MainWindowPackageInfoListener(this), true);
196409af934SAndrew Lindesay 
197cbadcae1SHumdinger 	BMenuBar* menuBar = new BMenuBar("Main Menu");
19804c9d578SStephan Aßmus 	_BuildMenu(menuBar);
19904c9d578SStephan Aßmus 
200cbadcae1SHumdinger 	BMenuBar* userMenuBar = new BMenuBar("User Menu");
201e0a26dceSStephan Aßmus 	_BuildUserMenu(userMenuBar);
202e0a26dceSStephan Aßmus 	set_small_font(userMenuBar);
203e0a26dceSStephan Aßmus 	userMenuBar->SetExplicitMaxSize(BSize(B_SIZE_UNSET,
204e0a26dceSStephan Aßmus 		menuBar->MaxSize().height));
205e0a26dceSStephan Aßmus 
20604c9d578SStephan Aßmus 	fFilterView = new FilterView();
207f0e491d3SAndrew Lindesay 	fFeaturedPackagesView = new FeaturedPackagesView(fModel);
208f0e491d3SAndrew Lindesay 	fPackageListView = new PackageListView(&fModel);
209f0e491d3SAndrew Lindesay 	fPackageInfoView = new PackageInfoView(&fModel, this);
21004c9d578SStephan Aßmus 
21104c9d578SStephan Aßmus 	fSplitView = new BSplitView(B_VERTICAL, 5.0f);
21204c9d578SStephan Aßmus 
213125d42d9SJulian Harnath 	fWorkStatusView = new WorkStatusView("work status");
214125d42d9SJulian Harnath 	fPackageListView->AttachWorkStatusView(fWorkStatusView);
215125d42d9SJulian Harnath 
216e00a489bSAugustin Cavalier 	fListTabs = new TabView(BMessenger(this),
217ccf707d0SAndrew Lindesay 		BMessage(MSG_CHANGE_PACKAGE_LIST_VIEW_MODE), "list tabs");
218e00a489bSAugustin Cavalier 	fListTabs->AddTab(fFeaturedPackagesView);
219e00a489bSAugustin Cavalier 	fListTabs->AddTab(fPackageListView);
2204b930ccaSStephan Aßmus 
22104c9d578SStephan Aßmus 	BLayoutBuilder::Group<>(this, B_VERTICAL, 0.0f)
222e0a26dceSStephan Aßmus 		.AddGroup(B_HORIZONTAL, 0.0f)
223e0a26dceSStephan Aßmus 			.Add(menuBar, 1.0f)
224e0a26dceSStephan Aßmus 			.Add(userMenuBar, 0.0f)
225e0a26dceSStephan Aßmus 		.End()
22604c9d578SStephan Aßmus 		.Add(fFilterView)
22704c9d578SStephan Aßmus 		.AddSplit(fSplitView)
22804c9d578SStephan Aßmus 			.AddGroup(B_VERTICAL)
229e00a489bSAugustin Cavalier 				.Add(fListTabs)
23004c9d578SStephan Aßmus 				.SetInsets(
23104c9d578SStephan Aßmus 					B_USE_DEFAULT_SPACING, 0.0f,
23204c9d578SStephan Aßmus 					B_USE_DEFAULT_SPACING, 0.0f)
23304c9d578SStephan Aßmus 			.End()
23404c9d578SStephan Aßmus 			.Add(fPackageInfoView)
23504c9d578SStephan Aßmus 		.End()
236125d42d9SJulian Harnath 		.Add(fWorkStatusView)
23704c9d578SStephan Aßmus 	;
23804c9d578SStephan Aßmus 
23904c9d578SStephan Aßmus 	fSplitView->SetCollapsible(0, false);
24004c9d578SStephan Aßmus 	fSplitView->SetCollapsible(1, false);
24104c9d578SStephan Aßmus 
2428f03a0f9SStephan Aßmus 	fModel.AddListener(fModelListener);
2438f03a0f9SStephan Aßmus 
24404c9d578SStephan Aßmus 	BMessage columnSettings;
24504c9d578SStephan Aßmus 	if (settings.FindMessage("column settings", &columnSettings) == B_OK)
24604c9d578SStephan Aßmus 		fPackageListView->LoadState(&columnSettings);
24704c9d578SStephan Aßmus 
248ccf707d0SAndrew Lindesay 	_RestoreModelSettings(settings);
249133ebab6SAndrew Lindesay 	_MaybePromptCanShareAnonymousUserData(settings);
25004c9d578SStephan Aßmus 
251ccf707d0SAndrew Lindesay 	if (fModel.PackageListViewMode() == PROMINENT)
252ccf707d0SAndrew Lindesay 		fListTabs->Select(TAB_PROMINENT_PACKAGES);
2532997e05bSStephan Aßmus 	else
254ccf707d0SAndrew Lindesay 		fListTabs->Select(TAB_ALL_PACKAGES);
2552997e05bSStephan Aßmus 
256d2d4866dSAndrew Lindesay 	_RestoreNickname(settings);
25710cd325cSAndrew Lindesay 	_UpdateAuthorization();
258f7c2983eSAxel Dörfler 	_RestoreWindowFrame(settings);
259f7c2983eSAxel Dörfler 
2608f03a0f9SStephan Aßmus 	// start worker threads
26104c9d578SStephan Aßmus 	BPackageRoster().StartWatching(this,
26204c9d578SStephan Aßmus 		B_WATCH_PACKAGE_INSTALLATION_LOCATIONS);
26304c9d578SStephan Aßmus 
2649883929bSAndrew Lindesay 	_AdoptModel();
2659883929bSAndrew Lindesay 	_StartBulkLoad();
26604c9d578SStephan Aßmus }
26704c9d578SStephan Aßmus 
26804c9d578SStephan Aßmus 
26975a70554SAndrew Lindesay /*!	This constructor is used when the application is loaded for the purpose of
27075a70554SAndrew Lindesay 	viewing an HPKG file.
27175a70554SAndrew Lindesay */
27275a70554SAndrew Lindesay 
MainWindow(const BMessage & settings,PackageInfoRef & package)273afe7affbSAndrew Lindesay MainWindow::MainWindow(const BMessage& settings, PackageInfoRef& package)
2746d519fd1SStephan Aßmus 	:
275f7c2983eSAxel Dörfler 	BWindow(BRect(50, 50, 650, 350), B_TRANSLATE_SYSTEM_NAME("HaikuDepot"),
2766d519fd1SStephan Aßmus 		B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
2776d519fd1SStephan Aßmus 		B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS),
2789883929bSAndrew Lindesay 	fFeaturedPackagesView(NULL),
2799883929bSAndrew Lindesay 	fPackageListView(NULL),
280d78bfd8dSJulian Harnath 	fWorkStatusView(NULL),
281d5ef985eSStephan Aßmus 	fScreenshotWindow(NULL),
28295c7b018SAndrew Lindesay 	fShuttingDownWindow(NULL),
283e0a26dceSStephan Aßmus 	fUserMenu(NULL),
284e0a26dceSStephan Aßmus 	fLogInItem(NULL),
2856d519fd1SStephan Aßmus 	fLogOutItem(NULL),
286976cadf1SAndrew Lindesay 	fUsersUserUsageConditionsMenuItem(NULL),
28789b16bb4SAndrew Lindesay 	fModelListener(new MainWindowModelListener(BMessenger(this)), true),
28810cd325cSAndrew Lindesay 	fCoordinator(NULL),
28995c7b018SAndrew Lindesay 	fShouldCloseWhenNoProcessesToCoordinate(false),
29084674570SAndrew Lindesay 	fSinglePackageMode(true),
29184674570SAndrew Lindesay 	fIncrementViewCounterDelayedRunner(NULL)
2926d519fd1SStephan Aßmus {
29375a70554SAndrew Lindesay 	BString title = B_TRANSLATE("HaikuDepot - %PackageName% %PackageVersion%");
29475a70554SAndrew Lindesay 	title.ReplaceAll("%PackageName%", package->Name());
29575a70554SAndrew Lindesay 	title.ReplaceAll("%PackageVersion%", package->Version().ToString());
29675a70554SAndrew Lindesay 	SetTitle(title);
29775a70554SAndrew Lindesay 
29810cd325cSAndrew Lindesay 	if ((fCoordinatorRunningSem = create_sem(1, "ProcessCoordinatorSem")) < B_OK)
29910cd325cSAndrew Lindesay 		debugger("unable to create the process coordinator semaphore");
30010cd325cSAndrew Lindesay 
301ad2df681SAndrew Lindesay 	_InitPreferredLanguage();
302ad2df681SAndrew Lindesay 
303409af934SAndrew Lindesay 	fPackageInfoListener = PackageInfoListenerRef(
304409af934SAndrew Lindesay 		new MainWindowPackageInfoListener(this), true);
305409af934SAndrew Lindesay 
3066d519fd1SStephan Aßmus 	fFilterView = new FilterView();
307f0e491d3SAndrew Lindesay 	fPackageInfoView = new PackageInfoView(&fModel, this);
30887016f8fSAndrew Lindesay 	fWorkStatusView = new WorkStatusView("work status");
3096d519fd1SStephan Aßmus 
3106d519fd1SStephan Aßmus 	BLayoutBuilder::Group<>(this, B_VERTICAL)
3116d519fd1SStephan Aßmus 		.Add(fPackageInfoView)
31287016f8fSAndrew Lindesay 		.Add(fWorkStatusView)
3136d519fd1SStephan Aßmus 		.SetInsets(0, B_USE_WINDOW_INSETS, 0, 0)
3146d519fd1SStephan Aßmus 	;
3156d519fd1SStephan Aßmus 
3166d519fd1SStephan Aßmus 	fModel.AddListener(fModelListener);
3176d519fd1SStephan Aßmus 
318afe7affbSAndrew Lindesay 	// add the single package into the model so that any internal
319afe7affbSAndrew Lindesay 	// business logic is able to find the package.
320afe7affbSAndrew Lindesay 	DepotInfoRef depot(new DepotInfo("single-pkg-depot"), true);
321afe7affbSAndrew Lindesay 	depot->AddPackage(package);
322afe7affbSAndrew Lindesay 	fModel.MergeOrAddDepot(depot);
323afe7affbSAndrew Lindesay 
3246d519fd1SStephan Aßmus 	// Restore settings
325d2d4866dSAndrew Lindesay 	_RestoreNickname(settings);
326ccf707d0SAndrew Lindesay 	_UpdateAuthorization();
327f7c2983eSAxel Dörfler 	_RestoreWindowFrame(settings);
3286d519fd1SStephan Aßmus 
3296d519fd1SStephan Aßmus 	fPackageInfoView->SetPackage(package);
33063975654SStephan Aßmus 
331afe7affbSAndrew Lindesay 	// start worker threads
332afe7affbSAndrew Lindesay 	BPackageRoster().StartWatching(this,
333afe7affbSAndrew Lindesay 		B_WATCH_PACKAGE_INSTALLATION_LOCATIONS);
3346d519fd1SStephan Aßmus }
3356d519fd1SStephan Aßmus 
3366d519fd1SStephan Aßmus 
~MainWindow()33704c9d578SStephan Aßmus MainWindow::~MainWindow()
33804c9d578SStephan Aßmus {
33910cd325cSAndrew Lindesay 	_SpinUntilProcessCoordinatorComplete();
34010cd325cSAndrew Lindesay 	delete_sem(fCoordinatorRunningSem);
34110cd325cSAndrew Lindesay 	fCoordinatorRunningSem = 0;
34210cd325cSAndrew Lindesay 
34304c9d578SStephan Aßmus 	BPackageRoster().StopWatching(this);
34404c9d578SStephan Aßmus 
34595c7b018SAndrew Lindesay 	if (fScreenshotWindow != NULL) {
34695c7b018SAndrew Lindesay 		if (fScreenshotWindow->Lock())
347d5ef985eSStephan Aßmus 			fScreenshotWindow->Quit();
34804c9d578SStephan Aßmus 	}
34904c9d578SStephan Aßmus 
35095c7b018SAndrew Lindesay 	if (fShuttingDownWindow != NULL) {
35195c7b018SAndrew Lindesay 		if (fShuttingDownWindow->Lock())
35295c7b018SAndrew Lindesay 			fShuttingDownWindow->Quit();
35395c7b018SAndrew Lindesay 	}
354d5562247SAugustin Cavalier 
3554329a83fSAugustin Cavalier 	// We must clear the model early to release references.
356d5562247SAugustin Cavalier 	fModel.Clear();
35795c7b018SAndrew Lindesay }
35895c7b018SAndrew Lindesay 
35904c9d578SStephan Aßmus 
36004c9d578SStephan Aßmus bool
QuitRequested()36104c9d578SStephan Aßmus MainWindow::QuitRequested()
36204c9d578SStephan Aßmus {
36304c9d578SStephan Aßmus 
36410cd325cSAndrew Lindesay 	_StopProcessCoordinators();
3653369e03dSAndrew Lindesay 
36695c7b018SAndrew Lindesay 	// If there are any processes in flight we need to be careful to make
36795c7b018SAndrew Lindesay 	// sure that they are cleanly completed before actually quitting.  By
36895c7b018SAndrew Lindesay 	// turning on the `fShouldCloseWhenNoProcessesToCoordinate` flag, when
36995c7b018SAndrew Lindesay 	// the process coordination has completed then it will detect this and
37095c7b018SAndrew Lindesay 	// quit again.
37195c7b018SAndrew Lindesay 
37295c7b018SAndrew Lindesay 	{
37395c7b018SAndrew Lindesay 		AutoLocker<BLocker> lock(&fCoordinatorLock);
37495c7b018SAndrew Lindesay 		fShouldCloseWhenNoProcessesToCoordinate = true;
37595c7b018SAndrew Lindesay 
376409af934SAndrew Lindesay 		if (fCoordinator != NULL) {
37795c7b018SAndrew Lindesay 			HDINFO("a coordinator is running --> will wait before quitting...");
37895c7b018SAndrew Lindesay 
37995c7b018SAndrew Lindesay 			if (fShuttingDownWindow == NULL)
38095c7b018SAndrew Lindesay 				fShuttingDownWindow = new ShuttingDownWindow(this);
38195c7b018SAndrew Lindesay 			fShuttingDownWindow->Show();
38295c7b018SAndrew Lindesay 
38395c7b018SAndrew Lindesay 			return false;
38495c7b018SAndrew Lindesay 		}
38595c7b018SAndrew Lindesay 	}
38695c7b018SAndrew Lindesay 
38795c7b018SAndrew Lindesay 	BMessage settings;
38895c7b018SAndrew Lindesay 	StoreSettings(settings);
38995c7b018SAndrew Lindesay 	BMessage message(MSG_MAIN_WINDOW_CLOSED);
39095c7b018SAndrew Lindesay 	message.AddMessage(KEY_WINDOW_SETTINGS, &settings);
39195c7b018SAndrew Lindesay 	be_app->PostMessage(&message);
39295c7b018SAndrew Lindesay 
39395c7b018SAndrew Lindesay 	if (fShuttingDownWindow != NULL) {
39495c7b018SAndrew Lindesay 		if (fShuttingDownWindow->Lock())
39595c7b018SAndrew Lindesay 			fShuttingDownWindow->Quit();
39695c7b018SAndrew Lindesay 		fShuttingDownWindow = NULL;
39795c7b018SAndrew Lindesay 	}
39895c7b018SAndrew Lindesay 
39904c9d578SStephan Aßmus 	return true;
40004c9d578SStephan Aßmus }
40104c9d578SStephan Aßmus 
40204c9d578SStephan Aßmus 
40304c9d578SStephan Aßmus void
MessageReceived(BMessage * message)40404c9d578SStephan Aßmus MainWindow::MessageReceived(BMessage* message)
40504c9d578SStephan Aßmus {
40604c9d578SStephan Aßmus 	switch (message->what) {
4073369e03dSAndrew Lindesay 		case MSG_BULK_LOAD_DONE:
40810cd325cSAndrew Lindesay 		{
40910cd325cSAndrew Lindesay 			int64 errorStatus64;
41010cd325cSAndrew Lindesay 			if (message->FindInt64(KEY_ERROR_STATUS, &errorStatus64) == B_OK)
41110cd325cSAndrew Lindesay 				_BulkLoadCompleteReceived((status_t) errorStatus64);
41210cd325cSAndrew Lindesay 			else
413fa5c8097SAndrew Lindesay 				HDERROR("expected [%s] value in message", KEY_ERROR_STATUS);
41404c9d578SStephan Aßmus 			break;
41510cd325cSAndrew Lindesay 		}
41604c9d578SStephan Aßmus 		case B_SIMPLE_DATA:
41704c9d578SStephan Aßmus 		case B_REFS_RECEIVED:
41804c9d578SStephan Aßmus 			// TODO: ?
41904c9d578SStephan Aßmus 			break;
42004c9d578SStephan Aßmus 
42104c9d578SStephan Aßmus 		case B_PACKAGE_UPDATE:
422f32d5c5cSAndrew Lindesay 			_HandleExternalPackageUpdateMessageReceived(message);
42304c9d578SStephan Aßmus 			break;
42404c9d578SStephan Aßmus 
4255bf2b6ebSBrian Hill 		case MSG_REFRESH_REPOS:
4263369e03dSAndrew Lindesay 			_StartBulkLoad(true);
4273369e03dSAndrew Lindesay 			break;
4283369e03dSAndrew Lindesay 
42910cd325cSAndrew Lindesay 		case MSG_WORK_STATUS_CLEAR:
43010cd325cSAndrew Lindesay 			_HandleWorkStatusClear();
43110cd325cSAndrew Lindesay 			break;
43210cd325cSAndrew Lindesay 
4333369e03dSAndrew Lindesay 		case MSG_WORK_STATUS_CHANGE:
4343369e03dSAndrew Lindesay 			_HandleWorkStatusChangeMessageReceived(message);
43504c9d578SStephan Aßmus 			break;
43604c9d578SStephan Aßmus 
4375bf2b6ebSBrian Hill 		case MSG_MANAGE_REPOS:
4385bf2b6ebSBrian Hill 			be_roster->Launch("application/x-vnd.Haiku-Repositories");
4395bf2b6ebSBrian Hill 			break;
4405bf2b6ebSBrian Hill 
441d144f952SAugustin Cavalier 		case MSG_SOFTWARE_UPDATER:
442d144f952SAugustin Cavalier 			be_roster->Launch("application/x-vnd.haiku-softwareupdater");
443d144f952SAugustin Cavalier 			break;
444d144f952SAugustin Cavalier 
44504c9d578SStephan Aßmus 		case MSG_LOG_IN:
4461bbda92dSStephan Aßmus 			_OpenLoginWindow(BMessage());
44704c9d578SStephan Aßmus 			break;
44804c9d578SStephan Aßmus 
449133ebab6SAndrew Lindesay 		case MSG_SETTINGS:
450133ebab6SAndrew Lindesay 			_OpenSettingsWindow();
451133ebab6SAndrew Lindesay 			break;
452133ebab6SAndrew Lindesay 
4538f03a0f9SStephan Aßmus 		case MSG_LOG_OUT:
454d2d4866dSAndrew Lindesay 			fModel.SetNickname("");
4558f03a0f9SStephan Aßmus 			break;
4568f03a0f9SStephan Aßmus 
45701339a54SAndrew Lindesay 		case MSG_VIEW_LATEST_USER_USAGE_CONDITIONS:
458d2d4866dSAndrew Lindesay 			_ViewUserUsageConditions(LATEST);
459d2d4866dSAndrew Lindesay 			break;
460d2d4866dSAndrew Lindesay 
461d2d4866dSAndrew Lindesay 		case MSG_VIEW_USERS_USER_USAGE_CONDITIONS:
462d2d4866dSAndrew Lindesay 			_ViewUserUsageConditions(USER);
46301339a54SAndrew Lindesay 			break;
46401339a54SAndrew Lindesay 
4658f03a0f9SStephan Aßmus 		case MSG_AUTHORIZATION_CHANGED:
46610cd325cSAndrew Lindesay 			_StartUserVerify();
4678f03a0f9SStephan Aßmus 			_UpdateAuthorization();
4688f03a0f9SStephan Aßmus 			break;
4698f03a0f9SStephan Aßmus 
47088af15cfSAndrew Lindesay 		case MSG_SCREENSHOT_CACHED:
47188af15cfSAndrew Lindesay 			_HandleScreenshotCached(message);
47288af15cfSAndrew Lindesay 			break;
47388af15cfSAndrew Lindesay 
47489b16bb4SAndrew Lindesay 		case MSG_CATEGORIES_LIST_CHANGED:
47589b16bb4SAndrew Lindesay 			fFilterView->AdoptModel(fModel);
47689b16bb4SAndrew Lindesay 			break;
47789b16bb4SAndrew Lindesay 
478ccf707d0SAndrew Lindesay 		case MSG_CHANGE_PACKAGE_LIST_VIEW_MODE:
479ccf707d0SAndrew Lindesay 			_HandleChangePackageListViewMode();
4804fade61fSStephan Aßmus 			break;
4814fade61fSStephan Aßmus 
482fdec4227SStephan Aßmus 		case MSG_SHOW_AVAILABLE_PACKAGES:
483fdec4227SStephan Aßmus 			{
484fdec4227SStephan Aßmus 				BAutolock locker(fModel.Lock());
485363fc60bSAndrew Lindesay 				PackageFilterModel* filterModel = fModel.PackageFilter();
486363fc60bSAndrew Lindesay 				filterModel->SetShowAvailablePackages(!filterModel->ShowAvailablePackages());
487fdec4227SStephan Aßmus 			}
488fdec4227SStephan Aßmus 			_AdoptModel();
489fdec4227SStephan Aßmus 			break;
490fdec4227SStephan Aßmus 
491fdec4227SStephan Aßmus 		case MSG_SHOW_INSTALLED_PACKAGES:
492fdec4227SStephan Aßmus 			{
493fdec4227SStephan Aßmus 				BAutolock locker(fModel.Lock());
494363fc60bSAndrew Lindesay 				PackageFilterModel* filterModel = fModel.PackageFilter();
495363fc60bSAndrew Lindesay 				filterModel->SetShowInstalledPackages(!filterModel->ShowInstalledPackages());
496fdec4227SStephan Aßmus 			}
497fdec4227SStephan Aßmus 			_AdoptModel();
498fdec4227SStephan Aßmus 			break;
499fdec4227SStephan Aßmus 
50004c9d578SStephan Aßmus 		case MSG_SHOW_SOURCE_PACKAGES:
50104c9d578SStephan Aßmus 			{
50204c9d578SStephan Aßmus 				BAutolock locker(fModel.Lock());
503363fc60bSAndrew Lindesay 				PackageFilterModel* filterModel = fModel.PackageFilter();
504363fc60bSAndrew Lindesay 				filterModel->SetShowSourcePackages(!filterModel->ShowSourcePackages());
50504c9d578SStephan Aßmus 			}
50604c9d578SStephan Aßmus 			_AdoptModel();
50704c9d578SStephan Aßmus 			break;
50804c9d578SStephan Aßmus 
50904c9d578SStephan Aßmus 		case MSG_SHOW_DEVELOP_PACKAGES:
51004c9d578SStephan Aßmus 			{
51104c9d578SStephan Aßmus 				BAutolock locker(fModel.Lock());
512363fc60bSAndrew Lindesay 				PackageFilterModel* filterModel = fModel.PackageFilter();
513363fc60bSAndrew Lindesay 				filterModel->SetShowDevelopPackages(!filterModel->ShowDevelopPackages());
51404c9d578SStephan Aßmus 			}
51504c9d578SStephan Aßmus 			_AdoptModel();
51604c9d578SStephan Aßmus 			break;
51704c9d578SStephan Aßmus 
518a9edb9bfSAndrew Lindesay 			// this may be triggered by, for example, a user rating being added
519a9edb9bfSAndrew Lindesay 			// or having been altered.
520a9edb9bfSAndrew Lindesay 		case MSG_SERVER_DATA_CHANGED:
521a9edb9bfSAndrew Lindesay 		{
522a9edb9bfSAndrew Lindesay 			BString name;
523a9edb9bfSAndrew Lindesay 			if (message->FindString("name", &name) == B_OK) {
524a9edb9bfSAndrew Lindesay 				BAutolock locker(fModel.Lock());
525a9edb9bfSAndrew Lindesay 				if (fPackageInfoView->Package()->Name() == name) {
526a9edb9bfSAndrew Lindesay 					_PopulatePackageAsync(true);
527a9edb9bfSAndrew Lindesay 				} else {
528f96d1f4dSAndrew Lindesay 					HDDEBUG("pkg [%s] is updated on the server, but is "
529f96d1f4dSAndrew Lindesay 						"not selected so will not be updated.",
530fa5c8097SAndrew Lindesay 						name.String());
531a9edb9bfSAndrew Lindesay 				}
532a9edb9bfSAndrew Lindesay 			}
533a9edb9bfSAndrew Lindesay 			break;
534a9edb9bfSAndrew Lindesay 		}
535a9edb9bfSAndrew Lindesay 
53684674570SAndrew Lindesay 		case MSG_INCREMENT_VIEW_COUNTER:
53784674570SAndrew Lindesay 			_HandleIncrementViewCounter(message);
53884674570SAndrew Lindesay 			break;
53984674570SAndrew Lindesay 
54004c9d578SStephan Aßmus 		case MSG_PACKAGE_SELECTED:
54104c9d578SStephan Aßmus 		{
54272992391SStephan Aßmus 			BString name;
54372992391SStephan Aßmus 			if (message->FindString("name", &name) == B_OK) {
544c4199192SAndrew Lindesay 				PackageInfoRef package;
545c4199192SAndrew Lindesay 				{
54675ba9dbfSStephan Aßmus 					BAutolock locker(fModel.Lock());
547c4199192SAndrew Lindesay 					package = fModel.PackageForName(name);
548c4199192SAndrew Lindesay 				}
5496f07feadSAndrew Lindesay 				if (!package.IsSet() || name != package->Name())
550c4199192SAndrew Lindesay 					debugger("unable to find the named package");
551133ebab6SAndrew Lindesay 				else {
55204c9d578SStephan Aßmus 					_AdoptPackage(package);
55384674570SAndrew Lindesay 					_SetupDelayedIncrementViewCounter(package);
554133ebab6SAndrew Lindesay 				}
55504c9d578SStephan Aßmus 			} else {
55604c9d578SStephan Aßmus 				_ClearPackage();
55704c9d578SStephan Aßmus 			}
55804c9d578SStephan Aßmus 			break;
55904c9d578SStephan Aßmus 		}
56004c9d578SStephan Aßmus 
56104c9d578SStephan Aßmus 		case MSG_CATEGORY_SELECTED:
56204c9d578SStephan Aßmus 		{
56389b16bb4SAndrew Lindesay 			BString code;
56489b16bb4SAndrew Lindesay 			if (message->FindString("code", &code) != B_OK)
56589b16bb4SAndrew Lindesay 				code = "";
56604c9d578SStephan Aßmus 			{
56704c9d578SStephan Aßmus 				BAutolock locker(fModel.Lock());
568363fc60bSAndrew Lindesay 				fModel.PackageFilter()->SetCategory(code);
56904c9d578SStephan Aßmus 			}
57004c9d578SStephan Aßmus 			_AdoptModel();
57104c9d578SStephan Aßmus 			break;
57204c9d578SStephan Aßmus 		}
57304c9d578SStephan Aßmus 
57404c9d578SStephan Aßmus 		case MSG_DEPOT_SELECTED:
57504c9d578SStephan Aßmus 		{
57604c9d578SStephan Aßmus 			BString name;
57704c9d578SStephan Aßmus 			if (message->FindString("name", &name) != B_OK)
57804c9d578SStephan Aßmus 				name = "";
57904c9d578SStephan Aßmus 			{
58004c9d578SStephan Aßmus 				BAutolock locker(fModel.Lock());
581363fc60bSAndrew Lindesay 				fModel.PackageFilter()->SetDepotName(name);
58204c9d578SStephan Aßmus 			}
58304c9d578SStephan Aßmus 			_AdoptModel();
584b965ce70SHumdinger 			_UpdateAvailableRepositories();
58504c9d578SStephan Aßmus 			break;
58604c9d578SStephan Aßmus 		}
58704c9d578SStephan Aßmus 
58804c9d578SStephan Aßmus 		case MSG_SEARCH_TERMS_MODIFIED:
58904c9d578SStephan Aßmus 		{
59004c9d578SStephan Aßmus 			// TODO: Do this with a delay!
59104c9d578SStephan Aßmus 			BString searchTerms;
59204c9d578SStephan Aßmus 			if (message->FindString("search terms", &searchTerms) != B_OK)
59304c9d578SStephan Aßmus 				searchTerms = "";
59404c9d578SStephan Aßmus 			{
59504c9d578SStephan Aßmus 				BAutolock locker(fModel.Lock());
596363fc60bSAndrew Lindesay 				fModel.PackageFilter()->SetSearchTerms(searchTerms);
59704c9d578SStephan Aßmus 			}
59804c9d578SStephan Aßmus 			_AdoptModel();
59904c9d578SStephan Aßmus 			break;
60004c9d578SStephan Aßmus 		}
60104c9d578SStephan Aßmus 
602da651104SStephan Aßmus 		case MSG_PACKAGE_CHANGED:
60304c9d578SStephan Aßmus 		{
60404c9d578SStephan Aßmus 			PackageInfo* info;
60504c9d578SStephan Aßmus 			if (message->FindPointer("package", (void**)&info) == B_OK) {
60604c9d578SStephan Aßmus 				PackageInfoRef ref(info, true);
6070b69420bSAndrew Lindesay 				fFeaturedPackagesView->BeginAddRemove();
608c4199192SAndrew Lindesay 				_AddRemovePackageFromLists(ref);
6090b69420bSAndrew Lindesay 				fFeaturedPackagesView->EndAddRemove();
61010cd325cSAndrew Lindesay 			}
61104c9d578SStephan Aßmus 			break;
61204c9d578SStephan Aßmus 		}
61304c9d578SStephan Aßmus 
614409af934SAndrew Lindesay 		case MSG_PROCESS_COORDINATOR_CHANGED:
615409af934SAndrew Lindesay 		{
616409af934SAndrew Lindesay 			ProcessCoordinatorState state(message);
617409af934SAndrew Lindesay 			_HandleProcessCoordinatorChanged(state);
618409af934SAndrew Lindesay 			break;
619409af934SAndrew Lindesay 		}
620409af934SAndrew Lindesay 
62104c9d578SStephan Aßmus 		case MSG_RATE_PACKAGE:
6221bbda92dSStephan Aßmus 			_RatePackage();
62304c9d578SStephan Aßmus 			break;
62404c9d578SStephan Aßmus 
625d5ef985eSStephan Aßmus 		case MSG_SHOW_SCREENSHOT:
626d5ef985eSStephan Aßmus 			_ShowScreenshot();
627d5ef985eSStephan Aßmus 			break;
628d5ef985eSStephan Aßmus 
629125d42d9SJulian Harnath 		case MSG_PACKAGE_WORKER_BUSY:
630125d42d9SJulian Harnath 		{
631125d42d9SJulian Harnath 			BString reason;
632125d42d9SJulian Harnath 			status_t status = message->FindString("reason", &reason);
633125d42d9SJulian Harnath 			if (status != B_OK)
634125d42d9SJulian Harnath 				break;
635125d42d9SJulian Harnath 			fWorkStatusView->SetBusy(reason);
636125d42d9SJulian Harnath 			break;
637125d42d9SJulian Harnath 		}
638125d42d9SJulian Harnath 
639125d42d9SJulian Harnath 		case MSG_PACKAGE_WORKER_IDLE:
640125d42d9SJulian Harnath 			fWorkStatusView->SetIdle();
641125d42d9SJulian Harnath 			break;
642125d42d9SJulian Harnath 
64310cd325cSAndrew Lindesay 		case MSG_USER_USAGE_CONDITIONS_NOT_LATEST:
64410cd325cSAndrew Lindesay 		{
64510cd325cSAndrew Lindesay 			BMessage userDetailMsg;
64610cd325cSAndrew Lindesay 			if (message->FindMessage("userDetail", &userDetailMsg) != B_OK) {
64710cd325cSAndrew Lindesay 				debugger("expected the [userDetail] data to be carried in the "
64810cd325cSAndrew Lindesay 					"message.");
64910cd325cSAndrew Lindesay 			}
65010cd325cSAndrew Lindesay 			UserDetail userDetail(&userDetailMsg);
65110cd325cSAndrew Lindesay 			_HandleUserUsageConditionsNotLatest(userDetail);
65210cd325cSAndrew Lindesay 			break;
65310cd325cSAndrew Lindesay 		}
65410cd325cSAndrew Lindesay 
65504c9d578SStephan Aßmus 		default:
65604c9d578SStephan Aßmus 			BWindow::MessageReceived(message);
65704c9d578SStephan Aßmus 			break;
65804c9d578SStephan Aßmus 	}
65904c9d578SStephan Aßmus }
66004c9d578SStephan Aßmus 
66104c9d578SStephan Aßmus 
662ccf707d0SAndrew Lindesay static const char*
main_window_package_list_view_mode_str(package_list_view_mode mode)663ccf707d0SAndrew Lindesay main_window_package_list_view_mode_str(package_list_view_mode mode)
664ccf707d0SAndrew Lindesay {
665ccf707d0SAndrew Lindesay 	if (mode == PROMINENT)
666ccf707d0SAndrew Lindesay 		return "PROMINENT";
667ccf707d0SAndrew Lindesay 	return "ALL";
668ccf707d0SAndrew Lindesay }
669ccf707d0SAndrew Lindesay 
670ccf707d0SAndrew Lindesay 
671ccf707d0SAndrew Lindesay static package_list_view_mode
main_window_str_to_package_list_view_mode(const BString & str)672ccf707d0SAndrew Lindesay main_window_str_to_package_list_view_mode(const BString& str)
673ccf707d0SAndrew Lindesay {
674ccf707d0SAndrew Lindesay 	if (str == "PROMINENT")
675ccf707d0SAndrew Lindesay 		return PROMINENT;
676ccf707d0SAndrew Lindesay 	return ALL;
677ccf707d0SAndrew Lindesay }
678ccf707d0SAndrew Lindesay 
679ccf707d0SAndrew Lindesay 
68004c9d578SStephan Aßmus void
StoreSettings(BMessage & settings)6814b347fccSAndrew Lindesay MainWindow::StoreSettings(BMessage& settings)
68204c9d578SStephan Aßmus {
683f7c2983eSAxel Dörfler 	settings.AddRect(_WindowFrameName(), Frame());
684f7c2983eSAxel Dörfler 	if (!fSinglePackageMode) {
68504c9d578SStephan Aßmus 		settings.AddRect("window frame", Frame());
68604c9d578SStephan Aßmus 
68704c9d578SStephan Aßmus 		BMessage columnSettings;
6889883929bSAndrew Lindesay 		if (fPackageListView != NULL)
68904c9d578SStephan Aßmus 			fPackageListView->SaveState(&columnSettings);
69004c9d578SStephan Aßmus 
69104c9d578SStephan Aßmus 		settings.AddMessage("column settings", &columnSettings);
69204c9d578SStephan Aßmus 
693133ebab6SAndrew Lindesay 		settings.AddString(SETTING_PACKAGE_LIST_VIEW_MODE,
694ccf707d0SAndrew Lindesay 			main_window_package_list_view_mode_str(
695ccf707d0SAndrew Lindesay 				fModel.PackageListViewMode()));
696363fc60bSAndrew Lindesay 
697133ebab6SAndrew Lindesay 		settings.AddBool(SETTING_SHOW_AVAILABLE_PACKAGES,
698363fc60bSAndrew Lindesay 			fModel.PackageFilter()->ShowAvailablePackages());
699133ebab6SAndrew Lindesay 		settings.AddBool(SETTING_SHOW_INSTALLED_PACKAGES,
700363fc60bSAndrew Lindesay 			fModel.PackageFilter()->ShowInstalledPackages());
701133ebab6SAndrew Lindesay 		settings.AddBool(SETTING_SHOW_DEVELOP_PACKAGES,
702363fc60bSAndrew Lindesay 			fModel.PackageFilter()->ShowDevelopPackages());
703133ebab6SAndrew Lindesay 		settings.AddBool(SETTING_SHOW_SOURCE_PACKAGES,
704363fc60bSAndrew Lindesay 			fModel.PackageFilter()->ShowSourcePackages());
705363fc60bSAndrew Lindesay 
706133ebab6SAndrew Lindesay 		settings.AddBool(SETTING_CAN_SHARE_ANONYMOUS_USER_DATA,
707133ebab6SAndrew Lindesay 			fModel.CanShareAnonymousUsageData());
7086d519fd1SStephan Aßmus 	}
7098f03a0f9SStephan Aßmus 
710d2d4866dSAndrew Lindesay 	settings.AddString("username", fModel.Nickname());
71104c9d578SStephan Aßmus }
71204c9d578SStephan Aßmus 
71304c9d578SStephan Aßmus 
71404c9d578SStephan Aßmus void
Consume(ProcessCoordinator * item)715a18f873fSAndrew Lindesay MainWindow::Consume(ProcessCoordinator *item)
716a18f873fSAndrew Lindesay {
717a18f873fSAndrew Lindesay 	_AddProcessCoordinator(item);
718a18f873fSAndrew Lindesay }
719a18f873fSAndrew Lindesay 
720a18f873fSAndrew Lindesay 
721a18f873fSAndrew Lindesay void
PackageChanged(const PackageInfoEvent & event)72204c9d578SStephan Aßmus MainWindow::PackageChanged(const PackageInfoEvent& event)
72304c9d578SStephan Aßmus {
724*c0789628SAndrew Lindesay 	uint32 watchedChanges = PKG_CHANGED_LOCAL_INFO | PKG_CHANGED_CLASSIFICATION;
725a9edb9bfSAndrew Lindesay 	if ((event.Changes() & watchedChanges) != 0) {
72604c9d578SStephan Aßmus 		PackageInfoRef ref(event.Package());
727da651104SStephan Aßmus 		BMessage message(MSG_PACKAGE_CHANGED);
72804c9d578SStephan Aßmus 		message.AddPointer("package", ref.Get());
72904c9d578SStephan Aßmus 		ref.Detach();
73004c9d578SStephan Aßmus 			// reference needs to be released by MessageReceived();
73104c9d578SStephan Aßmus 		PostMessage(&message);
73204c9d578SStephan Aßmus 	}
73304c9d578SStephan Aßmus }
73404c9d578SStephan Aßmus 
73504c9d578SStephan Aßmus 
73604c9d578SStephan Aßmus void
_BuildMenu(BMenuBar * menuBar)73704c9d578SStephan Aßmus MainWindow::_BuildMenu(BMenuBar* menuBar)
73804c9d578SStephan Aßmus {
7390b6928f1SHumdinger 	BMenu* menu = new BMenu(B_TRANSLATE_SYSTEM_NAME("HaikuDepot"));
7403369e03dSAndrew Lindesay 	fRefreshRepositoriesItem = new BMenuItem(
7413369e03dSAndrew Lindesay 		B_TRANSLATE("Refresh repositories"), new BMessage(MSG_REFRESH_REPOS));
7423369e03dSAndrew Lindesay 	menu->AddItem(fRefreshRepositoriesItem);
743d7f78130SHumdinger 	menu->AddItem(new BMenuItem(B_TRANSLATE("Manage repositories"
744d7f78130SHumdinger 		B_UTF8_ELLIPSIS), new BMessage(MSG_MANAGE_REPOS)));
745d144f952SAugustin Cavalier 	menu->AddItem(new BMenuItem(B_TRANSLATE("Check for updates"
746d144f952SAugustin Cavalier 		B_UTF8_ELLIPSIS), new BMessage(MSG_SOFTWARE_UPDATER)));
7470b6928f1SHumdinger 	menu->AddSeparatorItem();
7480b6928f1SHumdinger 	menu->AddItem(new BMenuItem(B_TRANSLATE("Settings" B_UTF8_ELLIPSIS),
749e1ae57abSJoachim Mairböck 		new BMessage(MSG_SETTINGS), ','));
7500b6928f1SHumdinger 	menu->AddItem(new BMenuItem(B_TRANSLATE("Quit"),
7510b6928f1SHumdinger 		new BMessage(B_QUIT_REQUESTED), 'Q'));
75204c9d578SStephan Aßmus 	menuBar->AddItem(menu);
75304c9d578SStephan Aßmus 
754b965ce70SHumdinger 	fRepositoryMenu = new BMenu(B_TRANSLATE("Repositories"));
755b965ce70SHumdinger 	menuBar->AddItem(fRepositoryMenu);
756b965ce70SHumdinger 
7574fade61fSStephan Aßmus 	menu = new BMenu(B_TRANSLATE("Show"));
7584fade61fSStephan Aßmus 
759fdec4227SStephan Aßmus 	fShowAvailablePackagesItem = new BMenuItem(
7604fade61fSStephan Aßmus 		B_TRANSLATE("Available packages"),
761fdec4227SStephan Aßmus 		new BMessage(MSG_SHOW_AVAILABLE_PACKAGES));
762fdec4227SStephan Aßmus 	menu->AddItem(fShowAvailablePackagesItem);
763fdec4227SStephan Aßmus 
764fdec4227SStephan Aßmus 	fShowInstalledPackagesItem = new BMenuItem(
7654fade61fSStephan Aßmus 		B_TRANSLATE("Installed packages"),
766fdec4227SStephan Aßmus 		new BMessage(MSG_SHOW_INSTALLED_PACKAGES));
767fdec4227SStephan Aßmus 	menu->AddItem(fShowInstalledPackagesItem);
768fdec4227SStephan Aßmus 
769fdec4227SStephan Aßmus 	menu->AddSeparatorItem();
770fdec4227SStephan Aßmus 
771fdec4227SStephan Aßmus 	fShowDevelopPackagesItem = new BMenuItem(
7724fade61fSStephan Aßmus 		B_TRANSLATE("Develop packages"),
773fdec4227SStephan Aßmus 		new BMessage(MSG_SHOW_DEVELOP_PACKAGES));
774fdec4227SStephan Aßmus 	menu->AddItem(fShowDevelopPackagesItem);
775fdec4227SStephan Aßmus 
776fdec4227SStephan Aßmus 	fShowSourcePackagesItem = new BMenuItem(
7774fade61fSStephan Aßmus 		B_TRANSLATE("Source packages"),
778fdec4227SStephan Aßmus 		new BMessage(MSG_SHOW_SOURCE_PACKAGES));
779fdec4227SStephan Aßmus 	menu->AddItem(fShowSourcePackagesItem);
780fdec4227SStephan Aßmus 
781fdec4227SStephan Aßmus 	menuBar->AddItem(menu);
78204c9d578SStephan Aßmus }
78304c9d578SStephan Aßmus 
78404c9d578SStephan Aßmus 
78504c9d578SStephan Aßmus void
_BuildUserMenu(BMenuBar * menuBar)786e0a26dceSStephan Aßmus MainWindow::_BuildUserMenu(BMenuBar* menuBar)
787e0a26dceSStephan Aßmus {
788e0a26dceSStephan Aßmus 	fUserMenu = new BMenu(B_TRANSLATE("Not logged in"));
789e0a26dceSStephan Aßmus 
790e0a26dceSStephan Aßmus 	fLogInItem = new BMenuItem(B_TRANSLATE("Log in" B_UTF8_ELLIPSIS),
791e0a26dceSStephan Aßmus 		new BMessage(MSG_LOG_IN));
792e0a26dceSStephan Aßmus 	fUserMenu->AddItem(fLogInItem);
793e0a26dceSStephan Aßmus 
794e0a26dceSStephan Aßmus 	fLogOutItem = new BMenuItem(B_TRANSLATE("Log out"),
795e0a26dceSStephan Aßmus 		new BMessage(MSG_LOG_OUT));
796e0a26dceSStephan Aßmus 	fUserMenu->AddItem(fLogOutItem);
797e0a26dceSStephan Aßmus 
7980c82f64bSAndrew Lindesay 	BMenuItem *latestUserUsageConditionsMenuItem =
7991448ced0SHumdinger 		new BMenuItem(B_TRANSLATE("View latest usage conditions"
80001339a54SAndrew Lindesay 			B_UTF8_ELLIPSIS),
80101339a54SAndrew Lindesay 			new BMessage(MSG_VIEW_LATEST_USER_USAGE_CONDITIONS));
8020c82f64bSAndrew Lindesay 	fUserMenu->AddItem(latestUserUsageConditionsMenuItem);
80301339a54SAndrew Lindesay 
804d2d4866dSAndrew Lindesay 	fUsersUserUsageConditionsMenuItem =
805d2d4866dSAndrew Lindesay 		new BMenuItem(B_TRANSLATE("View agreed usage conditions"
806d2d4866dSAndrew Lindesay 			B_UTF8_ELLIPSIS),
807d2d4866dSAndrew Lindesay 			new BMessage(MSG_VIEW_USERS_USER_USAGE_CONDITIONS));
808d2d4866dSAndrew Lindesay 	fUserMenu->AddItem(fUsersUserUsageConditionsMenuItem);
809d2d4866dSAndrew Lindesay 
810e0a26dceSStephan Aßmus 	menuBar->AddItem(fUserMenu);
811e0a26dceSStephan Aßmus }
812e0a26dceSStephan Aßmus 
813e0a26dceSStephan Aßmus 
814e0a26dceSStephan Aßmus void
_RestoreNickname(const BMessage & settings)815d2d4866dSAndrew Lindesay MainWindow::_RestoreNickname(const BMessage& settings)
816f7c2983eSAxel Dörfler {
817d2d4866dSAndrew Lindesay 	BString nickname;
818d2d4866dSAndrew Lindesay 	if (settings.FindString("username", &nickname) == B_OK
819d2d4866dSAndrew Lindesay 		&& nickname.Length() > 0) {
820d2d4866dSAndrew Lindesay 		fModel.SetNickname(nickname);
821f7c2983eSAxel Dörfler 	}
822f7c2983eSAxel Dörfler }
823f7c2983eSAxel Dörfler 
824f7c2983eSAxel Dörfler 
825f7c2983eSAxel Dörfler const char*
_WindowFrameName() const826f7c2983eSAxel Dörfler MainWindow::_WindowFrameName() const
827f7c2983eSAxel Dörfler {
828f7c2983eSAxel Dörfler 	if (fSinglePackageMode)
829f7c2983eSAxel Dörfler 		return "small window frame";
830f7c2983eSAxel Dörfler 
831f7c2983eSAxel Dörfler 	return "window frame";
832f7c2983eSAxel Dörfler }
833f7c2983eSAxel Dörfler 
834f7c2983eSAxel Dörfler 
835f7c2983eSAxel Dörfler void
_RestoreWindowFrame(const BMessage & settings)836f7c2983eSAxel Dörfler MainWindow::_RestoreWindowFrame(const BMessage& settings)
837f7c2983eSAxel Dörfler {
838f7c2983eSAxel Dörfler 	BRect frame = Frame();
839f7c2983eSAxel Dörfler 
840f7c2983eSAxel Dörfler 	BRect windowFrame;
841f7c2983eSAxel Dörfler 	bool fromSettings = false;
842f7c2983eSAxel Dörfler 	if (settings.FindRect(_WindowFrameName(), &windowFrame) == B_OK) {
843f7c2983eSAxel Dörfler 		frame = windowFrame;
844f7c2983eSAxel Dörfler 		fromSettings = true;
845f7c2983eSAxel Dörfler 	} else if (!fSinglePackageMode) {
846f7c2983eSAxel Dörfler 		// Resize to occupy a certain screen size
847f7c2983eSAxel Dörfler 		BRect screenFrame = BScreen(this).Frame();
848f7c2983eSAxel Dörfler 		float width = frame.Width();
849f7c2983eSAxel Dörfler 		float height = frame.Height();
850f7c2983eSAxel Dörfler 		if (width < screenFrame.Width() * .666f
851f7c2983eSAxel Dörfler 			&& height < screenFrame.Height() * .666f) {
852f7c2983eSAxel Dörfler 			frame.bottom = frame.top + screenFrame.Height() * .666f;
853f7c2983eSAxel Dörfler 			frame.right = frame.left
854f7c2983eSAxel Dörfler 				+ std::min(screenFrame.Width() * .666f, height * 7 / 5);
855f7c2983eSAxel Dörfler 		}
856f7c2983eSAxel Dörfler 	}
857f7c2983eSAxel Dörfler 
858f7c2983eSAxel Dörfler 	MoveTo(frame.LeftTop());
859f7c2983eSAxel Dörfler 	ResizeTo(frame.Width(), frame.Height());
860f7c2983eSAxel Dörfler 
861f7c2983eSAxel Dörfler 	if (fromSettings)
8628e96ec34SAxel Dörfler 		MoveOnScreen();
863f7c2983eSAxel Dörfler 	else
864f7c2983eSAxel Dörfler 		CenterOnScreen();
865f7c2983eSAxel Dörfler }
866f7c2983eSAxel Dörfler 
867f7c2983eSAxel Dörfler 
868f7c2983eSAxel Dörfler void
_RestoreModelSettings(const BMessage & settings)869ccf707d0SAndrew Lindesay MainWindow::_RestoreModelSettings(const BMessage& settings)
870ccf707d0SAndrew Lindesay {
871ccf707d0SAndrew Lindesay 	BString packageListViewMode;
872133ebab6SAndrew Lindesay 	if (settings.FindString(SETTING_PACKAGE_LIST_VIEW_MODE,
873ccf707d0SAndrew Lindesay 			&packageListViewMode) == B_OK) {
874ccf707d0SAndrew Lindesay 		fModel.SetPackageListViewMode(
875ccf707d0SAndrew Lindesay 			main_window_str_to_package_list_view_mode(packageListViewMode));
876ccf707d0SAndrew Lindesay 	}
877ccf707d0SAndrew Lindesay 
878ccf707d0SAndrew Lindesay 	bool showOption;
879363fc60bSAndrew Lindesay 
880133ebab6SAndrew Lindesay 	if (settings.FindBool(SETTING_SHOW_AVAILABLE_PACKAGES, &showOption) == B_OK)
881363fc60bSAndrew Lindesay 		fModel.PackageFilter()->SetShowAvailablePackages(showOption);
882133ebab6SAndrew Lindesay 	if (settings.FindBool(SETTING_SHOW_INSTALLED_PACKAGES, &showOption) == B_OK)
883363fc60bSAndrew Lindesay 		fModel.PackageFilter()->SetShowInstalledPackages(showOption);
884133ebab6SAndrew Lindesay 	if (settings.FindBool(SETTING_SHOW_DEVELOP_PACKAGES, &showOption) == B_OK)
885363fc60bSAndrew Lindesay 		fModel.PackageFilter()->SetShowDevelopPackages(showOption);
886133ebab6SAndrew Lindesay 	if (settings.FindBool(SETTING_SHOW_SOURCE_PACKAGES, &showOption) == B_OK)
887363fc60bSAndrew Lindesay 		fModel.PackageFilter()->SetShowSourcePackages(showOption);
888363fc60bSAndrew Lindesay 
889133ebab6SAndrew Lindesay 	if (settings.FindBool(SETTING_CAN_SHARE_ANONYMOUS_USER_DATA,
890133ebab6SAndrew Lindesay 			&showOption) == B_OK) {
891133ebab6SAndrew Lindesay 		fModel.SetCanShareAnonymousUsageData(showOption);
892133ebab6SAndrew Lindesay 	}
893133ebab6SAndrew Lindesay }
894133ebab6SAndrew Lindesay 
895133ebab6SAndrew Lindesay 
896133ebab6SAndrew Lindesay void
_MaybePromptCanShareAnonymousUserData(const BMessage & settings)897133ebab6SAndrew Lindesay MainWindow::_MaybePromptCanShareAnonymousUserData(const BMessage& settings)
898133ebab6SAndrew Lindesay {
899133ebab6SAndrew Lindesay 	bool showOption;
900133ebab6SAndrew Lindesay 	if (settings.FindBool(SETTING_CAN_SHARE_ANONYMOUS_USER_DATA,
901133ebab6SAndrew Lindesay 			&showOption) == B_NAME_NOT_FOUND) {
902133ebab6SAndrew Lindesay 		_PromptCanShareAnonymousUserData();
903133ebab6SAndrew Lindesay 	}
904133ebab6SAndrew Lindesay }
905133ebab6SAndrew Lindesay 
906133ebab6SAndrew Lindesay 
907133ebab6SAndrew Lindesay void
_PromptCanShareAnonymousUserData()908133ebab6SAndrew Lindesay MainWindow::_PromptCanShareAnonymousUserData()
909133ebab6SAndrew Lindesay {
910133ebab6SAndrew Lindesay 	BAlert* alert = new(std::nothrow) BAlert(
911133ebab6SAndrew Lindesay 		B_TRANSLATE("Sending anonymous usage data"),
912133ebab6SAndrew Lindesay 		B_TRANSLATE("Would it be acceptable to send anonymous usage data to the"
913133ebab6SAndrew Lindesay 			" HaikuDepotServer system from this computer? You can change your"
914133ebab6SAndrew Lindesay 			" preference in the \"Settings\" window later."),
915133ebab6SAndrew Lindesay 		B_TRANSLATE("No"),
916133ebab6SAndrew Lindesay 		B_TRANSLATE("Yes"));
917133ebab6SAndrew Lindesay 
918133ebab6SAndrew Lindesay 	int32 result = alert->Go();
919133ebab6SAndrew Lindesay 	fModel.SetCanShareAnonymousUsageData(1 == result);
920ccf707d0SAndrew Lindesay }
921ccf707d0SAndrew Lindesay 
922ccf707d0SAndrew Lindesay 
923ccf707d0SAndrew Lindesay void
_InitPreferredLanguage()924d668d227SAndrew Lindesay MainWindow::_InitPreferredLanguage()
925d668d227SAndrew Lindesay {
926d668d227SAndrew Lindesay 	LanguageRepository* repository = fModel.Languages();
927d668d227SAndrew Lindesay 	LanguageRef defaultLanguage = LocaleUtils::DeriveDefaultLanguage(repository);
928d668d227SAndrew Lindesay 	repository->AddLanguage(defaultLanguage);
929d668d227SAndrew Lindesay 	fModel.SetPreferredLanguage(defaultLanguage);
930d668d227SAndrew Lindesay }
931d668d227SAndrew Lindesay 
932d668d227SAndrew Lindesay 
933d668d227SAndrew Lindesay void
_AdoptModelControls()934c4199192SAndrew Lindesay MainWindow::_AdoptModelControls()
93504c9d578SStephan Aßmus {
9369883929bSAndrew Lindesay 	if (fSinglePackageMode)
9379883929bSAndrew Lindesay 		return;
9389883929bSAndrew Lindesay 
93904c9d578SStephan Aßmus 	BAutolock locker(fModel.Lock());
940363fc60bSAndrew Lindesay 	fShowAvailablePackagesItem->SetMarked(fModel.PackageFilter()->ShowAvailablePackages());
941363fc60bSAndrew Lindesay 	fShowInstalledPackagesItem->SetMarked(fModel.PackageFilter()->ShowInstalledPackages());
942363fc60bSAndrew Lindesay 	fShowSourcePackagesItem->SetMarked(fModel.PackageFilter()->ShowSourcePackages());
943363fc60bSAndrew Lindesay 	fShowDevelopPackagesItem->SetMarked(fModel.PackageFilter()->ShowDevelopPackages());
944da651104SStephan Aßmus 
945ccf707d0SAndrew Lindesay 	if (fModel.PackageListViewMode() == PROMINENT)
946ccf707d0SAndrew Lindesay 		fListTabs->Select(TAB_PROMINENT_PACKAGES);
9474fade61fSStephan Aßmus 	else
948ccf707d0SAndrew Lindesay 		fListTabs->Select(TAB_ALL_PACKAGES);
949b965ce70SHumdinger 
950b965ce70SHumdinger 	fFilterView->AdoptModel(fModel);
95104c9d578SStephan Aßmus }
95204c9d578SStephan Aßmus 
95304c9d578SStephan Aßmus 
95404c9d578SStephan Aßmus void
_AdoptModel()955c4199192SAndrew Lindesay MainWindow::_AdoptModel()
956c4199192SAndrew Lindesay {
957fa5c8097SAndrew Lindesay 	HDTRACE("adopting model to main window ui");
958c4199192SAndrew Lindesay 
959c4199192SAndrew Lindesay 	if (fSinglePackageMode)
960c4199192SAndrew Lindesay 		return;
961c4199192SAndrew Lindesay 
96205880d13SAndrew Lindesay 	std::vector<DepotInfoRef> depots = _CreateSnapshotOfDepots();
96305880d13SAndrew Lindesay 	std::vector<DepotInfoRef>::iterator it;
9640b69420bSAndrew Lindesay 
9650b69420bSAndrew Lindesay 	fFeaturedPackagesView->BeginAddRemove();
9660b69420bSAndrew Lindesay 
96705880d13SAndrew Lindesay 	for (it = depots.begin(); it != depots.end(); it++) {
96805880d13SAndrew Lindesay 		DepotInfoRef depotInfoRef = *it;
969d75b4d61SAndrew Lindesay 		for (int i = 0; i < depotInfoRef->CountPackages(); i++) {
970d75b4d61SAndrew Lindesay 			PackageInfoRef package = depotInfoRef->PackageAtIndex(i);
971d75b4d61SAndrew Lindesay 			_AddRemovePackageFromLists(package);
972d75b4d61SAndrew Lindesay 		}
973c4199192SAndrew Lindesay 	}
974c4199192SAndrew Lindesay 
9750b69420bSAndrew Lindesay 	fFeaturedPackagesView->EndAddRemove();
9760b69420bSAndrew Lindesay 
977c4199192SAndrew Lindesay 	_AdoptModelControls();
978c4199192SAndrew Lindesay }
979c4199192SAndrew Lindesay 
980c4199192SAndrew Lindesay 
981c4199192SAndrew Lindesay void
_AddRemovePackageFromLists(const PackageInfoRef & package)982c4199192SAndrew Lindesay MainWindow::_AddRemovePackageFromLists(const PackageInfoRef& package)
983c4199192SAndrew Lindesay {
984c4199192SAndrew Lindesay 	bool matches;
985c4199192SAndrew Lindesay 
986c4199192SAndrew Lindesay 	{
987c4199192SAndrew Lindesay 		AutoLocker<BLocker> modelLocker(fModel.Lock());
988363fc60bSAndrew Lindesay 		matches = fModel.PackageFilter()->Filter()->AcceptsPackage(package);
989c4199192SAndrew Lindesay 	}
990c4199192SAndrew Lindesay 
991c4199192SAndrew Lindesay 	if (matches) {
9928cc3ed34SAndrew Lindesay 		PackageClassificationInfoRef classification = package->PackageClassificationInfo();
9938cc3ed34SAndrew Lindesay 
9948cc3ed34SAndrew Lindesay 		if (classification.IsSet()) {
9958cc3ed34SAndrew Lindesay 			if (classification->IsProminent())
996c4199192SAndrew Lindesay 				fFeaturedPackagesView->AddPackage(package);
9978cc3ed34SAndrew Lindesay 		}
9988cc3ed34SAndrew Lindesay 
999c4199192SAndrew Lindesay 		fPackageListView->AddPackage(package);
1000c4199192SAndrew Lindesay 	} else {
1001c4199192SAndrew Lindesay 		fFeaturedPackagesView->RemovePackage(package);
1002c4199192SAndrew Lindesay 		fPackageListView->RemovePackage(package);
1003c4199192SAndrew Lindesay 	}
1004c4199192SAndrew Lindesay }
1005c4199192SAndrew Lindesay 
1006c4199192SAndrew Lindesay 
1007c4199192SAndrew Lindesay void
_SetupDelayedIncrementViewCounter(const PackageInfoRef package)100884674570SAndrew Lindesay MainWindow::_SetupDelayedIncrementViewCounter(const PackageInfoRef package) {
100984674570SAndrew Lindesay 	if (fIncrementViewCounterDelayedRunner != NULL) {
101084674570SAndrew Lindesay 		fIncrementViewCounterDelayedRunner->SetCount(0);
101184674570SAndrew Lindesay 		delete fIncrementViewCounterDelayedRunner;
101284674570SAndrew Lindesay 	}
101384674570SAndrew Lindesay 	BMessage message(MSG_INCREMENT_VIEW_COUNTER);
101484674570SAndrew Lindesay 	message.SetString("name", package->Name());
101584674570SAndrew Lindesay 	fIncrementViewCounterDelayedRunner =
101684674570SAndrew Lindesay 		new BMessageRunner(BMessenger(this), &message,
101784674570SAndrew Lindesay 			kIncrementViewCounterDelayMicros, 1);
101884674570SAndrew Lindesay 	if (fIncrementViewCounterDelayedRunner->InitCheck()
101984674570SAndrew Lindesay 			!= B_OK) {
102084674570SAndrew Lindesay 		HDERROR("unable to init the increment view counter");
102184674570SAndrew Lindesay 	}
102284674570SAndrew Lindesay }
102384674570SAndrew Lindesay 
102484674570SAndrew Lindesay 
102584674570SAndrew Lindesay void
_HandleIncrementViewCounter(const BMessage * message)102684674570SAndrew Lindesay MainWindow::_HandleIncrementViewCounter(const BMessage* message)
102784674570SAndrew Lindesay {
102884674570SAndrew Lindesay 	BString name;
102984674570SAndrew Lindesay 	if (message->FindString("name", &name) == B_OK) {
103084674570SAndrew Lindesay 		const PackageInfoRef& viewedPackage =
103184674570SAndrew Lindesay 			fPackageInfoView->Package();
103284674570SAndrew Lindesay 		if (viewedPackage.IsSet()) {
103384674570SAndrew Lindesay 			if (viewedPackage->Name() == name)
103484674570SAndrew Lindesay 				_IncrementViewCounter(viewedPackage);
103584674570SAndrew Lindesay 			else
103684674570SAndrew Lindesay 				HDINFO("incr. view counter; name mismatch");
103784674570SAndrew Lindesay 		} else
103884674570SAndrew Lindesay 			HDINFO("incr. view counter; no viewed pkg");
103984674570SAndrew Lindesay 	} else
104084674570SAndrew Lindesay 		HDERROR("incr. view counter; no name");
104184674570SAndrew Lindesay 	fIncrementViewCounterDelayedRunner->SetCount(0);
104284674570SAndrew Lindesay 	delete fIncrementViewCounterDelayedRunner;
104384674570SAndrew Lindesay 	fIncrementViewCounterDelayedRunner = NULL;
104484674570SAndrew Lindesay }
104584674570SAndrew Lindesay 
104684674570SAndrew Lindesay 
104784674570SAndrew Lindesay void
_IncrementViewCounter(const PackageInfoRef package)1048409af934SAndrew Lindesay MainWindow::_IncrementViewCounter(const PackageInfoRef package)
1049133ebab6SAndrew Lindesay {
1050133ebab6SAndrew Lindesay 	bool shouldIncrementViewCounter = false;
1051133ebab6SAndrew Lindesay 
1052133ebab6SAndrew Lindesay 	{
1053133ebab6SAndrew Lindesay 		AutoLocker<BLocker> modelLocker(fModel.Lock());
1054133ebab6SAndrew Lindesay 		bool canShareAnonymousUsageData = fModel.CanShareAnonymousUsageData();
1055*c0789628SAndrew Lindesay 		if (canShareAnonymousUsageData && !PackageUtils::Viewed(package)) {
1056*c0789628SAndrew Lindesay 			PackageLocalInfoRef localInfo = PackageUtils::NewLocalInfo(package);
1057*c0789628SAndrew Lindesay 			localInfo->SetViewed();
1058*c0789628SAndrew Lindesay 			package->SetLocalInfo(localInfo);
1059133ebab6SAndrew Lindesay 			shouldIncrementViewCounter = true;
1060133ebab6SAndrew Lindesay 		}
1061133ebab6SAndrew Lindesay 	}
1062133ebab6SAndrew Lindesay 
1063133ebab6SAndrew Lindesay 	if (shouldIncrementViewCounter) {
1064467ffecdSAugustin Cavalier 		ProcessCoordinator* incrementViewCoordinator =
1065133ebab6SAndrew Lindesay 			ProcessCoordinatorFactory::CreateIncrementViewCounter(
1066133ebab6SAndrew Lindesay 				&fModel, package);
1067467ffecdSAugustin Cavalier 		_AddProcessCoordinator(incrementViewCoordinator);
1068133ebab6SAndrew Lindesay 	}
1069133ebab6SAndrew Lindesay }
1070133ebab6SAndrew Lindesay 
1071133ebab6SAndrew Lindesay 
1072133ebab6SAndrew Lindesay void
_AdoptPackage(const PackageInfoRef & package)107304c9d578SStephan Aßmus MainWindow::_AdoptPackage(const PackageInfoRef& package)
107404c9d578SStephan Aßmus {
107575ba9dbfSStephan Aßmus 	{
107675ba9dbfSStephan Aßmus 		BAutolock locker(fModel.Lock());
107704c9d578SStephan Aßmus 		fPackageInfoView->SetPackage(package);
10781986ab9fSStephan Aßmus 
1079664372abSStephan Aßmus 		if (fFeaturedPackagesView != NULL)
1080664372abSStephan Aßmus 			fFeaturedPackagesView->SelectPackage(package);
10811986ab9fSStephan Aßmus 		if (fPackageListView != NULL)
10821986ab9fSStephan Aßmus 			fPackageListView->SelectPackage(package);
108375ba9dbfSStephan Aßmus 	}
108404c9d578SStephan Aßmus 
1085a9edb9bfSAndrew Lindesay 	_PopulatePackageAsync(false);
108604c9d578SStephan Aßmus }
108704c9d578SStephan Aßmus 
108804c9d578SStephan Aßmus 
108904c9d578SStephan Aßmus void
_ClearPackage()109004c9d578SStephan Aßmus MainWindow::_ClearPackage()
109104c9d578SStephan Aßmus {
109204c9d578SStephan Aßmus 	fPackageInfoView->Clear();
109304c9d578SStephan Aßmus }
109404c9d578SStephan Aßmus 
109504c9d578SStephan Aßmus 
109604c9d578SStephan Aßmus void
_StartBulkLoad(bool force)10973369e03dSAndrew Lindesay MainWindow::_StartBulkLoad(bool force)
109804c9d578SStephan Aßmus {
1099c4199192SAndrew Lindesay 	if (fFeaturedPackagesView != NULL)
1100c4199192SAndrew Lindesay 		fFeaturedPackagesView->Clear();
1101c4199192SAndrew Lindesay 	if (fPackageListView != NULL)
1102c4199192SAndrew Lindesay 		fPackageListView->Clear();
1103c4199192SAndrew Lindesay 	fPackageInfoView->Clear();
1104c4199192SAndrew Lindesay 
110510cd325cSAndrew Lindesay 	fRefreshRepositoriesItem->SetEnabled(false);
110610cd325cSAndrew Lindesay 	ProcessCoordinator* bulkLoadCoordinator =
110710cd325cSAndrew Lindesay 		ProcessCoordinatorFactory::CreateBulkLoadCoordinator(
1108409af934SAndrew Lindesay 			fPackageInfoListener, &fModel, force);
110910cd325cSAndrew Lindesay 	_AddProcessCoordinator(bulkLoadCoordinator);
111004c9d578SStephan Aßmus }
111104c9d578SStephan Aßmus 
111204c9d578SStephan Aßmus 
111304c9d578SStephan Aßmus void
_BulkLoadCompleteReceived(status_t errorStatus)111410cd325cSAndrew Lindesay MainWindow::_BulkLoadCompleteReceived(status_t errorStatus)
111504c9d578SStephan Aßmus {
111610cd325cSAndrew Lindesay 	if (errorStatus != B_OK) {
11173369e03dSAndrew Lindesay 		AppUtils::NotifySimpleError(
11181448ced0SHumdinger 			B_TRANSLATE("Package update error"),
11193369e03dSAndrew Lindesay 			B_TRANSLATE("While updating package data, a problem has arisen "
11203369e03dSAndrew Lindesay 				"that may cause data to be outdated or missing from the "
11213369e03dSAndrew Lindesay 				"application's display. Additional details regarding this "
11223369e03dSAndrew Lindesay 				"problem may be able to be obtained from the application "
1123b21c9447SAndrew Lindesay 				"logs."
1124b21c9447SAndrew Lindesay 				ALERT_MSG_LOGS_USER_GUIDE));
112504c9d578SStephan Aßmus 	}
112610cd325cSAndrew Lindesay 
11273369e03dSAndrew Lindesay 	fRefreshRepositoriesItem->SetEnabled(true);
112810cd325cSAndrew Lindesay 	_AdoptModel();
112910cd325cSAndrew Lindesay 	_UpdateAvailableRepositories();
1130ccf707d0SAndrew Lindesay 
1131ccf707d0SAndrew Lindesay 	// if after loading everything in, it transpires that there are no
1132ccf707d0SAndrew Lindesay 	// featured packages then the featured packages should be disabled
1133ccf707d0SAndrew Lindesay 	// and the user should be switched to the "all packages" view so
1134ccf707d0SAndrew Lindesay 	// that they are not presented with a blank window!
1135ccf707d0SAndrew Lindesay 
1136ccf707d0SAndrew Lindesay 	bool hasProminentPackages = fModel.HasAnyProminentPackages();
1137ccf707d0SAndrew Lindesay 	fListTabs->TabAt(TAB_PROMINENT_PACKAGES)->SetEnabled(hasProminentPackages);
1138ccf707d0SAndrew Lindesay 	if (!hasProminentPackages
1139ccf707d0SAndrew Lindesay 			&& fListTabs->Selection() == TAB_PROMINENT_PACKAGES) {
1140ccf707d0SAndrew Lindesay 		fModel.SetPackageListViewMode(ALL);
1141ccf707d0SAndrew Lindesay 		fListTabs->Select(TAB_ALL_PACKAGES);
1142ccf707d0SAndrew Lindesay 	}
114304c9d578SStephan Aßmus }
114404c9d578SStephan Aßmus 
114504c9d578SStephan Aßmus 
11463369e03dSAndrew Lindesay void
_NotifyWorkStatusClear()114710cd325cSAndrew Lindesay MainWindow::_NotifyWorkStatusClear()
114804c9d578SStephan Aßmus {
114910cd325cSAndrew Lindesay 	BMessage message(MSG_WORK_STATUS_CLEAR);
115010cd325cSAndrew Lindesay 	this->PostMessage(&message, this);
115110cd325cSAndrew Lindesay }
115210cd325cSAndrew Lindesay 
115310cd325cSAndrew Lindesay 
115410cd325cSAndrew Lindesay void
_HandleWorkStatusClear()115510cd325cSAndrew Lindesay MainWindow::_HandleWorkStatusClear()
115610cd325cSAndrew Lindesay {
115710cd325cSAndrew Lindesay 	fWorkStatusView->SetText("");
11583369e03dSAndrew Lindesay 	fWorkStatusView->SetIdle();
11593369e03dSAndrew Lindesay }
116004c9d578SStephan Aßmus 
116104c9d578SStephan Aßmus 
11623369e03dSAndrew Lindesay /*! Sends off a message to the Window so that it can change the status view
11633369e03dSAndrew Lindesay     on the front-end in the UI thread.
11643369e03dSAndrew Lindesay */
116504c9d578SStephan Aßmus 
11663369e03dSAndrew Lindesay void
_NotifyWorkStatusChange(const BString & text,float progress)11673369e03dSAndrew Lindesay MainWindow::_NotifyWorkStatusChange(const BString& text, float progress)
11683369e03dSAndrew Lindesay {
11693369e03dSAndrew Lindesay 	BMessage message(MSG_WORK_STATUS_CHANGE);
117004c9d578SStephan Aßmus 
11713369e03dSAndrew Lindesay 	if (!text.IsEmpty())
11723369e03dSAndrew Lindesay 		message.AddString(KEY_WORK_STATUS_TEXT, text);
11733369e03dSAndrew Lindesay 	message.AddFloat(KEY_WORK_STATUS_PROGRESS, progress);
117404c9d578SStephan Aßmus 
11753369e03dSAndrew Lindesay 	this->PostMessage(&message, this);
11763369e03dSAndrew Lindesay }
117704c9d578SStephan Aßmus 
11783369e03dSAndrew Lindesay 
1179f32d5c5cSAndrew Lindesay void
_HandleExternalPackageUpdateMessageReceived(const BMessage * message)1180f32d5c5cSAndrew Lindesay MainWindow::_HandleExternalPackageUpdateMessageReceived(const BMessage* message)
1181f32d5c5cSAndrew Lindesay {
1182f32d5c5cSAndrew Lindesay 	BStringList addedPackageNames;
1183f32d5c5cSAndrew Lindesay 	BStringList removedPackageNames;
1184f32d5c5cSAndrew Lindesay 
1185f32d5c5cSAndrew Lindesay 	if (message->FindStrings("added package names",
1186f32d5c5cSAndrew Lindesay 			&addedPackageNames) == B_OK) {
1187f32d5c5cSAndrew Lindesay 		addedPackageNames.Sort();
11880ebb9177SAndrew Lindesay 		AutoLocker<BLocker> locker(fModel.Lock());
11890ebb9177SAndrew Lindesay 		fModel.SetStateForPackagesByName(addedPackageNames, ACTIVATED);
1190f32d5c5cSAndrew Lindesay 	}
1191f32d5c5cSAndrew Lindesay 	else
1192f32d5c5cSAndrew Lindesay 		HDINFO("no [added package names] key in inbound message");
1193f32d5c5cSAndrew Lindesay 
1194f32d5c5cSAndrew Lindesay 	if (message->FindStrings("removed package names",
1195f32d5c5cSAndrew Lindesay 			&removedPackageNames) == B_OK) {
1196f32d5c5cSAndrew Lindesay 		removedPackageNames.Sort();
11970ebb9177SAndrew Lindesay 		AutoLocker<BLocker> locker(fModel.Lock());
11980ebb9177SAndrew Lindesay 		fModel.SetStateForPackagesByName(addedPackageNames, UNINSTALLED);
1199f32d5c5cSAndrew Lindesay 	} else
1200f32d5c5cSAndrew Lindesay 		HDINFO("no [removed package names] key in inbound message");
1201f32d5c5cSAndrew Lindesay }
1202f32d5c5cSAndrew Lindesay 
1203f32d5c5cSAndrew Lindesay 
12043369e03dSAndrew Lindesay void
_HandleWorkStatusChangeMessageReceived(const BMessage * message)12053369e03dSAndrew Lindesay MainWindow::_HandleWorkStatusChangeMessageReceived(const BMessage* message)
12063369e03dSAndrew Lindesay {
12079883929bSAndrew Lindesay 	if (fWorkStatusView == NULL)
12089883929bSAndrew Lindesay 		return;
12099883929bSAndrew Lindesay 
12103369e03dSAndrew Lindesay 	BString text;
12113369e03dSAndrew Lindesay 	float progress;
12123369e03dSAndrew Lindesay 
12133369e03dSAndrew Lindesay 	if (message->FindString(KEY_WORK_STATUS_TEXT, &text) == B_OK)
12143369e03dSAndrew Lindesay 		fWorkStatusView->SetText(text);
12153369e03dSAndrew Lindesay 
1216a18f873fSAndrew Lindesay 	if (message->FindFloat(KEY_WORK_STATUS_PROGRESS, &progress) == B_OK) {
1217a18f873fSAndrew Lindesay 		if (progress < 0.0f)
1218a18f873fSAndrew Lindesay 			fWorkStatusView->SetBusy();
1219a18f873fSAndrew Lindesay 		else
12203369e03dSAndrew Lindesay 			fWorkStatusView->SetProgress(progress);
1221a18f873fSAndrew Lindesay 	} else {
1222a18f873fSAndrew Lindesay 		HDERROR("work status change missing progress on update message");
1223a18f873fSAndrew Lindesay 		fWorkStatusView->SetProgress(0.0f);
122404c9d578SStephan Aßmus 	}
122504c9d578SStephan Aßmus }
122604c9d578SStephan Aßmus 
122704c9d578SStephan Aßmus 
12288266f4d7SAugustin Cavalier /*! Initially only superficial data is loaded from the server into the data
12298266f4d7SAugustin Cavalier 	model of the packages.  When the package is viewed, additional data needs
12308266f4d7SAugustin Cavalier 	to be populated including ratings.
12318266f4d7SAugustin Cavalier 
12328266f4d7SAugustin Cavalier 	This method will cause the package to have its data refreshed from
1233a9edb9bfSAndrew Lindesay 	the server application.  The refresh happens in the background; this method
1234a9edb9bfSAndrew Lindesay 	is asynchronous.
1235a9edb9bfSAndrew Lindesay */
1236a9edb9bfSAndrew Lindesay 
1237a9edb9bfSAndrew Lindesay void
_PopulatePackageAsync(bool forcePopulate)1238a9edb9bfSAndrew Lindesay MainWindow::_PopulatePackageAsync(bool forcePopulate)
1239a9edb9bfSAndrew Lindesay {
12408266f4d7SAugustin Cavalier 	const PackageInfoRef package = fPackageInfoView->Package();
1241a9edb9bfSAndrew Lindesay 
12428266f4d7SAugustin Cavalier 	if (!fModel.CanPopulatePackage(package))
12438266f4d7SAugustin Cavalier 		return;
12448266f4d7SAugustin Cavalier 
12458266f4d7SAugustin Cavalier 	const char* packageNameStr = package->Name().String();
12468266f4d7SAugustin Cavalier 
1247c65ff9f1SAndrew Lindesay 	PackageLocalizedTextRef localized = package->LocalizedText();
1248c65ff9f1SAndrew Lindesay 
1249c65ff9f1SAndrew Lindesay 	if (localized.IsSet()) {
1250c65ff9f1SAndrew Lindesay 		if (localized->HasChangelog() && (forcePopulate || localized->Changelog().IsEmpty())) {
12518266f4d7SAugustin Cavalier 			_AddProcessCoordinator(
12528266f4d7SAugustin Cavalier 				ProcessCoordinatorFactory::PopulatePkgChangelogCoordinator(&fModel, package));
12538266f4d7SAugustin Cavalier 			HDINFO("pkg [%s] will have changelog updated from server.", packageNameStr);
12548266f4d7SAugustin Cavalier 		} else {
12558266f4d7SAugustin Cavalier 			HDDEBUG("pkg [%s] not have changelog updated from server.", packageNameStr);
1256a9edb9bfSAndrew Lindesay 		}
1257c65ff9f1SAndrew Lindesay 	}
1258a9edb9bfSAndrew Lindesay 
12594b3c808eSAndrew Lindesay 	if (forcePopulate || RatingUtils::ShouldTryPopulateUserRatings(package->UserRatingInfo())) {
12608266f4d7SAugustin Cavalier 		_AddProcessCoordinator(
12618266f4d7SAugustin Cavalier 			ProcessCoordinatorFactory::PopulatePkgUserRatingsCoordinator(&fModel, package));
12628266f4d7SAugustin Cavalier 		HDINFO("pkg [%s] will have user ratings updated from server.", packageNameStr);
12638266f4d7SAugustin Cavalier 	} else {
12648266f4d7SAugustin Cavalier 		HDDEBUG("pkg [%s] not have user ratings updated from server.", packageNameStr);
126504c9d578SStephan Aßmus 	}
126604c9d578SStephan Aßmus }
126704c9d578SStephan Aßmus 
126804c9d578SStephan Aßmus 
126904c9d578SStephan Aßmus void
_OpenSettingsWindow()1270133ebab6SAndrew Lindesay MainWindow::_OpenSettingsWindow()
1271133ebab6SAndrew Lindesay {
1272133ebab6SAndrew Lindesay 	SettingsWindow* window = new SettingsWindow(this, &fModel);
1273133ebab6SAndrew Lindesay 	window->Show();
1274133ebab6SAndrew Lindesay }
1275133ebab6SAndrew Lindesay 
1276133ebab6SAndrew Lindesay 
1277133ebab6SAndrew Lindesay void
_OpenLoginWindow(const BMessage & onSuccessMessage)12781bbda92dSStephan Aßmus MainWindow::_OpenLoginWindow(const BMessage& onSuccessMessage)
127904c9d578SStephan Aßmus {
128004c9d578SStephan Aßmus 	UserLoginWindow* window = new UserLoginWindow(this,
128104c9d578SStephan Aßmus 		BRect(0, 0, 500, 400), fModel);
12821bbda92dSStephan Aßmus 
12831bbda92dSStephan Aßmus 	if (onSuccessMessage.what != 0)
12841bbda92dSStephan Aßmus 		window->SetOnSuccessMessage(BMessenger(this), onSuccessMessage);
12851bbda92dSStephan Aßmus 
128604c9d578SStephan Aßmus 	window->Show();
128704c9d578SStephan Aßmus }
128804c9d578SStephan Aßmus 
12898f03a0f9SStephan Aßmus 
12908f03a0f9SStephan Aßmus void
_StartUserVerify()129110cd325cSAndrew Lindesay MainWindow::_StartUserVerify()
129210cd325cSAndrew Lindesay {
129310cd325cSAndrew Lindesay 	if (!fModel.Nickname().IsEmpty()) {
129410cd325cSAndrew Lindesay 		_AddProcessCoordinator(
129510cd325cSAndrew Lindesay 			ProcessCoordinatorFactory::CreateUserDetailVerifierCoordinator(
129610cd325cSAndrew Lindesay 				this,
129710cd325cSAndrew Lindesay 					// UserDetailVerifierListener
129810cd325cSAndrew Lindesay 				&fModel) );
129910cd325cSAndrew Lindesay 	}
130010cd325cSAndrew Lindesay }
130110cd325cSAndrew Lindesay 
130210cd325cSAndrew Lindesay 
130310cd325cSAndrew Lindesay void
_UpdateAuthorization()13048f03a0f9SStephan Aßmus MainWindow::_UpdateAuthorization()
13058f03a0f9SStephan Aßmus {
1306d2d4866dSAndrew Lindesay 	BString nickname(fModel.Nickname());
1307d2d4866dSAndrew Lindesay 	bool hasUser = !nickname.IsEmpty();
1308e0a26dceSStephan Aßmus 
13096d519fd1SStephan Aßmus 	if (fLogOutItem != NULL)
1310e0a26dceSStephan Aßmus 		fLogOutItem->SetEnabled(hasUser);
1311d2d4866dSAndrew Lindesay 	if (fUsersUserUsageConditionsMenuItem != NULL)
1312d2d4866dSAndrew Lindesay 		fUsersUserUsageConditionsMenuItem->SetEnabled(hasUser);
1313e0a26dceSStephan Aßmus 	if (fLogInItem != NULL) {
1314e0a26dceSStephan Aßmus 		if (hasUser)
1315e0a26dceSStephan Aßmus 			fLogInItem->SetLabel(B_TRANSLATE("Switch account" B_UTF8_ELLIPSIS));
1316e0a26dceSStephan Aßmus 		else
1317e0a26dceSStephan Aßmus 			fLogInItem->SetLabel(B_TRANSLATE("Log in" B_UTF8_ELLIPSIS));
1318e0a26dceSStephan Aßmus 	}
1319e0a26dceSStephan Aßmus 
1320e0a26dceSStephan Aßmus 	if (fUserMenu != NULL) {
1321e0a26dceSStephan Aßmus 		BString label;
1322d2d4866dSAndrew Lindesay 		if (hasUser) {
1323e0a26dceSStephan Aßmus 			label = B_TRANSLATE("Logged in as %User%");
1324d2d4866dSAndrew Lindesay 			label.ReplaceAll("%User%", nickname);
1325d2d4866dSAndrew Lindesay 		} else {
1326d2d4866dSAndrew Lindesay 			label = B_TRANSLATE("Not logged in");
1327e0a26dceSStephan Aßmus 		}
1328e0a26dceSStephan Aßmus 		fUserMenu->Superitem()->SetLabel(label);
1329e0a26dceSStephan Aßmus 	}
13308f03a0f9SStephan Aßmus }
13311bbda92dSStephan Aßmus 
13321bbda92dSStephan Aßmus 
13331bbda92dSStephan Aßmus void
_UpdateAvailableRepositories()1334b965ce70SHumdinger MainWindow::_UpdateAvailableRepositories()
1335b965ce70SHumdinger {
1336b965ce70SHumdinger 	fRepositoryMenu->RemoveItems(0, fRepositoryMenu->CountItems(), true);
1337b965ce70SHumdinger 
1338b965ce70SHumdinger 	fRepositoryMenu->AddItem(new BMenuItem(B_TRANSLATE("All repositories"),
1339b965ce70SHumdinger 		new BMessage(MSG_DEPOT_SELECTED)));
1340b965ce70SHumdinger 
1341b965ce70SHumdinger 	fRepositoryMenu->AddItem(new BSeparatorItem());
1342b965ce70SHumdinger 
1343b965ce70SHumdinger 	bool foundSelectedDepot = false;
134405880d13SAndrew Lindesay 	std::vector<DepotInfoRef> depots = _CreateSnapshotOfDepots();
134505880d13SAndrew Lindesay 	std::vector<DepotInfoRef>::iterator it;
1346d13c3d89SAndrew Lindesay 
134705880d13SAndrew Lindesay 	for (it = depots.begin(); it != depots.end(); it++) {
134805880d13SAndrew Lindesay 		DepotInfoRef depot = *it;
134905880d13SAndrew Lindesay 
135005880d13SAndrew Lindesay 		if (depot->Name().Length() != 0) {
1351b965ce70SHumdinger 			BMessage* message = new BMessage(MSG_DEPOT_SELECTED);
135205880d13SAndrew Lindesay 			message->AddString("name", depot->Name());
135305880d13SAndrew Lindesay 			BMenuItem* item = new(std::nothrow) BMenuItem(depot->Name(), message);
135405880d13SAndrew Lindesay 
135505880d13SAndrew Lindesay 			if (item == NULL)
135605880d13SAndrew Lindesay 				HDFATAL("memory exhaustion");
135705880d13SAndrew Lindesay 
1358b965ce70SHumdinger 			fRepositoryMenu->AddItem(item);
1359b965ce70SHumdinger 
1360363fc60bSAndrew Lindesay 			if (depot->Name() == fModel.PackageFilter()->DepotName()) {
1361b965ce70SHumdinger 				item->SetMarked(true);
1362b965ce70SHumdinger 				foundSelectedDepot = true;
1363b965ce70SHumdinger 			}
1364b965ce70SHumdinger 		}
1365d13c3d89SAndrew Lindesay 	}
1366b965ce70SHumdinger 
1367b965ce70SHumdinger 	if (!foundSelectedDepot)
1368b965ce70SHumdinger 		fRepositoryMenu->ItemAt(0)->SetMarked(true);
1369b965ce70SHumdinger }
1370b965ce70SHumdinger 
1371b965ce70SHumdinger 
1372a9edb9bfSAndrew Lindesay bool
_SelectedPackageHasWebAppRepositoryCode()1373a9edb9bfSAndrew Lindesay MainWindow::_SelectedPackageHasWebAppRepositoryCode()
1374a9edb9bfSAndrew Lindesay {
1375a9edb9bfSAndrew Lindesay 	const PackageInfoRef& package = fPackageInfoView->Package();
13766ab878c0SAndrew Lindesay 	const BString depotName = package->DepotName();
1377a9edb9bfSAndrew Lindesay 
13786ab878c0SAndrew Lindesay 	if (depotName.IsEmpty()) {
1379fa5c8097SAndrew Lindesay 		HDDEBUG("the package [%s] has no depot name", package->Name().String());
13806ab878c0SAndrew Lindesay 	} else {
13816ab878c0SAndrew Lindesay 		const DepotInfo* depot = fModel.DepotForName(depotName);
1382a9edb9bfSAndrew Lindesay 
13836ab878c0SAndrew Lindesay 		if (depot == NULL) {
1384f96d1f4dSAndrew Lindesay 			HDINFO("the depot [%s] was not able to be found",
1385fa5c8097SAndrew Lindesay 				depotName.String());
13866ab878c0SAndrew Lindesay 		} else {
13876ab878c0SAndrew Lindesay 			BString repositoryCode = depot->WebAppRepositoryCode();
1388a9edb9bfSAndrew Lindesay 
13896ab878c0SAndrew Lindesay 			if (repositoryCode.IsEmpty()) {
1390f96d1f4dSAndrew Lindesay 				HDINFO("the depot [%s] has no web app repository code",
1391fa5c8097SAndrew Lindesay 					depotName.String());
1392fa5c8097SAndrew Lindesay 			} else
13936ab878c0SAndrew Lindesay 				return true;
13946ab878c0SAndrew Lindesay 		}
13956ab878c0SAndrew Lindesay 	}
13966ab878c0SAndrew Lindesay 
13976ab878c0SAndrew Lindesay 	return false;
1398a9edb9bfSAndrew Lindesay }
1399a9edb9bfSAndrew Lindesay 
1400a9edb9bfSAndrew Lindesay 
1401b965ce70SHumdinger void
_RatePackage()14021bbda92dSStephan Aßmus MainWindow::_RatePackage()
14031bbda92dSStephan Aßmus {
1404a9edb9bfSAndrew Lindesay 	if (!_SelectedPackageHasWebAppRepositoryCode()) {
1405a9edb9bfSAndrew Lindesay 		BAlert* alert = new(std::nothrow) BAlert(
1406cbadcae1SHumdinger 			B_TRANSLATE("Rating not possible"),
1407cbadcae1SHumdinger 			B_TRANSLATE("This package doesn't seem to be on the HaikuDepot "
1408cbadcae1SHumdinger 				"Server, so it's not possible to create a new rating "
1409cbadcae1SHumdinger 				"or edit an existing rating."),
1410a9edb9bfSAndrew Lindesay 			B_TRANSLATE("OK"));
1411a9edb9bfSAndrew Lindesay 		alert->Go();
1412a9edb9bfSAndrew Lindesay     	return;
1413a9edb9bfSAndrew Lindesay 	}
1414a9edb9bfSAndrew Lindesay 
1415d2d4866dSAndrew Lindesay 	if (fModel.Nickname().IsEmpty()) {
14161bbda92dSStephan Aßmus 		BAlert* alert = new(std::nothrow) BAlert(
14171bbda92dSStephan Aßmus 			B_TRANSLATE("Not logged in"),
14181bbda92dSStephan Aßmus 			B_TRANSLATE("You need to be logged into an account before you "
14191bbda92dSStephan Aßmus 				"can rate packages."),
14201bbda92dSStephan Aßmus 			B_TRANSLATE("Cancel"),
14211bbda92dSStephan Aßmus 			B_TRANSLATE("Login or Create account"));
14221bbda92dSStephan Aßmus 
14231bbda92dSStephan Aßmus 		if (alert == NULL)
14241bbda92dSStephan Aßmus 			return;
14251bbda92dSStephan Aßmus 
14261bbda92dSStephan Aßmus 		int32 choice = alert->Go();
14271bbda92dSStephan Aßmus 		if (choice == 1)
14281bbda92dSStephan Aßmus 			_OpenLoginWindow(BMessage(MSG_RATE_PACKAGE));
14291bbda92dSStephan Aßmus 		return;
14301bbda92dSStephan Aßmus 	}
14311bbda92dSStephan Aßmus 
14321bbda92dSStephan Aßmus 	// TODO: Allow only one RatePackageWindow
14331bbda92dSStephan Aßmus 	// TODO: Mechanism for remembering the window frame
14341bbda92dSStephan Aßmus 	RatePackageWindow* window = new RatePackageWindow(this,
14351bbda92dSStephan Aßmus 		BRect(0, 0, 500, 400), fModel);
14361bbda92dSStephan Aßmus 	window->SetPackage(fPackageInfoView->Package());
14371bbda92dSStephan Aßmus 	window->Show();
14381bbda92dSStephan Aßmus }
1439d5ef985eSStephan Aßmus 
1440d5ef985eSStephan Aßmus 
1441d5ef985eSStephan Aßmus void
_ShowScreenshot()1442d5ef985eSStephan Aßmus MainWindow::_ShowScreenshot()
1443d5ef985eSStephan Aßmus {
1444d5ef985eSStephan Aßmus 	// TODO: Mechanism for remembering the window frame
1445d5ef985eSStephan Aßmus 	if (fScreenshotWindow == NULL)
144688af15cfSAndrew Lindesay 		fScreenshotWindow = new ScreenshotWindow(this, BRect(0, 0, 500, 400), &fModel);
1447d5ef985eSStephan Aßmus 
1448d5ef985eSStephan Aßmus 	if (fScreenshotWindow->LockWithTimeout(1000) != B_OK)
1449d5ef985eSStephan Aßmus 		return;
1450d5ef985eSStephan Aßmus 
1451d5ef985eSStephan Aßmus 	fScreenshotWindow->SetPackage(fPackageInfoView->Package());
1452d5ef985eSStephan Aßmus 
1453d5ef985eSStephan Aßmus 	if (fScreenshotWindow->IsHidden())
1454d5ef985eSStephan Aßmus 		fScreenshotWindow->Show();
1455d5ef985eSStephan Aßmus 	else
1456d5ef985eSStephan Aßmus 		fScreenshotWindow->Activate();
1457d5ef985eSStephan Aßmus 
1458d5ef985eSStephan Aßmus 	fScreenshotWindow->Unlock();
1459d5ef985eSStephan Aßmus }
146001339a54SAndrew Lindesay 
146101339a54SAndrew Lindesay 
146201339a54SAndrew Lindesay void
_ViewUserUsageConditions(UserUsageConditionsSelectionMode mode)1463d2d4866dSAndrew Lindesay MainWindow::_ViewUserUsageConditions(
1464d2d4866dSAndrew Lindesay 	UserUsageConditionsSelectionMode mode)
146501339a54SAndrew Lindesay {
146601339a54SAndrew Lindesay 	UserUsageConditionsWindow* window = new UserUsageConditionsWindow(
1467d2d4866dSAndrew Lindesay 		fModel, mode);
146801339a54SAndrew Lindesay 	window->Show();
146901339a54SAndrew Lindesay }
147010cd325cSAndrew Lindesay 
147110cd325cSAndrew Lindesay 
147210cd325cSAndrew Lindesay void
UserCredentialsFailed()147310cd325cSAndrew Lindesay MainWindow::UserCredentialsFailed()
147410cd325cSAndrew Lindesay {
147510cd325cSAndrew Lindesay 	BString message = B_TRANSLATE("The password previously "
147610cd325cSAndrew Lindesay 		"supplied for the user [%Nickname%] is not currently "
147710cd325cSAndrew Lindesay 		"valid. The user will be logged-out of this application "
147810cd325cSAndrew Lindesay 		"and you should login again with your updated password.");
147910cd325cSAndrew Lindesay 	message.ReplaceAll("%Nickname%", fModel.Nickname());
148010cd325cSAndrew Lindesay 
148110cd325cSAndrew Lindesay 	AppUtils::NotifySimpleError(B_TRANSLATE("Login issue"),
148210cd325cSAndrew Lindesay 		message);
148310cd325cSAndrew Lindesay 
148410cd325cSAndrew Lindesay 	{
148510cd325cSAndrew Lindesay 		AutoLocker<BLocker> locker(fModel.Lock());
148610cd325cSAndrew Lindesay 		fModel.SetNickname("");
148710cd325cSAndrew Lindesay 	}
148810cd325cSAndrew Lindesay }
148910cd325cSAndrew Lindesay 
149010cd325cSAndrew Lindesay 
149110cd325cSAndrew Lindesay /*! \brief This method is invoked from the UserDetailVerifierProcess on a
149210cd325cSAndrew Lindesay 		   background thread.  For this reason it lodges a message into itself
149310cd325cSAndrew Lindesay 		   which can then be handled on the main thread.
149410cd325cSAndrew Lindesay */
149510cd325cSAndrew Lindesay 
149610cd325cSAndrew Lindesay void
UserUsageConditionsNotLatest(const UserDetail & userDetail)149710cd325cSAndrew Lindesay MainWindow::UserUsageConditionsNotLatest(const UserDetail& userDetail)
149810cd325cSAndrew Lindesay {
149910cd325cSAndrew Lindesay 	BMessage message(MSG_USER_USAGE_CONDITIONS_NOT_LATEST);
150010cd325cSAndrew Lindesay 	BMessage detailsMessage;
150110cd325cSAndrew Lindesay 	if (userDetail.Archive(&detailsMessage, true) != B_OK
150210cd325cSAndrew Lindesay 			|| message.AddMessage("userDetail", &detailsMessage) != B_OK) {
1503fa5c8097SAndrew Lindesay 		HDERROR("unable to archive the user detail into a message");
150410cd325cSAndrew Lindesay 	}
150510cd325cSAndrew Lindesay 	else
150610cd325cSAndrew Lindesay 		BMessenger(this).SendMessage(&message);
150710cd325cSAndrew Lindesay }
150810cd325cSAndrew Lindesay 
150910cd325cSAndrew Lindesay 
151010cd325cSAndrew Lindesay void
_HandleUserUsageConditionsNotLatest(const UserDetail & userDetail)151110cd325cSAndrew Lindesay MainWindow::_HandleUserUsageConditionsNotLatest(
151210cd325cSAndrew Lindesay 	const UserDetail& userDetail)
151310cd325cSAndrew Lindesay {
151410cd325cSAndrew Lindesay 	ToLatestUserUsageConditionsWindow* window =
151510cd325cSAndrew Lindesay 		new ToLatestUserUsageConditionsWindow(this, fModel, userDetail);
151610cd325cSAndrew Lindesay 	window->Show();
151710cd325cSAndrew Lindesay }
151810cd325cSAndrew Lindesay 
151910cd325cSAndrew Lindesay 
152010cd325cSAndrew Lindesay void
_AddProcessCoordinator(ProcessCoordinator * item)152110cd325cSAndrew Lindesay MainWindow::_AddProcessCoordinator(ProcessCoordinator* item)
152210cd325cSAndrew Lindesay {
152310cd325cSAndrew Lindesay 	AutoLocker<BLocker> lock(&fCoordinatorLock);
152410cd325cSAndrew Lindesay 
152595c7b018SAndrew Lindesay 	if (fShouldCloseWhenNoProcessesToCoordinate) {
152695c7b018SAndrew Lindesay 		HDINFO("system shutting down --> new process coordinator [%s] rejected",
152795c7b018SAndrew Lindesay 			item->Name().String());
152895c7b018SAndrew Lindesay 		return;
152995c7b018SAndrew Lindesay 	}
153095c7b018SAndrew Lindesay 
1531a18f873fSAndrew Lindesay 	item->SetListener(this);
1532a18f873fSAndrew Lindesay 
1533409af934SAndrew Lindesay 	if (fCoordinator == NULL) {
153410cd325cSAndrew Lindesay 		if (acquire_sem(fCoordinatorRunningSem) != B_OK)
153510cd325cSAndrew Lindesay 			debugger("unable to acquire the process coordinator sem");
1536f96d1f4dSAndrew Lindesay 		HDINFO("adding and starting a process coordinator [%s]",
1537fa5c8097SAndrew Lindesay 			item->Name().String());
1538409af934SAndrew Lindesay 		delete fCoordinator;
1539409af934SAndrew Lindesay 		fCoordinator = item;
154010cd325cSAndrew Lindesay 		fCoordinator->Start();
15417d7de135SAugustin Cavalier 	} else {
1542f96d1f4dSAndrew Lindesay 		HDINFO("adding process coordinator [%s] to the queue",
154310cd325cSAndrew Lindesay 			item->Name().String());
154410cd325cSAndrew Lindesay 		fCoordinatorQueue.push(item);
154510cd325cSAndrew Lindesay 	}
154610cd325cSAndrew Lindesay }
154710cd325cSAndrew Lindesay 
154810cd325cSAndrew Lindesay 
154910cd325cSAndrew Lindesay void
_SpinUntilProcessCoordinatorComplete()155010cd325cSAndrew Lindesay MainWindow::_SpinUntilProcessCoordinatorComplete()
155110cd325cSAndrew Lindesay {
155210cd325cSAndrew Lindesay 	while (true) {
155310cd325cSAndrew Lindesay 		if (acquire_sem(fCoordinatorRunningSem) != B_OK)
155410cd325cSAndrew Lindesay 			debugger("unable to acquire the process coordinator sem");
155510cd325cSAndrew Lindesay 		if (release_sem(fCoordinatorRunningSem) != B_OK)
155610cd325cSAndrew Lindesay 			debugger("unable to release the process coordinator sem");
155710cd325cSAndrew Lindesay 		{
155810cd325cSAndrew Lindesay 			AutoLocker<BLocker> lock(&fCoordinatorLock);
1559409af934SAndrew Lindesay 			if (fCoordinator == NULL)
156010cd325cSAndrew Lindesay 				return;
156110cd325cSAndrew Lindesay 		}
156210cd325cSAndrew Lindesay 	}
156310cd325cSAndrew Lindesay }
156410cd325cSAndrew Lindesay 
156510cd325cSAndrew Lindesay 
156610cd325cSAndrew Lindesay void
_StopProcessCoordinators()156710cd325cSAndrew Lindesay MainWindow::_StopProcessCoordinators()
156810cd325cSAndrew Lindesay {
156995c7b018SAndrew Lindesay 	HDINFO("will stop all queued process coordinators");
157010cd325cSAndrew Lindesay 	AutoLocker<BLocker> lock(&fCoordinatorLock);
157110cd325cSAndrew Lindesay 
157210cd325cSAndrew Lindesay 	while (!fCoordinatorQueue.empty()) {
1573409af934SAndrew Lindesay 		ProcessCoordinator* processCoordinator
1574f96d1f4dSAndrew Lindesay 			= fCoordinatorQueue.front();
1575f96d1f4dSAndrew Lindesay 		HDINFO("will drop queued process coordinator [%s]",
1576fa5c8097SAndrew Lindesay 			processCoordinator->Name().String());
157710cd325cSAndrew Lindesay 		fCoordinatorQueue.pop();
1578409af934SAndrew Lindesay 		delete processCoordinator;
157910cd325cSAndrew Lindesay 	}
158010cd325cSAndrew Lindesay 
1581409af934SAndrew Lindesay 	if (fCoordinator != NULL)
158295c7b018SAndrew Lindesay 		fCoordinator->RequestStop();
158310cd325cSAndrew Lindesay }
158410cd325cSAndrew Lindesay 
158510cd325cSAndrew Lindesay 
158610cd325cSAndrew Lindesay /*! This method is called when there is some change in the bulk load process
158710cd325cSAndrew Lindesay 	or other process coordinator.
158810cd325cSAndrew Lindesay 	A change may mean that a new process has started / stopped etc... or it
158910cd325cSAndrew Lindesay 	may mean that the entire coordinator has finished.
159010cd325cSAndrew Lindesay */
159110cd325cSAndrew Lindesay 
159210cd325cSAndrew Lindesay void
CoordinatorChanged(ProcessCoordinatorState & coordinatorState)159310cd325cSAndrew Lindesay MainWindow::CoordinatorChanged(ProcessCoordinatorState& coordinatorState)
159410cd325cSAndrew Lindesay {
1595409af934SAndrew Lindesay 	BMessage message(MSG_PROCESS_COORDINATOR_CHANGED);
1596409af934SAndrew Lindesay 	if (coordinatorState.Archive(&message, true) != B_OK) {
1597409af934SAndrew Lindesay 		HDFATAL("unable to archive message when the process coordinator"
1598409af934SAndrew Lindesay 			" has changed");
1599409af934SAndrew Lindesay 	}
1600409af934SAndrew Lindesay 	BMessenger(this).SendMessage(&message);
1601409af934SAndrew Lindesay }
1602409af934SAndrew Lindesay 
1603409af934SAndrew Lindesay 
1604409af934SAndrew Lindesay void
_HandleProcessCoordinatorChanged(ProcessCoordinatorState & coordinatorState)1605409af934SAndrew Lindesay MainWindow::_HandleProcessCoordinatorChanged(ProcessCoordinatorState& coordinatorState)
1606409af934SAndrew Lindesay {
160710cd325cSAndrew Lindesay 	AutoLocker<BLocker> lock(&fCoordinatorLock);
160810cd325cSAndrew Lindesay 
1609409af934SAndrew Lindesay 	if (fCoordinator->Identifier()
1610409af934SAndrew Lindesay 			== coordinatorState.ProcessCoordinatorIdentifier()) {
161110cd325cSAndrew Lindesay 		if (!coordinatorState.IsRunning()) {
161210cd325cSAndrew Lindesay 			if (release_sem(fCoordinatorRunningSem) != B_OK)
161310cd325cSAndrew Lindesay 				debugger("unable to release the process coordinator sem");
1614f96d1f4dSAndrew Lindesay 			HDINFO("process coordinator [%s] did complete",
1615fa5c8097SAndrew Lindesay 				fCoordinator->Name().String());
161610cd325cSAndrew Lindesay 			// complete the last one that just finished
161710cd325cSAndrew Lindesay 			BMessage* message = fCoordinator->Message();
161810cd325cSAndrew Lindesay 
161910cd325cSAndrew Lindesay 			if (message != NULL) {
162010cd325cSAndrew Lindesay 				BMessenger messenger(this);
162110cd325cSAndrew Lindesay 				message->AddInt64(KEY_ERROR_STATUS,
162210cd325cSAndrew Lindesay 					(int64) fCoordinator->ErrorStatus());
162310cd325cSAndrew Lindesay 				messenger.SendMessage(message);
162410cd325cSAndrew Lindesay 			}
162510cd325cSAndrew Lindesay 
16263538133fSAndrew Lindesay 			HDDEBUG("process coordinator report;\n---\n%s\n----",
16273538133fSAndrew Lindesay 				fCoordinator->LogReport().String());
16283538133fSAndrew Lindesay 
1629409af934SAndrew Lindesay 			delete fCoordinator;
1630409af934SAndrew Lindesay 			fCoordinator = NULL;
163110cd325cSAndrew Lindesay 
163210cd325cSAndrew Lindesay 			// now schedule the next one.
163310cd325cSAndrew Lindesay 			if (!fCoordinatorQueue.empty()) {
163410cd325cSAndrew Lindesay 				if (acquire_sem(fCoordinatorRunningSem) != B_OK)
163510cd325cSAndrew Lindesay 					debugger("unable to acquire the process coordinator sem");
163610cd325cSAndrew Lindesay 				fCoordinator = fCoordinatorQueue.front();
1637f96d1f4dSAndrew Lindesay 				HDINFO("starting next process coordinator [%s]",
163810cd325cSAndrew Lindesay 					fCoordinator->Name().String());
163910cd325cSAndrew Lindesay 				fCoordinatorQueue.pop();
164010cd325cSAndrew Lindesay 				fCoordinator->Start();
164110cd325cSAndrew Lindesay 			}
164210cd325cSAndrew Lindesay 			else {
164310cd325cSAndrew Lindesay 				_NotifyWorkStatusClear();
164495c7b018SAndrew Lindesay 				if (fShouldCloseWhenNoProcessesToCoordinate) {
164595c7b018SAndrew Lindesay 					HDINFO("no more processes to coord --> will quit");
164695c7b018SAndrew Lindesay 					BMessage message(B_QUIT_REQUESTED);
164795c7b018SAndrew Lindesay 					PostMessage(&message);
164895c7b018SAndrew Lindesay 				}
164910cd325cSAndrew Lindesay 			}
165010cd325cSAndrew Lindesay 		}
165110cd325cSAndrew Lindesay 		else {
165210cd325cSAndrew Lindesay 			_NotifyWorkStatusChange(coordinatorState.Message(),
165310cd325cSAndrew Lindesay 				coordinatorState.Progress());
165410cd325cSAndrew Lindesay 				// show the progress to the user.
165510cd325cSAndrew Lindesay 		}
165695c7b018SAndrew Lindesay 	} else {
165795c7b018SAndrew Lindesay 		_NotifyWorkStatusClear();
1658fa5c8097SAndrew Lindesay 		HDINFO("! unknown process coordinator changed");
165910cd325cSAndrew Lindesay 	}
166095c7b018SAndrew Lindesay }
1661ccf707d0SAndrew Lindesay 
1662ccf707d0SAndrew Lindesay 
1663ccf707d0SAndrew Lindesay static package_list_view_mode
main_window_tab_to_package_list_view_mode(int32 tab)1664ccf707d0SAndrew Lindesay main_window_tab_to_package_list_view_mode(int32 tab)
1665ccf707d0SAndrew Lindesay {
1666ccf707d0SAndrew Lindesay 	if (tab == TAB_PROMINENT_PACKAGES)
1667ccf707d0SAndrew Lindesay 		return PROMINENT;
1668ccf707d0SAndrew Lindesay 	return ALL;
1669ccf707d0SAndrew Lindesay }
1670ccf707d0SAndrew Lindesay 
1671ccf707d0SAndrew Lindesay 
1672ccf707d0SAndrew Lindesay void
_HandleChangePackageListViewMode()1673ccf707d0SAndrew Lindesay MainWindow::_HandleChangePackageListViewMode()
1674ccf707d0SAndrew Lindesay {
1675ccf707d0SAndrew Lindesay 	package_list_view_mode tabMode = main_window_tab_to_package_list_view_mode(
1676ccf707d0SAndrew Lindesay 		fListTabs->Selection());
1677ccf707d0SAndrew Lindesay 	package_list_view_mode modelMode = fModel.PackageListViewMode();
1678ccf707d0SAndrew Lindesay 
1679ccf707d0SAndrew Lindesay 	if (tabMode != modelMode) {
1680ccf707d0SAndrew Lindesay 		BAutolock locker(fModel.Lock());
1681ccf707d0SAndrew Lindesay 		fModel.SetPackageListViewMode(tabMode);
1682ccf707d0SAndrew Lindesay 	}
1683ccf707d0SAndrew Lindesay }
168405880d13SAndrew Lindesay 
168505880d13SAndrew Lindesay 
168605880d13SAndrew Lindesay std::vector<DepotInfoRef>
_CreateSnapshotOfDepots()168705880d13SAndrew Lindesay MainWindow::_CreateSnapshotOfDepots()
168805880d13SAndrew Lindesay {
168905880d13SAndrew Lindesay 	std::vector<DepotInfoRef> result;
169005880d13SAndrew Lindesay 	BAutolock locker(fModel.Lock());
169105880d13SAndrew Lindesay 	int32 countDepots = fModel.CountDepots();
169205880d13SAndrew Lindesay 	for(int32 i = 0; i < countDepots; i++)
169305880d13SAndrew Lindesay 		result.push_back(fModel.DepotAtIndex(i));
169405880d13SAndrew Lindesay 	return result;
169505880d13SAndrew Lindesay }
169688af15cfSAndrew Lindesay 
169788af15cfSAndrew Lindesay 
169888af15cfSAndrew Lindesay /*! This will get invoked in the case that a screenshot has been cached
169988af15cfSAndrew Lindesay     and so could now be loaded by some UI element. This method will then
170088af15cfSAndrew Lindesay     signal to other UI elements that they could load a screenshot should
170188af15cfSAndrew Lindesay     they have been waiting for it.
170288af15cfSAndrew Lindesay */
170388af15cfSAndrew Lindesay 
170488af15cfSAndrew Lindesay void
_HandleScreenshotCached(const BMessage * message)170588af15cfSAndrew Lindesay MainWindow::_HandleScreenshotCached(const BMessage* message)
170688af15cfSAndrew Lindesay {
170788af15cfSAndrew Lindesay 	ScreenshotCoordinate coordinate(message);
170888af15cfSAndrew Lindesay 	fPackageInfoView->HandleScreenshotCached(coordinate);
170988af15cfSAndrew Lindesay }
1710