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" 40d13c3d89SAndrew Lindesay #include "Logger.h" 4104c9d578SStephan Aßmus #include "PackageInfoView.h" 4204c9d578SStephan Aßmus #include "PackageListView.h" 4304c9d578SStephan Aßmus #include "PackageManager.h" 443369e03dSAndrew Lindesay #include "ProcessCoordinator.h" 453369e03dSAndrew Lindesay #include "ProcessCoordinatorFactory.h" 4604c9d578SStephan Aßmus #include "RatePackageWindow.h" 47e0a26dceSStephan Aßmus #include "support.h" 48d5ef985eSStephan Aßmus #include "ScreenshotWindow.h" 49133ebab6SAndrew Lindesay #include "SettingsWindow.h" 5095c7b018SAndrew Lindesay #include "ShuttingDownWindow.h" 5110cd325cSAndrew Lindesay #include "ToLatestUserUsageConditionsWindow.h" 5204c9d578SStephan Aßmus #include "UserLoginWindow.h" 5301339a54SAndrew Lindesay #include "UserUsageConditionsWindow.h" 54125d42d9SJulian Harnath #include "WorkStatusView.h" 5504c9d578SStephan Aßmus 5604c9d578SStephan Aßmus 5704c9d578SStephan Aßmus #undef B_TRANSLATION_CONTEXT 5804c9d578SStephan Aßmus #define B_TRANSLATION_CONTEXT "MainWindow" 5904c9d578SStephan Aßmus 6004c9d578SStephan Aßmus 6104c9d578SStephan Aßmus enum { 625bf2b6ebSBrian Hill MSG_REFRESH_REPOS = 'mrrp', 635bf2b6ebSBrian Hill MSG_MANAGE_REPOS = 'mmrp', 64d144f952SAugustin Cavalier MSG_SOFTWARE_UPDATER = 'mswu', 65133ebab6SAndrew Lindesay MSG_SETTINGS = 'stgs', 6604c9d578SStephan Aßmus MSG_LOG_IN = 'lgin', 678f03a0f9SStephan Aßmus MSG_AUTHORIZATION_CHANGED = 'athc', 6889b16bb4SAndrew Lindesay MSG_CATEGORIES_LIST_CHANGED = 'clic', 69da651104SStephan Aßmus MSG_PACKAGE_CHANGED = 'pchd', 70409af934SAndrew Lindesay MSG_PROCESS_COORDINATOR_CHANGED = 'pccd', 713369e03dSAndrew Lindesay MSG_WORK_STATUS_CHANGE = 'wsch', 723369e03dSAndrew Lindesay MSG_WORK_STATUS_CLEAR = 'wscl', 7384674570SAndrew Lindesay MSG_INCREMENT_VIEW_COUNTER = 'icrv', 7488af15cfSAndrew Lindesay MSG_SCREENSHOT_CACHED = 'ssca', 75fdec4227SStephan Aßmus 76ccf707d0SAndrew Lindesay MSG_CHANGE_PACKAGE_LIST_VIEW_MODE = 'cplm', 77fdec4227SStephan Aßmus MSG_SHOW_AVAILABLE_PACKAGES = 'savl', 78fdec4227SStephan Aßmus MSG_SHOW_INSTALLED_PACKAGES = 'sins', 7904c9d578SStephan Aßmus MSG_SHOW_SOURCE_PACKAGES = 'ssrc', 8004c9d578SStephan Aßmus MSG_SHOW_DEVELOP_PACKAGES = 'sdvl' 8104c9d578SStephan Aßmus }; 8204c9d578SStephan Aßmus 8310cd325cSAndrew Lindesay #define KEY_ERROR_STATUS "errorStatus" 84ccf707d0SAndrew Lindesay 8584674570SAndrew Lindesay const bigtime_t kIncrementViewCounterDelayMicros = 3 * 1000 * 1000; 8684674570SAndrew Lindesay 87ccf707d0SAndrew Lindesay #define TAB_PROMINENT_PACKAGES 0 88ccf707d0SAndrew Lindesay #define TAB_ALL_PACKAGES 1 8904c9d578SStephan Aßmus 9004c9d578SStephan Aßmus using namespace BPackageKit; 9104c9d578SStephan Aßmus using namespace BPackageKit::BManager::BPrivate; 9204c9d578SStephan Aßmus 9304c9d578SStephan Aßmus 9404c9d578SStephan Aßmus typedef std::map<BString, PackageInfoRef> PackageInfoMap; 9504c9d578SStephan Aßmus 9604c9d578SStephan Aßmus 9704c9d578SStephan Aßmus struct RefreshWorkerParameters { 9804c9d578SStephan Aßmus MainWindow* window; 9904c9d578SStephan Aßmus bool forceRefresh; 10004c9d578SStephan Aßmus 10104c9d578SStephan Aßmus RefreshWorkerParameters(MainWindow* window, bool forceRefresh) 10204c9d578SStephan Aßmus : 10304c9d578SStephan Aßmus window(window), 10404c9d578SStephan Aßmus forceRefresh(forceRefresh) 10504c9d578SStephan Aßmus { 10604c9d578SStephan Aßmus } 10704c9d578SStephan Aßmus }; 10804c9d578SStephan Aßmus 10904c9d578SStephan Aßmus 11089b16bb4SAndrew Lindesay class MainWindowModelListener : public ModelListener { 1118f03a0f9SStephan Aßmus public: 11289b16bb4SAndrew Lindesay MainWindowModelListener(const BMessenger& messenger) 1138f03a0f9SStephan Aßmus : 1148f03a0f9SStephan Aßmus fMessenger(messenger) 1158f03a0f9SStephan Aßmus { 1168f03a0f9SStephan Aßmus } 1178f03a0f9SStephan Aßmus 1188f03a0f9SStephan Aßmus virtual void AuthorizationChanged() 1198f03a0f9SStephan Aßmus { 1208f03a0f9SStephan Aßmus if (fMessenger.IsValid()) 1218f03a0f9SStephan Aßmus fMessenger.SendMessage(MSG_AUTHORIZATION_CHANGED); 1228f03a0f9SStephan Aßmus } 1238f03a0f9SStephan Aßmus 12489b16bb4SAndrew Lindesay virtual void CategoryListChanged() 12589b16bb4SAndrew Lindesay { 12689b16bb4SAndrew Lindesay if (fMessenger.IsValid()) 12789b16bb4SAndrew Lindesay fMessenger.SendMessage(MSG_CATEGORIES_LIST_CHANGED); 12889b16bb4SAndrew Lindesay } 12989b16bb4SAndrew Lindesay 13088af15cfSAndrew Lindesay virtual void ScreenshotCached(const ScreenshotCoordinate& coordinate) 13188af15cfSAndrew Lindesay { 13288af15cfSAndrew Lindesay if (fMessenger.IsValid()) { 13388af15cfSAndrew Lindesay BMessage message(MSG_SCREENSHOT_CACHED); 13488af15cfSAndrew Lindesay if (coordinate.Archive(&message) != B_OK) 13588af15cfSAndrew Lindesay debugger("unable to serialize a screenshot coordinate"); 13688af15cfSAndrew Lindesay fMessenger.SendMessage(&message); 13788af15cfSAndrew Lindesay } 13888af15cfSAndrew Lindesay } 13988af15cfSAndrew Lindesay 1408f03a0f9SStephan Aßmus private: 1418f03a0f9SStephan Aßmus BMessenger fMessenger; 1428f03a0f9SStephan Aßmus }; 1438f03a0f9SStephan Aßmus 1448f03a0f9SStephan Aßmus 145409af934SAndrew Lindesay class MainWindowPackageInfoListener : public PackageInfoListener { 146409af934SAndrew Lindesay public: 147409af934SAndrew Lindesay MainWindowPackageInfoListener(MainWindow* mainWindow) 148409af934SAndrew Lindesay : 149409af934SAndrew Lindesay fMainWindow(mainWindow) 150409af934SAndrew Lindesay { 151409af934SAndrew Lindesay } 152409af934SAndrew Lindesay 153409af934SAndrew Lindesay ~MainWindowPackageInfoListener() 154409af934SAndrew Lindesay { 155409af934SAndrew Lindesay } 156409af934SAndrew Lindesay 157409af934SAndrew Lindesay private: 158409af934SAndrew Lindesay // PackageInfoListener 159409af934SAndrew Lindesay virtual void PackageChanged(const PackageInfoEvent& event) 160409af934SAndrew Lindesay { 161409af934SAndrew Lindesay fMainWindow->PackageChanged(event); 162409af934SAndrew Lindesay } 163409af934SAndrew Lindesay 164409af934SAndrew Lindesay private: 165409af934SAndrew Lindesay MainWindow* fMainWindow; 166409af934SAndrew Lindesay }; 167409af934SAndrew Lindesay 168409af934SAndrew Lindesay 169f7c2983eSAxel Dörfler MainWindow::MainWindow(const BMessage& settings) 17004c9d578SStephan Aßmus : 171f7c2983eSAxel Dörfler BWindow(BRect(50, 50, 650, 550), B_TRANSLATE_SYSTEM_NAME("HaikuDepot"), 17204c9d578SStephan Aßmus B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, 17304c9d578SStephan Aßmus B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS), 174d5ef985eSStephan Aßmus fScreenshotWindow(NULL), 17595c7b018SAndrew Lindesay fShuttingDownWindow(NULL), 176e0a26dceSStephan Aßmus fUserMenu(NULL), 177e0a26dceSStephan Aßmus fLogInItem(NULL), 178e0a26dceSStephan Aßmus fLogOutItem(NULL), 179976cadf1SAndrew Lindesay fUsersUserUsageConditionsMenuItem(NULL), 18089b16bb4SAndrew Lindesay fModelListener(new MainWindowModelListener(BMessenger(this)), true), 18110cd325cSAndrew Lindesay fCoordinator(NULL), 18295c7b018SAndrew Lindesay fShouldCloseWhenNoProcessesToCoordinate(false), 18384674570SAndrew Lindesay fSinglePackageMode(false), 18484674570SAndrew Lindesay fIncrementViewCounterDelayedRunner(NULL) 18504c9d578SStephan Aßmus { 18610cd325cSAndrew Lindesay if ((fCoordinatorRunningSem = create_sem(1, "ProcessCoordinatorSem")) < B_OK) 18710cd325cSAndrew Lindesay debugger("unable to create the process coordinator semaphore"); 18810cd325cSAndrew Lindesay 189409af934SAndrew Lindesay fPackageInfoListener = PackageInfoListenerRef( 190409af934SAndrew Lindesay new MainWindowPackageInfoListener(this), true); 191409af934SAndrew Lindesay 192cbadcae1SHumdinger BMenuBar* menuBar = new BMenuBar("Main Menu"); 19304c9d578SStephan Aßmus _BuildMenu(menuBar); 19404c9d578SStephan Aßmus 195cbadcae1SHumdinger BMenuBar* userMenuBar = new BMenuBar("User Menu"); 196e0a26dceSStephan Aßmus _BuildUserMenu(userMenuBar); 197e0a26dceSStephan Aßmus set_small_font(userMenuBar); 198e0a26dceSStephan Aßmus userMenuBar->SetExplicitMaxSize(BSize(B_SIZE_UNSET, 199e0a26dceSStephan Aßmus menuBar->MaxSize().height)); 200e0a26dceSStephan Aßmus 20104c9d578SStephan Aßmus fFilterView = new FilterView(); 202f0e491d3SAndrew Lindesay fFeaturedPackagesView = new FeaturedPackagesView(fModel); 203f0e491d3SAndrew Lindesay fPackageListView = new PackageListView(&fModel); 204f0e491d3SAndrew Lindesay fPackageInfoView = new PackageInfoView(&fModel, this); 20504c9d578SStephan Aßmus 20604c9d578SStephan Aßmus fSplitView = new BSplitView(B_VERTICAL, 5.0f); 20704c9d578SStephan Aßmus 208125d42d9SJulian Harnath fWorkStatusView = new WorkStatusView("work status"); 209125d42d9SJulian Harnath fPackageListView->AttachWorkStatusView(fWorkStatusView); 210125d42d9SJulian Harnath 211e00a489bSAugustin Cavalier fListTabs = new TabView(BMessenger(this), 212ccf707d0SAndrew Lindesay BMessage(MSG_CHANGE_PACKAGE_LIST_VIEW_MODE), "list tabs"); 213e00a489bSAugustin Cavalier fListTabs->AddTab(fFeaturedPackagesView); 214e00a489bSAugustin Cavalier fListTabs->AddTab(fPackageListView); 2154b930ccaSStephan Aßmus 21604c9d578SStephan Aßmus BLayoutBuilder::Group<>(this, B_VERTICAL, 0.0f) 217e0a26dceSStephan Aßmus .AddGroup(B_HORIZONTAL, 0.0f) 218e0a26dceSStephan Aßmus .Add(menuBar, 1.0f) 219e0a26dceSStephan Aßmus .Add(userMenuBar, 0.0f) 220e0a26dceSStephan Aßmus .End() 22104c9d578SStephan Aßmus .Add(fFilterView) 22204c9d578SStephan Aßmus .AddSplit(fSplitView) 22304c9d578SStephan Aßmus .AddGroup(B_VERTICAL) 224e00a489bSAugustin Cavalier .Add(fListTabs) 22504c9d578SStephan Aßmus .SetInsets( 22604c9d578SStephan Aßmus B_USE_DEFAULT_SPACING, 0.0f, 22704c9d578SStephan Aßmus B_USE_DEFAULT_SPACING, 0.0f) 22804c9d578SStephan Aßmus .End() 22904c9d578SStephan Aßmus .Add(fPackageInfoView) 23004c9d578SStephan Aßmus .End() 231125d42d9SJulian Harnath .Add(fWorkStatusView) 23204c9d578SStephan Aßmus ; 23304c9d578SStephan Aßmus 23404c9d578SStephan Aßmus fSplitView->SetCollapsible(0, false); 23504c9d578SStephan Aßmus fSplitView->SetCollapsible(1, false); 23604c9d578SStephan Aßmus 2378f03a0f9SStephan Aßmus fModel.AddListener(fModelListener); 2388f03a0f9SStephan Aßmus 23904c9d578SStephan Aßmus BMessage columnSettings; 24004c9d578SStephan Aßmus if (settings.FindMessage("column settings", &columnSettings) == B_OK) 24104c9d578SStephan Aßmus fPackageListView->LoadState(&columnSettings); 24204c9d578SStephan Aßmus 243ccf707d0SAndrew Lindesay _RestoreModelSettings(settings); 244133ebab6SAndrew Lindesay _MaybePromptCanShareAnonymousUserData(settings); 24504c9d578SStephan Aßmus 246ccf707d0SAndrew Lindesay if (fModel.PackageListViewMode() == PROMINENT) 247ccf707d0SAndrew Lindesay fListTabs->Select(TAB_PROMINENT_PACKAGES); 2482997e05bSStephan Aßmus else 249ccf707d0SAndrew Lindesay fListTabs->Select(TAB_ALL_PACKAGES); 2502997e05bSStephan Aßmus 251d2d4866dSAndrew Lindesay _RestoreNickname(settings); 25210cd325cSAndrew Lindesay _UpdateAuthorization(); 253f7c2983eSAxel Dörfler _RestoreWindowFrame(settings); 254f7c2983eSAxel Dörfler 2558f03a0f9SStephan Aßmus // start worker threads 25604c9d578SStephan Aßmus BPackageRoster().StartWatching(this, 25704c9d578SStephan Aßmus B_WATCH_PACKAGE_INSTALLATION_LOCATIONS); 25804c9d578SStephan Aßmus 25963975654SStephan Aßmus _InitWorkerThreads(); 2609883929bSAndrew Lindesay _AdoptModel(); 2619883929bSAndrew Lindesay _StartBulkLoad(); 26204c9d578SStephan Aßmus } 26304c9d578SStephan Aßmus 26404c9d578SStephan Aßmus 26575a70554SAndrew Lindesay /*! This constructor is used when the application is loaded for the purpose of 26675a70554SAndrew Lindesay viewing an HPKG file. 26775a70554SAndrew Lindesay */ 26875a70554SAndrew Lindesay 269afe7affbSAndrew Lindesay MainWindow::MainWindow(const BMessage& settings, PackageInfoRef& package) 2706d519fd1SStephan Aßmus : 271f7c2983eSAxel Dörfler BWindow(BRect(50, 50, 650, 350), B_TRANSLATE_SYSTEM_NAME("HaikuDepot"), 2726d519fd1SStephan Aßmus B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, 2736d519fd1SStephan Aßmus B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS), 2749883929bSAndrew Lindesay fFeaturedPackagesView(NULL), 2759883929bSAndrew Lindesay fPackageListView(NULL), 276d78bfd8dSJulian Harnath fWorkStatusView(NULL), 277d5ef985eSStephan Aßmus fScreenshotWindow(NULL), 27895c7b018SAndrew Lindesay fShuttingDownWindow(NULL), 279e0a26dceSStephan Aßmus fUserMenu(NULL), 280e0a26dceSStephan Aßmus fLogInItem(NULL), 2816d519fd1SStephan Aßmus fLogOutItem(NULL), 282976cadf1SAndrew Lindesay fUsersUserUsageConditionsMenuItem(NULL), 28389b16bb4SAndrew Lindesay fModelListener(new MainWindowModelListener(BMessenger(this)), true), 28410cd325cSAndrew Lindesay fCoordinator(NULL), 28595c7b018SAndrew Lindesay fShouldCloseWhenNoProcessesToCoordinate(false), 28684674570SAndrew Lindesay fSinglePackageMode(true), 28784674570SAndrew Lindesay fIncrementViewCounterDelayedRunner(NULL) 2886d519fd1SStephan Aßmus { 28975a70554SAndrew Lindesay BString title = B_TRANSLATE("HaikuDepot - %PackageName% %PackageVersion%"); 29075a70554SAndrew Lindesay title.ReplaceAll("%PackageName%", package->Name()); 29175a70554SAndrew Lindesay title.ReplaceAll("%PackageVersion%", package->Version().ToString()); 29275a70554SAndrew Lindesay SetTitle(title); 29375a70554SAndrew Lindesay 29410cd325cSAndrew Lindesay if ((fCoordinatorRunningSem = create_sem(1, "ProcessCoordinatorSem")) < B_OK) 29510cd325cSAndrew Lindesay debugger("unable to create the process coordinator semaphore"); 29610cd325cSAndrew Lindesay 297409af934SAndrew Lindesay fPackageInfoListener = PackageInfoListenerRef( 298409af934SAndrew Lindesay new MainWindowPackageInfoListener(this), true); 299409af934SAndrew Lindesay 3006d519fd1SStephan Aßmus fFilterView = new FilterView(); 301f0e491d3SAndrew Lindesay fPackageInfoView = new PackageInfoView(&fModel, this); 30287016f8fSAndrew Lindesay fWorkStatusView = new WorkStatusView("work status"); 3036d519fd1SStephan Aßmus 3046d519fd1SStephan Aßmus BLayoutBuilder::Group<>(this, B_VERTICAL) 3056d519fd1SStephan Aßmus .Add(fPackageInfoView) 30687016f8fSAndrew Lindesay .Add(fWorkStatusView) 3076d519fd1SStephan Aßmus .SetInsets(0, B_USE_WINDOW_INSETS, 0, 0) 3086d519fd1SStephan Aßmus ; 3096d519fd1SStephan Aßmus 3106d519fd1SStephan Aßmus fModel.AddListener(fModelListener); 3116d519fd1SStephan Aßmus 312afe7affbSAndrew Lindesay // add the single package into the model so that any internal 313afe7affbSAndrew Lindesay // business logic is able to find the package. 314afe7affbSAndrew Lindesay DepotInfoRef depot(new DepotInfo("single-pkg-depot"), true); 315afe7affbSAndrew Lindesay depot->AddPackage(package); 316afe7affbSAndrew Lindesay fModel.MergeOrAddDepot(depot); 317afe7affbSAndrew Lindesay 3186d519fd1SStephan Aßmus // Restore settings 319d2d4866dSAndrew Lindesay _RestoreNickname(settings); 320ccf707d0SAndrew Lindesay _UpdateAuthorization(); 321f7c2983eSAxel Dörfler _RestoreWindowFrame(settings); 3226d519fd1SStephan Aßmus 3236d519fd1SStephan Aßmus fPackageInfoView->SetPackage(package); 32463975654SStephan Aßmus 325afe7affbSAndrew Lindesay // start worker threads 326afe7affbSAndrew Lindesay BPackageRoster().StartWatching(this, 327afe7affbSAndrew Lindesay B_WATCH_PACKAGE_INSTALLATION_LOCATIONS); 328afe7affbSAndrew Lindesay 32963975654SStephan Aßmus _InitWorkerThreads(); 3306d519fd1SStephan Aßmus } 3316d519fd1SStephan Aßmus 3326d519fd1SStephan Aßmus 33304c9d578SStephan Aßmus MainWindow::~MainWindow() 33404c9d578SStephan Aßmus { 33510cd325cSAndrew Lindesay _SpinUntilProcessCoordinatorComplete(); 33610cd325cSAndrew Lindesay delete_sem(fCoordinatorRunningSem); 33710cd325cSAndrew Lindesay fCoordinatorRunningSem = 0; 33810cd325cSAndrew Lindesay 33904c9d578SStephan Aßmus BPackageRoster().StopWatching(this); 34004c9d578SStephan Aßmus 34195c7b018SAndrew Lindesay if (fScreenshotWindow != NULL) { 34295c7b018SAndrew Lindesay if (fScreenshotWindow->Lock()) 343d5ef985eSStephan Aßmus fScreenshotWindow->Quit(); 34404c9d578SStephan Aßmus } 34504c9d578SStephan Aßmus 34695c7b018SAndrew Lindesay if (fShuttingDownWindow != NULL) { 34795c7b018SAndrew Lindesay if (fShuttingDownWindow->Lock()) 34895c7b018SAndrew Lindesay fShuttingDownWindow->Quit(); 34995c7b018SAndrew Lindesay } 350d5562247SAugustin Cavalier 351a3866854SAugustin Cavalier delete_sem(fPackageToPopulateSem); 352a3866854SAugustin Cavalier wait_for_thread(fPopulatePackageWorker, NULL); 353a3866854SAugustin Cavalier 3544329a83fSAugustin Cavalier // We must clear the model early to release references. 355d5562247SAugustin Cavalier fModel.Clear(); 35695c7b018SAndrew Lindesay } 35795c7b018SAndrew Lindesay 35804c9d578SStephan Aßmus 35904c9d578SStephan Aßmus bool 36004c9d578SStephan Aßmus MainWindow::QuitRequested() 36104c9d578SStephan Aßmus { 36204c9d578SStephan Aßmus 36310cd325cSAndrew Lindesay _StopProcessCoordinators(); 3643369e03dSAndrew Lindesay 36595c7b018SAndrew Lindesay // If there are any processes in flight we need to be careful to make 36695c7b018SAndrew Lindesay // sure that they are cleanly completed before actually quitting. By 36795c7b018SAndrew Lindesay // turning on the `fShouldCloseWhenNoProcessesToCoordinate` flag, when 36895c7b018SAndrew Lindesay // the process coordination has completed then it will detect this and 36995c7b018SAndrew Lindesay // quit again. 37095c7b018SAndrew Lindesay 37195c7b018SAndrew Lindesay { 37295c7b018SAndrew Lindesay AutoLocker<BLocker> lock(&fCoordinatorLock); 37395c7b018SAndrew Lindesay fShouldCloseWhenNoProcessesToCoordinate = true; 37495c7b018SAndrew Lindesay 375409af934SAndrew Lindesay if (fCoordinator != NULL) { 37695c7b018SAndrew Lindesay HDINFO("a coordinator is running --> will wait before quitting..."); 37795c7b018SAndrew Lindesay 37895c7b018SAndrew Lindesay if (fShuttingDownWindow == NULL) 37995c7b018SAndrew Lindesay fShuttingDownWindow = new ShuttingDownWindow(this); 38095c7b018SAndrew Lindesay fShuttingDownWindow->Show(); 38195c7b018SAndrew Lindesay 38295c7b018SAndrew Lindesay return false; 38395c7b018SAndrew Lindesay } 38495c7b018SAndrew Lindesay } 38595c7b018SAndrew Lindesay 38695c7b018SAndrew Lindesay BMessage settings; 38795c7b018SAndrew Lindesay StoreSettings(settings); 38895c7b018SAndrew Lindesay BMessage message(MSG_MAIN_WINDOW_CLOSED); 38995c7b018SAndrew Lindesay message.AddMessage(KEY_WINDOW_SETTINGS, &settings); 39095c7b018SAndrew Lindesay be_app->PostMessage(&message); 39195c7b018SAndrew Lindesay 39295c7b018SAndrew Lindesay if (fShuttingDownWindow != NULL) { 39395c7b018SAndrew Lindesay if (fShuttingDownWindow->Lock()) 39495c7b018SAndrew Lindesay fShuttingDownWindow->Quit(); 39595c7b018SAndrew Lindesay fShuttingDownWindow = NULL; 39695c7b018SAndrew Lindesay } 39795c7b018SAndrew Lindesay 39804c9d578SStephan Aßmus return true; 39904c9d578SStephan Aßmus } 40004c9d578SStephan Aßmus 40104c9d578SStephan Aßmus 40204c9d578SStephan Aßmus void 40304c9d578SStephan Aßmus MainWindow::MessageReceived(BMessage* message) 40404c9d578SStephan Aßmus { 40504c9d578SStephan Aßmus switch (message->what) { 4063369e03dSAndrew Lindesay case MSG_BULK_LOAD_DONE: 40710cd325cSAndrew Lindesay { 40810cd325cSAndrew Lindesay int64 errorStatus64; 40910cd325cSAndrew Lindesay if (message->FindInt64(KEY_ERROR_STATUS, &errorStatus64) == B_OK) 41010cd325cSAndrew Lindesay _BulkLoadCompleteReceived((status_t) errorStatus64); 41110cd325cSAndrew Lindesay else 412fa5c8097SAndrew Lindesay HDERROR("expected [%s] value in message", KEY_ERROR_STATUS); 41304c9d578SStephan Aßmus break; 41410cd325cSAndrew Lindesay } 41504c9d578SStephan Aßmus case B_SIMPLE_DATA: 41604c9d578SStephan Aßmus case B_REFS_RECEIVED: 41704c9d578SStephan Aßmus // TODO: ? 41804c9d578SStephan Aßmus break; 41904c9d578SStephan Aßmus 42004c9d578SStephan Aßmus case B_PACKAGE_UPDATE: 421f32d5c5cSAndrew Lindesay _HandleExternalPackageUpdateMessageReceived(message); 42204c9d578SStephan Aßmus break; 42304c9d578SStephan Aßmus 4245bf2b6ebSBrian Hill case MSG_REFRESH_REPOS: 4253369e03dSAndrew Lindesay _StartBulkLoad(true); 4263369e03dSAndrew Lindesay break; 4273369e03dSAndrew Lindesay 42810cd325cSAndrew Lindesay case MSG_WORK_STATUS_CLEAR: 42910cd325cSAndrew Lindesay _HandleWorkStatusClear(); 43010cd325cSAndrew Lindesay break; 43110cd325cSAndrew Lindesay 4323369e03dSAndrew Lindesay case MSG_WORK_STATUS_CHANGE: 4333369e03dSAndrew Lindesay _HandleWorkStatusChangeMessageReceived(message); 43404c9d578SStephan Aßmus break; 43504c9d578SStephan Aßmus 4365bf2b6ebSBrian Hill case MSG_MANAGE_REPOS: 4375bf2b6ebSBrian Hill be_roster->Launch("application/x-vnd.Haiku-Repositories"); 4385bf2b6ebSBrian Hill break; 4395bf2b6ebSBrian Hill 440d144f952SAugustin Cavalier case MSG_SOFTWARE_UPDATER: 441d144f952SAugustin Cavalier be_roster->Launch("application/x-vnd.haiku-softwareupdater"); 442d144f952SAugustin Cavalier break; 443d144f952SAugustin Cavalier 44404c9d578SStephan Aßmus case MSG_LOG_IN: 4451bbda92dSStephan Aßmus _OpenLoginWindow(BMessage()); 44604c9d578SStephan Aßmus break; 44704c9d578SStephan Aßmus 448133ebab6SAndrew Lindesay case MSG_SETTINGS: 449133ebab6SAndrew Lindesay _OpenSettingsWindow(); 450133ebab6SAndrew Lindesay break; 451133ebab6SAndrew Lindesay 4528f03a0f9SStephan Aßmus case MSG_LOG_OUT: 453d2d4866dSAndrew Lindesay fModel.SetNickname(""); 4548f03a0f9SStephan Aßmus break; 4558f03a0f9SStephan Aßmus 45601339a54SAndrew Lindesay case MSG_VIEW_LATEST_USER_USAGE_CONDITIONS: 457d2d4866dSAndrew Lindesay _ViewUserUsageConditions(LATEST); 458d2d4866dSAndrew Lindesay break; 459d2d4866dSAndrew Lindesay 460d2d4866dSAndrew Lindesay case MSG_VIEW_USERS_USER_USAGE_CONDITIONS: 461d2d4866dSAndrew Lindesay _ViewUserUsageConditions(USER); 46201339a54SAndrew Lindesay break; 46301339a54SAndrew Lindesay 4648f03a0f9SStephan Aßmus case MSG_AUTHORIZATION_CHANGED: 46510cd325cSAndrew Lindesay _StartUserVerify(); 4668f03a0f9SStephan Aßmus _UpdateAuthorization(); 4678f03a0f9SStephan Aßmus break; 4688f03a0f9SStephan Aßmus 46988af15cfSAndrew Lindesay case MSG_SCREENSHOT_CACHED: 47088af15cfSAndrew Lindesay _HandleScreenshotCached(message); 47188af15cfSAndrew Lindesay break; 47288af15cfSAndrew Lindesay 47389b16bb4SAndrew Lindesay case MSG_CATEGORIES_LIST_CHANGED: 47489b16bb4SAndrew Lindesay fFilterView->AdoptModel(fModel); 47589b16bb4SAndrew Lindesay break; 47689b16bb4SAndrew Lindesay 477ccf707d0SAndrew Lindesay case MSG_CHANGE_PACKAGE_LIST_VIEW_MODE: 478ccf707d0SAndrew Lindesay _HandleChangePackageListViewMode(); 4794fade61fSStephan Aßmus break; 4804fade61fSStephan Aßmus 481fdec4227SStephan Aßmus case MSG_SHOW_AVAILABLE_PACKAGES: 482fdec4227SStephan Aßmus { 483fdec4227SStephan Aßmus BAutolock locker(fModel.Lock()); 484*363fc60bSAndrew Lindesay PackageFilterModel* filterModel = fModel.PackageFilter(); 485*363fc60bSAndrew Lindesay filterModel->SetShowAvailablePackages(!filterModel->ShowAvailablePackages()); 486fdec4227SStephan Aßmus } 487fdec4227SStephan Aßmus _AdoptModel(); 488fdec4227SStephan Aßmus break; 489fdec4227SStephan Aßmus 490fdec4227SStephan Aßmus case MSG_SHOW_INSTALLED_PACKAGES: 491fdec4227SStephan Aßmus { 492fdec4227SStephan Aßmus BAutolock locker(fModel.Lock()); 493*363fc60bSAndrew Lindesay PackageFilterModel* filterModel = fModel.PackageFilter(); 494*363fc60bSAndrew Lindesay filterModel->SetShowInstalledPackages(!filterModel->ShowInstalledPackages()); 495fdec4227SStephan Aßmus } 496fdec4227SStephan Aßmus _AdoptModel(); 497fdec4227SStephan Aßmus break; 498fdec4227SStephan Aßmus 49904c9d578SStephan Aßmus case MSG_SHOW_SOURCE_PACKAGES: 50004c9d578SStephan Aßmus { 50104c9d578SStephan Aßmus BAutolock locker(fModel.Lock()); 502*363fc60bSAndrew Lindesay PackageFilterModel* filterModel = fModel.PackageFilter(); 503*363fc60bSAndrew Lindesay filterModel->SetShowSourcePackages(!filterModel->ShowSourcePackages()); 50404c9d578SStephan Aßmus } 50504c9d578SStephan Aßmus _AdoptModel(); 50604c9d578SStephan Aßmus break; 50704c9d578SStephan Aßmus 50804c9d578SStephan Aßmus case MSG_SHOW_DEVELOP_PACKAGES: 50904c9d578SStephan Aßmus { 51004c9d578SStephan Aßmus BAutolock locker(fModel.Lock()); 511*363fc60bSAndrew Lindesay PackageFilterModel* filterModel = fModel.PackageFilter(); 512*363fc60bSAndrew Lindesay filterModel->SetShowDevelopPackages(!filterModel->ShowDevelopPackages()); 51304c9d578SStephan Aßmus } 51404c9d578SStephan Aßmus _AdoptModel(); 51504c9d578SStephan Aßmus break; 51604c9d578SStephan Aßmus 517a9edb9bfSAndrew Lindesay // this may be triggered by, for example, a user rating being added 518a9edb9bfSAndrew Lindesay // or having been altered. 519a9edb9bfSAndrew Lindesay case MSG_SERVER_DATA_CHANGED: 520a9edb9bfSAndrew Lindesay { 521a9edb9bfSAndrew Lindesay BString name; 522a9edb9bfSAndrew Lindesay if (message->FindString("name", &name) == B_OK) { 523a9edb9bfSAndrew Lindesay BAutolock locker(fModel.Lock()); 524a9edb9bfSAndrew Lindesay if (fPackageInfoView->Package()->Name() == name) { 525a9edb9bfSAndrew Lindesay _PopulatePackageAsync(true); 526a9edb9bfSAndrew Lindesay } else { 527f96d1f4dSAndrew Lindesay HDDEBUG("pkg [%s] is updated on the server, but is " 528f96d1f4dSAndrew Lindesay "not selected so will not be updated.", 529fa5c8097SAndrew Lindesay name.String()); 530a9edb9bfSAndrew Lindesay } 531a9edb9bfSAndrew Lindesay } 532a9edb9bfSAndrew Lindesay break; 533a9edb9bfSAndrew Lindesay } 534a9edb9bfSAndrew Lindesay 53584674570SAndrew Lindesay case MSG_INCREMENT_VIEW_COUNTER: 53684674570SAndrew Lindesay _HandleIncrementViewCounter(message); 53784674570SAndrew Lindesay break; 53884674570SAndrew Lindesay 53904c9d578SStephan Aßmus case MSG_PACKAGE_SELECTED: 54004c9d578SStephan Aßmus { 54172992391SStephan Aßmus BString name; 54272992391SStephan Aßmus if (message->FindString("name", &name) == B_OK) { 543c4199192SAndrew Lindesay PackageInfoRef package; 544c4199192SAndrew Lindesay { 54575ba9dbfSStephan Aßmus BAutolock locker(fModel.Lock()); 546c4199192SAndrew Lindesay package = fModel.PackageForName(name); 547c4199192SAndrew Lindesay } 5486f07feadSAndrew Lindesay if (!package.IsSet() || name != package->Name()) 549c4199192SAndrew Lindesay debugger("unable to find the named package"); 550133ebab6SAndrew Lindesay else { 55104c9d578SStephan Aßmus _AdoptPackage(package); 55284674570SAndrew Lindesay _SetupDelayedIncrementViewCounter(package); 553133ebab6SAndrew Lindesay } 55404c9d578SStephan Aßmus } else { 55504c9d578SStephan Aßmus _ClearPackage(); 55604c9d578SStephan Aßmus } 55704c9d578SStephan Aßmus break; 55804c9d578SStephan Aßmus } 55904c9d578SStephan Aßmus 56004c9d578SStephan Aßmus case MSG_CATEGORY_SELECTED: 56104c9d578SStephan Aßmus { 56289b16bb4SAndrew Lindesay BString code; 56389b16bb4SAndrew Lindesay if (message->FindString("code", &code) != B_OK) 56489b16bb4SAndrew Lindesay code = ""; 56504c9d578SStephan Aßmus { 56604c9d578SStephan Aßmus BAutolock locker(fModel.Lock()); 567*363fc60bSAndrew Lindesay fModel.PackageFilter()->SetCategory(code); 56804c9d578SStephan Aßmus } 56904c9d578SStephan Aßmus _AdoptModel(); 57004c9d578SStephan Aßmus break; 57104c9d578SStephan Aßmus } 57204c9d578SStephan Aßmus 57304c9d578SStephan Aßmus case MSG_DEPOT_SELECTED: 57404c9d578SStephan Aßmus { 57504c9d578SStephan Aßmus BString name; 57604c9d578SStephan Aßmus if (message->FindString("name", &name) != B_OK) 57704c9d578SStephan Aßmus name = ""; 57804c9d578SStephan Aßmus { 57904c9d578SStephan Aßmus BAutolock locker(fModel.Lock()); 580*363fc60bSAndrew Lindesay fModel.PackageFilter()->SetDepotName(name); 58104c9d578SStephan Aßmus } 58204c9d578SStephan Aßmus _AdoptModel(); 583b965ce70SHumdinger _UpdateAvailableRepositories(); 58404c9d578SStephan Aßmus break; 58504c9d578SStephan Aßmus } 58604c9d578SStephan Aßmus 58704c9d578SStephan Aßmus case MSG_SEARCH_TERMS_MODIFIED: 58804c9d578SStephan Aßmus { 58904c9d578SStephan Aßmus // TODO: Do this with a delay! 59004c9d578SStephan Aßmus BString searchTerms; 59104c9d578SStephan Aßmus if (message->FindString("search terms", &searchTerms) != B_OK) 59204c9d578SStephan Aßmus searchTerms = ""; 59304c9d578SStephan Aßmus { 59404c9d578SStephan Aßmus BAutolock locker(fModel.Lock()); 595*363fc60bSAndrew Lindesay fModel.PackageFilter()->SetSearchTerms(searchTerms); 59604c9d578SStephan Aßmus } 59704c9d578SStephan Aßmus _AdoptModel(); 59804c9d578SStephan Aßmus break; 59904c9d578SStephan Aßmus } 60004c9d578SStephan Aßmus 601da651104SStephan Aßmus case MSG_PACKAGE_CHANGED: 60204c9d578SStephan Aßmus { 60304c9d578SStephan Aßmus PackageInfo* info; 60404c9d578SStephan Aßmus if (message->FindPointer("package", (void**)&info) == B_OK) { 60504c9d578SStephan Aßmus PackageInfoRef ref(info, true); 6060b69420bSAndrew Lindesay fFeaturedPackagesView->BeginAddRemove(); 607c4199192SAndrew Lindesay _AddRemovePackageFromLists(ref); 6080b69420bSAndrew Lindesay fFeaturedPackagesView->EndAddRemove(); 60910cd325cSAndrew Lindesay } 61004c9d578SStephan Aßmus break; 61104c9d578SStephan Aßmus } 61204c9d578SStephan Aßmus 613409af934SAndrew Lindesay case MSG_PROCESS_COORDINATOR_CHANGED: 614409af934SAndrew Lindesay { 615409af934SAndrew Lindesay ProcessCoordinatorState state(message); 616409af934SAndrew Lindesay _HandleProcessCoordinatorChanged(state); 617409af934SAndrew Lindesay break; 618409af934SAndrew Lindesay } 619409af934SAndrew Lindesay 62004c9d578SStephan Aßmus case MSG_RATE_PACKAGE: 6211bbda92dSStephan Aßmus _RatePackage(); 62204c9d578SStephan Aßmus break; 62304c9d578SStephan Aßmus 624d5ef985eSStephan Aßmus case MSG_SHOW_SCREENSHOT: 625d5ef985eSStephan Aßmus _ShowScreenshot(); 626d5ef985eSStephan Aßmus break; 627d5ef985eSStephan Aßmus 628125d42d9SJulian Harnath case MSG_PACKAGE_WORKER_BUSY: 629125d42d9SJulian Harnath { 630125d42d9SJulian Harnath BString reason; 631125d42d9SJulian Harnath status_t status = message->FindString("reason", &reason); 632125d42d9SJulian Harnath if (status != B_OK) 633125d42d9SJulian Harnath break; 634125d42d9SJulian Harnath fWorkStatusView->SetBusy(reason); 635125d42d9SJulian Harnath break; 636125d42d9SJulian Harnath } 637125d42d9SJulian Harnath 638125d42d9SJulian Harnath case MSG_PACKAGE_WORKER_IDLE: 639125d42d9SJulian Harnath fWorkStatusView->SetIdle(); 640125d42d9SJulian Harnath break; 641125d42d9SJulian Harnath 64210cd325cSAndrew Lindesay case MSG_USER_USAGE_CONDITIONS_NOT_LATEST: 64310cd325cSAndrew Lindesay { 64410cd325cSAndrew Lindesay BMessage userDetailMsg; 64510cd325cSAndrew Lindesay if (message->FindMessage("userDetail", &userDetailMsg) != B_OK) { 64610cd325cSAndrew Lindesay debugger("expected the [userDetail] data to be carried in the " 64710cd325cSAndrew Lindesay "message."); 64810cd325cSAndrew Lindesay } 64910cd325cSAndrew Lindesay UserDetail userDetail(&userDetailMsg); 65010cd325cSAndrew Lindesay _HandleUserUsageConditionsNotLatest(userDetail); 65110cd325cSAndrew Lindesay break; 65210cd325cSAndrew Lindesay } 65310cd325cSAndrew Lindesay 65404c9d578SStephan Aßmus default: 65504c9d578SStephan Aßmus BWindow::MessageReceived(message); 65604c9d578SStephan Aßmus break; 65704c9d578SStephan Aßmus } 65804c9d578SStephan Aßmus } 65904c9d578SStephan Aßmus 66004c9d578SStephan Aßmus 661ccf707d0SAndrew Lindesay static const char* 662ccf707d0SAndrew Lindesay main_window_package_list_view_mode_str(package_list_view_mode mode) 663ccf707d0SAndrew Lindesay { 664ccf707d0SAndrew Lindesay if (mode == PROMINENT) 665ccf707d0SAndrew Lindesay return "PROMINENT"; 666ccf707d0SAndrew Lindesay return "ALL"; 667ccf707d0SAndrew Lindesay } 668ccf707d0SAndrew Lindesay 669ccf707d0SAndrew Lindesay 670ccf707d0SAndrew Lindesay static package_list_view_mode 671ccf707d0SAndrew Lindesay main_window_str_to_package_list_view_mode(const BString& str) 672ccf707d0SAndrew Lindesay { 673ccf707d0SAndrew Lindesay if (str == "PROMINENT") 674ccf707d0SAndrew Lindesay return PROMINENT; 675ccf707d0SAndrew Lindesay return ALL; 676ccf707d0SAndrew Lindesay } 677ccf707d0SAndrew Lindesay 678ccf707d0SAndrew Lindesay 67904c9d578SStephan Aßmus void 6804b347fccSAndrew Lindesay MainWindow::StoreSettings(BMessage& settings) 68104c9d578SStephan Aßmus { 682f7c2983eSAxel Dörfler settings.AddRect(_WindowFrameName(), Frame()); 683f7c2983eSAxel Dörfler if (!fSinglePackageMode) { 68404c9d578SStephan Aßmus settings.AddRect("window frame", Frame()); 68504c9d578SStephan Aßmus 68604c9d578SStephan Aßmus BMessage columnSettings; 6879883929bSAndrew Lindesay if (fPackageListView != NULL) 68804c9d578SStephan Aßmus fPackageListView->SaveState(&columnSettings); 68904c9d578SStephan Aßmus 69004c9d578SStephan Aßmus settings.AddMessage("column settings", &columnSettings); 69104c9d578SStephan Aßmus 692133ebab6SAndrew Lindesay settings.AddString(SETTING_PACKAGE_LIST_VIEW_MODE, 693ccf707d0SAndrew Lindesay main_window_package_list_view_mode_str( 694ccf707d0SAndrew Lindesay fModel.PackageListViewMode())); 695*363fc60bSAndrew Lindesay 696133ebab6SAndrew Lindesay settings.AddBool(SETTING_SHOW_AVAILABLE_PACKAGES, 697*363fc60bSAndrew Lindesay fModel.PackageFilter()->ShowAvailablePackages()); 698133ebab6SAndrew Lindesay settings.AddBool(SETTING_SHOW_INSTALLED_PACKAGES, 699*363fc60bSAndrew Lindesay fModel.PackageFilter()->ShowInstalledPackages()); 700133ebab6SAndrew Lindesay settings.AddBool(SETTING_SHOW_DEVELOP_PACKAGES, 701*363fc60bSAndrew Lindesay fModel.PackageFilter()->ShowDevelopPackages()); 702133ebab6SAndrew Lindesay settings.AddBool(SETTING_SHOW_SOURCE_PACKAGES, 703*363fc60bSAndrew Lindesay fModel.PackageFilter()->ShowSourcePackages()); 704*363fc60bSAndrew Lindesay 705133ebab6SAndrew Lindesay settings.AddBool(SETTING_CAN_SHARE_ANONYMOUS_USER_DATA, 706133ebab6SAndrew Lindesay fModel.CanShareAnonymousUsageData()); 7076d519fd1SStephan Aßmus } 7088f03a0f9SStephan Aßmus 709d2d4866dSAndrew Lindesay settings.AddString("username", fModel.Nickname()); 71004c9d578SStephan Aßmus } 71104c9d578SStephan Aßmus 71204c9d578SStephan Aßmus 71304c9d578SStephan Aßmus void 714a18f873fSAndrew Lindesay MainWindow::Consume(ProcessCoordinator *item) 715a18f873fSAndrew Lindesay { 716a18f873fSAndrew Lindesay _AddProcessCoordinator(item); 717a18f873fSAndrew Lindesay } 718a18f873fSAndrew Lindesay 719a18f873fSAndrew Lindesay 720a18f873fSAndrew Lindesay void 72104c9d578SStephan Aßmus MainWindow::PackageChanged(const PackageInfoEvent& event) 72204c9d578SStephan Aßmus { 723a9edb9bfSAndrew Lindesay uint32 watchedChanges = PKG_CHANGED_STATE | PKG_CHANGED_PROMINENCE; 724a9edb9bfSAndrew Lindesay if ((event.Changes() & watchedChanges) != 0) { 72504c9d578SStephan Aßmus PackageInfoRef ref(event.Package()); 726da651104SStephan Aßmus BMessage message(MSG_PACKAGE_CHANGED); 72704c9d578SStephan Aßmus message.AddPointer("package", ref.Get()); 72804c9d578SStephan Aßmus ref.Detach(); 72904c9d578SStephan Aßmus // reference needs to be released by MessageReceived(); 73004c9d578SStephan Aßmus PostMessage(&message); 73104c9d578SStephan Aßmus } 73204c9d578SStephan Aßmus } 73304c9d578SStephan Aßmus 73404c9d578SStephan Aßmus 73504c9d578SStephan Aßmus void 73604c9d578SStephan Aßmus MainWindow::_BuildMenu(BMenuBar* menuBar) 73704c9d578SStephan Aßmus { 7380b6928f1SHumdinger BMenu* menu = new BMenu(B_TRANSLATE_SYSTEM_NAME("HaikuDepot")); 7393369e03dSAndrew Lindesay fRefreshRepositoriesItem = new BMenuItem( 7403369e03dSAndrew Lindesay B_TRANSLATE("Refresh repositories"), new BMessage(MSG_REFRESH_REPOS)); 7413369e03dSAndrew Lindesay menu->AddItem(fRefreshRepositoriesItem); 742d7f78130SHumdinger menu->AddItem(new BMenuItem(B_TRANSLATE("Manage repositories" 743d7f78130SHumdinger B_UTF8_ELLIPSIS), new BMessage(MSG_MANAGE_REPOS))); 744d144f952SAugustin Cavalier menu->AddItem(new BMenuItem(B_TRANSLATE("Check for updates" 745d144f952SAugustin Cavalier B_UTF8_ELLIPSIS), new BMessage(MSG_SOFTWARE_UPDATER))); 7460b6928f1SHumdinger menu->AddSeparatorItem(); 7470b6928f1SHumdinger menu->AddItem(new BMenuItem(B_TRANSLATE("Settings" B_UTF8_ELLIPSIS), 748e1ae57abSJoachim Mairböck new BMessage(MSG_SETTINGS), ',')); 7490b6928f1SHumdinger menu->AddItem(new BMenuItem(B_TRANSLATE("Quit"), 7500b6928f1SHumdinger new BMessage(B_QUIT_REQUESTED), 'Q')); 75104c9d578SStephan Aßmus menuBar->AddItem(menu); 75204c9d578SStephan Aßmus 753b965ce70SHumdinger fRepositoryMenu = new BMenu(B_TRANSLATE("Repositories")); 754b965ce70SHumdinger menuBar->AddItem(fRepositoryMenu); 755b965ce70SHumdinger 7564fade61fSStephan Aßmus menu = new BMenu(B_TRANSLATE("Show")); 7574fade61fSStephan Aßmus 758fdec4227SStephan Aßmus fShowAvailablePackagesItem = new BMenuItem( 7594fade61fSStephan Aßmus B_TRANSLATE("Available packages"), 760fdec4227SStephan Aßmus new BMessage(MSG_SHOW_AVAILABLE_PACKAGES)); 761fdec4227SStephan Aßmus menu->AddItem(fShowAvailablePackagesItem); 762fdec4227SStephan Aßmus 763fdec4227SStephan Aßmus fShowInstalledPackagesItem = new BMenuItem( 7644fade61fSStephan Aßmus B_TRANSLATE("Installed packages"), 765fdec4227SStephan Aßmus new BMessage(MSG_SHOW_INSTALLED_PACKAGES)); 766fdec4227SStephan Aßmus menu->AddItem(fShowInstalledPackagesItem); 767fdec4227SStephan Aßmus 768fdec4227SStephan Aßmus menu->AddSeparatorItem(); 769fdec4227SStephan Aßmus 770fdec4227SStephan Aßmus fShowDevelopPackagesItem = new BMenuItem( 7714fade61fSStephan Aßmus B_TRANSLATE("Develop packages"), 772fdec4227SStephan Aßmus new BMessage(MSG_SHOW_DEVELOP_PACKAGES)); 773fdec4227SStephan Aßmus menu->AddItem(fShowDevelopPackagesItem); 774fdec4227SStephan Aßmus 775fdec4227SStephan Aßmus fShowSourcePackagesItem = new BMenuItem( 7764fade61fSStephan Aßmus B_TRANSLATE("Source packages"), 777fdec4227SStephan Aßmus new BMessage(MSG_SHOW_SOURCE_PACKAGES)); 778fdec4227SStephan Aßmus menu->AddItem(fShowSourcePackagesItem); 779fdec4227SStephan Aßmus 780fdec4227SStephan Aßmus menuBar->AddItem(menu); 78104c9d578SStephan Aßmus } 78204c9d578SStephan Aßmus 78304c9d578SStephan Aßmus 78404c9d578SStephan Aßmus void 785e0a26dceSStephan Aßmus MainWindow::_BuildUserMenu(BMenuBar* menuBar) 786e0a26dceSStephan Aßmus { 787e0a26dceSStephan Aßmus fUserMenu = new BMenu(B_TRANSLATE("Not logged in")); 788e0a26dceSStephan Aßmus 789e0a26dceSStephan Aßmus fLogInItem = new BMenuItem(B_TRANSLATE("Log in" B_UTF8_ELLIPSIS), 790e0a26dceSStephan Aßmus new BMessage(MSG_LOG_IN)); 791e0a26dceSStephan Aßmus fUserMenu->AddItem(fLogInItem); 792e0a26dceSStephan Aßmus 793e0a26dceSStephan Aßmus fLogOutItem = new BMenuItem(B_TRANSLATE("Log out"), 794e0a26dceSStephan Aßmus new BMessage(MSG_LOG_OUT)); 795e0a26dceSStephan Aßmus fUserMenu->AddItem(fLogOutItem); 796e0a26dceSStephan Aßmus 7970c82f64bSAndrew Lindesay BMenuItem *latestUserUsageConditionsMenuItem = 7981448ced0SHumdinger new BMenuItem(B_TRANSLATE("View latest usage conditions" 79901339a54SAndrew Lindesay B_UTF8_ELLIPSIS), 80001339a54SAndrew Lindesay new BMessage(MSG_VIEW_LATEST_USER_USAGE_CONDITIONS)); 8010c82f64bSAndrew Lindesay fUserMenu->AddItem(latestUserUsageConditionsMenuItem); 80201339a54SAndrew Lindesay 803d2d4866dSAndrew Lindesay fUsersUserUsageConditionsMenuItem = 804d2d4866dSAndrew Lindesay new BMenuItem(B_TRANSLATE("View agreed usage conditions" 805d2d4866dSAndrew Lindesay B_UTF8_ELLIPSIS), 806d2d4866dSAndrew Lindesay new BMessage(MSG_VIEW_USERS_USER_USAGE_CONDITIONS)); 807d2d4866dSAndrew Lindesay fUserMenu->AddItem(fUsersUserUsageConditionsMenuItem); 808d2d4866dSAndrew Lindesay 809e0a26dceSStephan Aßmus menuBar->AddItem(fUserMenu); 810e0a26dceSStephan Aßmus } 811e0a26dceSStephan Aßmus 812e0a26dceSStephan Aßmus 813e0a26dceSStephan Aßmus void 814d2d4866dSAndrew Lindesay MainWindow::_RestoreNickname(const BMessage& settings) 815f7c2983eSAxel Dörfler { 816d2d4866dSAndrew Lindesay BString nickname; 817d2d4866dSAndrew Lindesay if (settings.FindString("username", &nickname) == B_OK 818d2d4866dSAndrew Lindesay && nickname.Length() > 0) { 819d2d4866dSAndrew Lindesay fModel.SetNickname(nickname); 820f7c2983eSAxel Dörfler } 821f7c2983eSAxel Dörfler } 822f7c2983eSAxel Dörfler 823f7c2983eSAxel Dörfler 824f7c2983eSAxel Dörfler const char* 825f7c2983eSAxel Dörfler MainWindow::_WindowFrameName() const 826f7c2983eSAxel Dörfler { 827f7c2983eSAxel Dörfler if (fSinglePackageMode) 828f7c2983eSAxel Dörfler return "small window frame"; 829f7c2983eSAxel Dörfler 830f7c2983eSAxel Dörfler return "window frame"; 831f7c2983eSAxel Dörfler } 832f7c2983eSAxel Dörfler 833f7c2983eSAxel Dörfler 834f7c2983eSAxel Dörfler void 835f7c2983eSAxel Dörfler MainWindow::_RestoreWindowFrame(const BMessage& settings) 836f7c2983eSAxel Dörfler { 837f7c2983eSAxel Dörfler BRect frame = Frame(); 838f7c2983eSAxel Dörfler 839f7c2983eSAxel Dörfler BRect windowFrame; 840f7c2983eSAxel Dörfler bool fromSettings = false; 841f7c2983eSAxel Dörfler if (settings.FindRect(_WindowFrameName(), &windowFrame) == B_OK) { 842f7c2983eSAxel Dörfler frame = windowFrame; 843f7c2983eSAxel Dörfler fromSettings = true; 844f7c2983eSAxel Dörfler } else if (!fSinglePackageMode) { 845f7c2983eSAxel Dörfler // Resize to occupy a certain screen size 846f7c2983eSAxel Dörfler BRect screenFrame = BScreen(this).Frame(); 847f7c2983eSAxel Dörfler float width = frame.Width(); 848f7c2983eSAxel Dörfler float height = frame.Height(); 849f7c2983eSAxel Dörfler if (width < screenFrame.Width() * .666f 850f7c2983eSAxel Dörfler && height < screenFrame.Height() * .666f) { 851f7c2983eSAxel Dörfler frame.bottom = frame.top + screenFrame.Height() * .666f; 852f7c2983eSAxel Dörfler frame.right = frame.left 853f7c2983eSAxel Dörfler + std::min(screenFrame.Width() * .666f, height * 7 / 5); 854f7c2983eSAxel Dörfler } 855f7c2983eSAxel Dörfler } 856f7c2983eSAxel Dörfler 857f7c2983eSAxel Dörfler MoveTo(frame.LeftTop()); 858f7c2983eSAxel Dörfler ResizeTo(frame.Width(), frame.Height()); 859f7c2983eSAxel Dörfler 860f7c2983eSAxel Dörfler if (fromSettings) 8618e96ec34SAxel Dörfler MoveOnScreen(); 862f7c2983eSAxel Dörfler else 863f7c2983eSAxel Dörfler CenterOnScreen(); 864f7c2983eSAxel Dörfler } 865f7c2983eSAxel Dörfler 866f7c2983eSAxel Dörfler 867f7c2983eSAxel Dörfler void 868ccf707d0SAndrew Lindesay MainWindow::_RestoreModelSettings(const BMessage& settings) 869ccf707d0SAndrew Lindesay { 870ccf707d0SAndrew Lindesay BString packageListViewMode; 871133ebab6SAndrew Lindesay if (settings.FindString(SETTING_PACKAGE_LIST_VIEW_MODE, 872ccf707d0SAndrew Lindesay &packageListViewMode) == B_OK) { 873ccf707d0SAndrew Lindesay fModel.SetPackageListViewMode( 874ccf707d0SAndrew Lindesay main_window_str_to_package_list_view_mode(packageListViewMode)); 875ccf707d0SAndrew Lindesay } 876ccf707d0SAndrew Lindesay 877ccf707d0SAndrew Lindesay bool showOption; 878*363fc60bSAndrew Lindesay 879133ebab6SAndrew Lindesay if (settings.FindBool(SETTING_SHOW_AVAILABLE_PACKAGES, &showOption) == B_OK) 880*363fc60bSAndrew Lindesay fModel.PackageFilter()->SetShowAvailablePackages(showOption); 881133ebab6SAndrew Lindesay if (settings.FindBool(SETTING_SHOW_INSTALLED_PACKAGES, &showOption) == B_OK) 882*363fc60bSAndrew Lindesay fModel.PackageFilter()->SetShowInstalledPackages(showOption); 883133ebab6SAndrew Lindesay if (settings.FindBool(SETTING_SHOW_DEVELOP_PACKAGES, &showOption) == B_OK) 884*363fc60bSAndrew Lindesay fModel.PackageFilter()->SetShowDevelopPackages(showOption); 885133ebab6SAndrew Lindesay if (settings.FindBool(SETTING_SHOW_SOURCE_PACKAGES, &showOption) == B_OK) 886*363fc60bSAndrew Lindesay fModel.PackageFilter()->SetShowSourcePackages(showOption); 887*363fc60bSAndrew Lindesay 888133ebab6SAndrew Lindesay if (settings.FindBool(SETTING_CAN_SHARE_ANONYMOUS_USER_DATA, 889133ebab6SAndrew Lindesay &showOption) == B_OK) { 890133ebab6SAndrew Lindesay fModel.SetCanShareAnonymousUsageData(showOption); 891133ebab6SAndrew Lindesay } 892133ebab6SAndrew Lindesay } 893133ebab6SAndrew Lindesay 894133ebab6SAndrew Lindesay 895133ebab6SAndrew Lindesay void 896133ebab6SAndrew Lindesay MainWindow::_MaybePromptCanShareAnonymousUserData(const BMessage& settings) 897133ebab6SAndrew Lindesay { 898133ebab6SAndrew Lindesay bool showOption; 899133ebab6SAndrew Lindesay if (settings.FindBool(SETTING_CAN_SHARE_ANONYMOUS_USER_DATA, 900133ebab6SAndrew Lindesay &showOption) == B_NAME_NOT_FOUND) { 901133ebab6SAndrew Lindesay _PromptCanShareAnonymousUserData(); 902133ebab6SAndrew Lindesay } 903133ebab6SAndrew Lindesay } 904133ebab6SAndrew Lindesay 905133ebab6SAndrew Lindesay 906133ebab6SAndrew Lindesay void 907133ebab6SAndrew Lindesay MainWindow::_PromptCanShareAnonymousUserData() 908133ebab6SAndrew Lindesay { 909133ebab6SAndrew Lindesay BAlert* alert = new(std::nothrow) BAlert( 910133ebab6SAndrew Lindesay B_TRANSLATE("Sending anonymous usage data"), 911133ebab6SAndrew Lindesay B_TRANSLATE("Would it be acceptable to send anonymous usage data to the" 912133ebab6SAndrew Lindesay " HaikuDepotServer system from this computer? You can change your" 913133ebab6SAndrew Lindesay " preference in the \"Settings\" window later."), 914133ebab6SAndrew Lindesay B_TRANSLATE("No"), 915133ebab6SAndrew Lindesay B_TRANSLATE("Yes")); 916133ebab6SAndrew Lindesay 917133ebab6SAndrew Lindesay int32 result = alert->Go(); 918133ebab6SAndrew Lindesay fModel.SetCanShareAnonymousUsageData(1 == result); 919ccf707d0SAndrew Lindesay } 920ccf707d0SAndrew Lindesay 921ccf707d0SAndrew Lindesay 922ccf707d0SAndrew Lindesay void 92363975654SStephan Aßmus MainWindow::_InitWorkerThreads() 92463975654SStephan Aßmus { 92563975654SStephan Aßmus fPackageToPopulateSem = create_sem(0, "PopulatePackage"); 92663975654SStephan Aßmus if (fPackageToPopulateSem >= 0) { 92763975654SStephan Aßmus fPopulatePackageWorker = spawn_thread(&_PopulatePackageWorker, 92863975654SStephan Aßmus "Package Populator", B_NORMAL_PRIORITY, this); 92963975654SStephan Aßmus if (fPopulatePackageWorker >= 0) 93063975654SStephan Aßmus resume_thread(fPopulatePackageWorker); 93109f82905SStephan Aßmus } else 93209f82905SStephan Aßmus fPopulatePackageWorker = -1; 93363975654SStephan Aßmus } 93463975654SStephan Aßmus 93563975654SStephan Aßmus 93663975654SStephan Aßmus void 937c4199192SAndrew Lindesay MainWindow::_AdoptModelControls() 93804c9d578SStephan Aßmus { 9399883929bSAndrew Lindesay if (fSinglePackageMode) 9409883929bSAndrew Lindesay return; 9419883929bSAndrew Lindesay 94204c9d578SStephan Aßmus BAutolock locker(fModel.Lock()); 943*363fc60bSAndrew Lindesay fShowAvailablePackagesItem->SetMarked(fModel.PackageFilter()->ShowAvailablePackages()); 944*363fc60bSAndrew Lindesay fShowInstalledPackagesItem->SetMarked(fModel.PackageFilter()->ShowInstalledPackages()); 945*363fc60bSAndrew Lindesay fShowSourcePackagesItem->SetMarked(fModel.PackageFilter()->ShowSourcePackages()); 946*363fc60bSAndrew Lindesay fShowDevelopPackagesItem->SetMarked(fModel.PackageFilter()->ShowDevelopPackages()); 947da651104SStephan Aßmus 948ccf707d0SAndrew Lindesay if (fModel.PackageListViewMode() == PROMINENT) 949ccf707d0SAndrew Lindesay fListTabs->Select(TAB_PROMINENT_PACKAGES); 9504fade61fSStephan Aßmus else 951ccf707d0SAndrew Lindesay fListTabs->Select(TAB_ALL_PACKAGES); 952b965ce70SHumdinger 953b965ce70SHumdinger fFilterView->AdoptModel(fModel); 95404c9d578SStephan Aßmus } 95504c9d578SStephan Aßmus 95604c9d578SStephan Aßmus 95704c9d578SStephan Aßmus void 958c4199192SAndrew Lindesay MainWindow::_AdoptModel() 959c4199192SAndrew Lindesay { 960fa5c8097SAndrew Lindesay HDTRACE("adopting model to main window ui"); 961c4199192SAndrew Lindesay 962c4199192SAndrew Lindesay if (fSinglePackageMode) 963c4199192SAndrew Lindesay return; 964c4199192SAndrew Lindesay 96505880d13SAndrew Lindesay std::vector<DepotInfoRef> depots = _CreateSnapshotOfDepots(); 96605880d13SAndrew Lindesay std::vector<DepotInfoRef>::iterator it; 9670b69420bSAndrew Lindesay 9680b69420bSAndrew Lindesay fFeaturedPackagesView->BeginAddRemove(); 9690b69420bSAndrew Lindesay 97005880d13SAndrew Lindesay for (it = depots.begin(); it != depots.end(); it++) { 97105880d13SAndrew Lindesay DepotInfoRef depotInfoRef = *it; 972d75b4d61SAndrew Lindesay for (int i = 0; i < depotInfoRef->CountPackages(); i++) { 973d75b4d61SAndrew Lindesay PackageInfoRef package = depotInfoRef->PackageAtIndex(i); 974d75b4d61SAndrew Lindesay _AddRemovePackageFromLists(package); 975d75b4d61SAndrew Lindesay } 976c4199192SAndrew Lindesay } 977c4199192SAndrew Lindesay 9780b69420bSAndrew Lindesay fFeaturedPackagesView->EndAddRemove(); 9790b69420bSAndrew Lindesay 980c4199192SAndrew Lindesay _AdoptModelControls(); 981c4199192SAndrew Lindesay } 982c4199192SAndrew Lindesay 983c4199192SAndrew Lindesay 984c4199192SAndrew Lindesay void 985c4199192SAndrew Lindesay MainWindow::_AddRemovePackageFromLists(const PackageInfoRef& package) 986c4199192SAndrew Lindesay { 987c4199192SAndrew Lindesay bool matches; 988c4199192SAndrew Lindesay 989c4199192SAndrew Lindesay { 990c4199192SAndrew Lindesay AutoLocker<BLocker> modelLocker(fModel.Lock()); 991*363fc60bSAndrew Lindesay matches = fModel.PackageFilter()->Filter()->AcceptsPackage(package); 992c4199192SAndrew Lindesay } 993c4199192SAndrew Lindesay 994c4199192SAndrew Lindesay if (matches) { 995c4199192SAndrew Lindesay if (package->IsProminent()) 996c4199192SAndrew Lindesay fFeaturedPackagesView->AddPackage(package); 997c4199192SAndrew Lindesay fPackageListView->AddPackage(package); 998c4199192SAndrew Lindesay } else { 999c4199192SAndrew Lindesay fFeaturedPackagesView->RemovePackage(package); 1000c4199192SAndrew Lindesay fPackageListView->RemovePackage(package); 1001c4199192SAndrew Lindesay } 1002c4199192SAndrew Lindesay } 1003c4199192SAndrew Lindesay 1004c4199192SAndrew Lindesay 1005c4199192SAndrew Lindesay void 100684674570SAndrew Lindesay MainWindow::_SetupDelayedIncrementViewCounter(const PackageInfoRef package) { 100784674570SAndrew Lindesay if (fIncrementViewCounterDelayedRunner != NULL) { 100884674570SAndrew Lindesay fIncrementViewCounterDelayedRunner->SetCount(0); 100984674570SAndrew Lindesay delete fIncrementViewCounterDelayedRunner; 101084674570SAndrew Lindesay } 101184674570SAndrew Lindesay BMessage message(MSG_INCREMENT_VIEW_COUNTER); 101284674570SAndrew Lindesay message.SetString("name", package->Name()); 101384674570SAndrew Lindesay fIncrementViewCounterDelayedRunner = 101484674570SAndrew Lindesay new BMessageRunner(BMessenger(this), &message, 101584674570SAndrew Lindesay kIncrementViewCounterDelayMicros, 1); 101684674570SAndrew Lindesay if (fIncrementViewCounterDelayedRunner->InitCheck() 101784674570SAndrew Lindesay != B_OK) { 101884674570SAndrew Lindesay HDERROR("unable to init the increment view counter"); 101984674570SAndrew Lindesay } 102084674570SAndrew Lindesay } 102184674570SAndrew Lindesay 102284674570SAndrew Lindesay 102384674570SAndrew Lindesay void 102484674570SAndrew Lindesay MainWindow::_HandleIncrementViewCounter(const BMessage* message) 102584674570SAndrew Lindesay { 102684674570SAndrew Lindesay BString name; 102784674570SAndrew Lindesay if (message->FindString("name", &name) == B_OK) { 102884674570SAndrew Lindesay const PackageInfoRef& viewedPackage = 102984674570SAndrew Lindesay fPackageInfoView->Package(); 103084674570SAndrew Lindesay if (viewedPackage.IsSet()) { 103184674570SAndrew Lindesay if (viewedPackage->Name() == name) 103284674570SAndrew Lindesay _IncrementViewCounter(viewedPackage); 103384674570SAndrew Lindesay else 103484674570SAndrew Lindesay HDINFO("incr. view counter; name mismatch"); 103584674570SAndrew Lindesay } else 103684674570SAndrew Lindesay HDINFO("incr. view counter; no viewed pkg"); 103784674570SAndrew Lindesay } else 103884674570SAndrew Lindesay HDERROR("incr. view counter; no name"); 103984674570SAndrew Lindesay fIncrementViewCounterDelayedRunner->SetCount(0); 104084674570SAndrew Lindesay delete fIncrementViewCounterDelayedRunner; 104184674570SAndrew Lindesay fIncrementViewCounterDelayedRunner = NULL; 104284674570SAndrew Lindesay } 104384674570SAndrew Lindesay 104484674570SAndrew Lindesay 104584674570SAndrew Lindesay void 1046409af934SAndrew Lindesay MainWindow::_IncrementViewCounter(const PackageInfoRef package) 1047133ebab6SAndrew Lindesay { 1048133ebab6SAndrew Lindesay bool shouldIncrementViewCounter = false; 1049133ebab6SAndrew Lindesay 1050133ebab6SAndrew Lindesay { 1051133ebab6SAndrew Lindesay AutoLocker<BLocker> modelLocker(fModel.Lock()); 1052133ebab6SAndrew Lindesay bool canShareAnonymousUsageData = fModel.CanShareAnonymousUsageData(); 1053133ebab6SAndrew Lindesay if (canShareAnonymousUsageData && !package->Viewed()) { 1054133ebab6SAndrew Lindesay package->SetViewed(); 1055133ebab6SAndrew Lindesay shouldIncrementViewCounter = true; 1056133ebab6SAndrew Lindesay } 1057133ebab6SAndrew Lindesay } 1058133ebab6SAndrew Lindesay 1059133ebab6SAndrew Lindesay if (shouldIncrementViewCounter) { 1060467ffecdSAugustin Cavalier ProcessCoordinator* incrementViewCoordinator = 1061133ebab6SAndrew Lindesay ProcessCoordinatorFactory::CreateIncrementViewCounter( 1062133ebab6SAndrew Lindesay &fModel, package); 1063467ffecdSAugustin Cavalier _AddProcessCoordinator(incrementViewCoordinator); 1064133ebab6SAndrew Lindesay } 1065133ebab6SAndrew Lindesay } 1066133ebab6SAndrew Lindesay 1067133ebab6SAndrew Lindesay 1068133ebab6SAndrew Lindesay void 106904c9d578SStephan Aßmus MainWindow::_AdoptPackage(const PackageInfoRef& package) 107004c9d578SStephan Aßmus { 107175ba9dbfSStephan Aßmus { 107275ba9dbfSStephan Aßmus BAutolock locker(fModel.Lock()); 107304c9d578SStephan Aßmus fPackageInfoView->SetPackage(package); 10741986ab9fSStephan Aßmus 1075664372abSStephan Aßmus if (fFeaturedPackagesView != NULL) 1076664372abSStephan Aßmus fFeaturedPackagesView->SelectPackage(package); 10771986ab9fSStephan Aßmus if (fPackageListView != NULL) 10781986ab9fSStephan Aßmus fPackageListView->SelectPackage(package); 107975ba9dbfSStephan Aßmus } 108004c9d578SStephan Aßmus 1081a9edb9bfSAndrew Lindesay _PopulatePackageAsync(false); 108204c9d578SStephan Aßmus } 108304c9d578SStephan Aßmus 108404c9d578SStephan Aßmus 108504c9d578SStephan Aßmus void 108604c9d578SStephan Aßmus MainWindow::_ClearPackage() 108704c9d578SStephan Aßmus { 108804c9d578SStephan Aßmus fPackageInfoView->Clear(); 108904c9d578SStephan Aßmus } 109004c9d578SStephan Aßmus 109104c9d578SStephan Aßmus 109204c9d578SStephan Aßmus void 10933369e03dSAndrew Lindesay MainWindow::_StartBulkLoad(bool force) 109404c9d578SStephan Aßmus { 1095c4199192SAndrew Lindesay if (fFeaturedPackagesView != NULL) 1096c4199192SAndrew Lindesay fFeaturedPackagesView->Clear(); 1097c4199192SAndrew Lindesay if (fPackageListView != NULL) 1098c4199192SAndrew Lindesay fPackageListView->Clear(); 1099c4199192SAndrew Lindesay fPackageInfoView->Clear(); 1100c4199192SAndrew Lindesay 110110cd325cSAndrew Lindesay fRefreshRepositoriesItem->SetEnabled(false); 110210cd325cSAndrew Lindesay ProcessCoordinator* bulkLoadCoordinator = 110310cd325cSAndrew Lindesay ProcessCoordinatorFactory::CreateBulkLoadCoordinator( 1104409af934SAndrew Lindesay fPackageInfoListener, &fModel, force); 110510cd325cSAndrew Lindesay _AddProcessCoordinator(bulkLoadCoordinator); 110604c9d578SStephan Aßmus } 110704c9d578SStephan Aßmus 110804c9d578SStephan Aßmus 110904c9d578SStephan Aßmus void 111010cd325cSAndrew Lindesay MainWindow::_BulkLoadCompleteReceived(status_t errorStatus) 111104c9d578SStephan Aßmus { 111210cd325cSAndrew Lindesay if (errorStatus != B_OK) { 11133369e03dSAndrew Lindesay AppUtils::NotifySimpleError( 11141448ced0SHumdinger B_TRANSLATE("Package update error"), 11153369e03dSAndrew Lindesay B_TRANSLATE("While updating package data, a problem has arisen " 11163369e03dSAndrew Lindesay "that may cause data to be outdated or missing from the " 11173369e03dSAndrew Lindesay "application's display. Additional details regarding this " 11183369e03dSAndrew Lindesay "problem may be able to be obtained from the application " 1119b21c9447SAndrew Lindesay "logs." 1120b21c9447SAndrew Lindesay ALERT_MSG_LOGS_USER_GUIDE)); 112104c9d578SStephan Aßmus } 112210cd325cSAndrew Lindesay 11233369e03dSAndrew Lindesay fRefreshRepositoriesItem->SetEnabled(true); 112410cd325cSAndrew Lindesay _AdoptModel(); 112510cd325cSAndrew Lindesay _UpdateAvailableRepositories(); 1126ccf707d0SAndrew Lindesay 1127ccf707d0SAndrew Lindesay // if after loading everything in, it transpires that there are no 1128ccf707d0SAndrew Lindesay // featured packages then the featured packages should be disabled 1129ccf707d0SAndrew Lindesay // and the user should be switched to the "all packages" view so 1130ccf707d0SAndrew Lindesay // that they are not presented with a blank window! 1131ccf707d0SAndrew Lindesay 1132ccf707d0SAndrew Lindesay bool hasProminentPackages = fModel.HasAnyProminentPackages(); 1133ccf707d0SAndrew Lindesay fListTabs->TabAt(TAB_PROMINENT_PACKAGES)->SetEnabled(hasProminentPackages); 1134ccf707d0SAndrew Lindesay if (!hasProminentPackages 1135ccf707d0SAndrew Lindesay && fListTabs->Selection() == TAB_PROMINENT_PACKAGES) { 1136ccf707d0SAndrew Lindesay fModel.SetPackageListViewMode(ALL); 1137ccf707d0SAndrew Lindesay fListTabs->Select(TAB_ALL_PACKAGES); 1138ccf707d0SAndrew Lindesay } 113904c9d578SStephan Aßmus } 114004c9d578SStephan Aßmus 114104c9d578SStephan Aßmus 11423369e03dSAndrew Lindesay void 114310cd325cSAndrew Lindesay MainWindow::_NotifyWorkStatusClear() 114404c9d578SStephan Aßmus { 114510cd325cSAndrew Lindesay BMessage message(MSG_WORK_STATUS_CLEAR); 114610cd325cSAndrew Lindesay this->PostMessage(&message, this); 114710cd325cSAndrew Lindesay } 114810cd325cSAndrew Lindesay 114910cd325cSAndrew Lindesay 115010cd325cSAndrew Lindesay void 115110cd325cSAndrew Lindesay MainWindow::_HandleWorkStatusClear() 115210cd325cSAndrew Lindesay { 115310cd325cSAndrew Lindesay fWorkStatusView->SetText(""); 11543369e03dSAndrew Lindesay fWorkStatusView->SetIdle(); 11553369e03dSAndrew Lindesay } 115604c9d578SStephan Aßmus 115704c9d578SStephan Aßmus 11583369e03dSAndrew Lindesay /*! Sends off a message to the Window so that it can change the status view 11593369e03dSAndrew Lindesay on the front-end in the UI thread. 11603369e03dSAndrew Lindesay */ 116104c9d578SStephan Aßmus 11623369e03dSAndrew Lindesay void 11633369e03dSAndrew Lindesay MainWindow::_NotifyWorkStatusChange(const BString& text, float progress) 11643369e03dSAndrew Lindesay { 11653369e03dSAndrew Lindesay BMessage message(MSG_WORK_STATUS_CHANGE); 116604c9d578SStephan Aßmus 11673369e03dSAndrew Lindesay if (!text.IsEmpty()) 11683369e03dSAndrew Lindesay message.AddString(KEY_WORK_STATUS_TEXT, text); 11693369e03dSAndrew Lindesay message.AddFloat(KEY_WORK_STATUS_PROGRESS, progress); 117004c9d578SStephan Aßmus 11713369e03dSAndrew Lindesay this->PostMessage(&message, this); 11723369e03dSAndrew Lindesay } 117304c9d578SStephan Aßmus 11743369e03dSAndrew Lindesay 1175f32d5c5cSAndrew Lindesay void 1176f32d5c5cSAndrew Lindesay MainWindow::_HandleExternalPackageUpdateMessageReceived(const BMessage* message) 1177f32d5c5cSAndrew Lindesay { 1178f32d5c5cSAndrew Lindesay BStringList addedPackageNames; 1179f32d5c5cSAndrew Lindesay BStringList removedPackageNames; 1180f32d5c5cSAndrew Lindesay 1181f32d5c5cSAndrew Lindesay if (message->FindStrings("added package names", 1182f32d5c5cSAndrew Lindesay &addedPackageNames) == B_OK) { 1183f32d5c5cSAndrew Lindesay addedPackageNames.Sort(); 11840ebb9177SAndrew Lindesay AutoLocker<BLocker> locker(fModel.Lock()); 11850ebb9177SAndrew Lindesay fModel.SetStateForPackagesByName(addedPackageNames, ACTIVATED); 1186f32d5c5cSAndrew Lindesay } 1187f32d5c5cSAndrew Lindesay else 1188f32d5c5cSAndrew Lindesay HDINFO("no [added package names] key in inbound message"); 1189f32d5c5cSAndrew Lindesay 1190f32d5c5cSAndrew Lindesay if (message->FindStrings("removed package names", 1191f32d5c5cSAndrew Lindesay &removedPackageNames) == B_OK) { 1192f32d5c5cSAndrew Lindesay removedPackageNames.Sort(); 11930ebb9177SAndrew Lindesay AutoLocker<BLocker> locker(fModel.Lock()); 11940ebb9177SAndrew Lindesay fModel.SetStateForPackagesByName(addedPackageNames, UNINSTALLED); 1195f32d5c5cSAndrew Lindesay } else 1196f32d5c5cSAndrew Lindesay HDINFO("no [removed package names] key in inbound message"); 1197f32d5c5cSAndrew Lindesay } 1198f32d5c5cSAndrew Lindesay 1199f32d5c5cSAndrew Lindesay 12003369e03dSAndrew Lindesay void 12013369e03dSAndrew Lindesay MainWindow::_HandleWorkStatusChangeMessageReceived(const BMessage* message) 12023369e03dSAndrew Lindesay { 12039883929bSAndrew Lindesay if (fWorkStatusView == NULL) 12049883929bSAndrew Lindesay return; 12059883929bSAndrew Lindesay 12063369e03dSAndrew Lindesay BString text; 12073369e03dSAndrew Lindesay float progress; 12083369e03dSAndrew Lindesay 12093369e03dSAndrew Lindesay if (message->FindString(KEY_WORK_STATUS_TEXT, &text) == B_OK) 12103369e03dSAndrew Lindesay fWorkStatusView->SetText(text); 12113369e03dSAndrew Lindesay 1212a18f873fSAndrew Lindesay if (message->FindFloat(KEY_WORK_STATUS_PROGRESS, &progress) == B_OK) { 1213a18f873fSAndrew Lindesay if (progress < 0.0f) 1214a18f873fSAndrew Lindesay fWorkStatusView->SetBusy(); 1215a18f873fSAndrew Lindesay else 12163369e03dSAndrew Lindesay fWorkStatusView->SetProgress(progress); 1217a18f873fSAndrew Lindesay } else { 1218a18f873fSAndrew Lindesay HDERROR("work status change missing progress on update message"); 1219a18f873fSAndrew Lindesay fWorkStatusView->SetProgress(0.0f); 122004c9d578SStephan Aßmus } 122104c9d578SStephan Aßmus } 122204c9d578SStephan Aßmus 122304c9d578SStephan Aßmus 1224a9edb9bfSAndrew Lindesay /*! This method will cause the package to have its data refreshed from 1225a9edb9bfSAndrew Lindesay the server application. The refresh happens in the background; this method 1226a9edb9bfSAndrew Lindesay is asynchronous. 1227a9edb9bfSAndrew Lindesay */ 1228a9edb9bfSAndrew Lindesay 1229a9edb9bfSAndrew Lindesay void 1230a9edb9bfSAndrew Lindesay MainWindow::_PopulatePackageAsync(bool forcePopulate) 1231a9edb9bfSAndrew Lindesay { 1232a9edb9bfSAndrew Lindesay // Trigger asynchronous package population from the web-app 1233a9edb9bfSAndrew Lindesay { 1234a9edb9bfSAndrew Lindesay AutoLocker<BLocker> lock(&fPackageToPopulateLock); 1235a9edb9bfSAndrew Lindesay fPackageToPopulate = fPackageInfoView->Package(); 1236a9edb9bfSAndrew Lindesay fForcePopulatePackage = forcePopulate; 1237a9edb9bfSAndrew Lindesay } 1238a9edb9bfSAndrew Lindesay release_sem_etc(fPackageToPopulateSem, 1, 0); 1239a9edb9bfSAndrew Lindesay 1240f96d1f4dSAndrew Lindesay HDDEBUG("pkg [%s] will be updated from the server.", 1241fa5c8097SAndrew Lindesay fPackageToPopulate->Name().String()); 1242a9edb9bfSAndrew Lindesay } 1243a9edb9bfSAndrew Lindesay 1244a9edb9bfSAndrew Lindesay 1245a9edb9bfSAndrew Lindesay /*! This method will run in the background. The thread will block until there 1246a9edb9bfSAndrew Lindesay is a package to be updated. When the thread unblocks, it will update the 1247a9edb9bfSAndrew Lindesay package with information from the server. 1248a9edb9bfSAndrew Lindesay */ 1249a9edb9bfSAndrew Lindesay 125004c9d578SStephan Aßmus status_t 125104c9d578SStephan Aßmus MainWindow::_PopulatePackageWorker(void* arg) 125204c9d578SStephan Aßmus { 125304c9d578SStephan Aßmus MainWindow* window = reinterpret_cast<MainWindow*>(arg); 125404c9d578SStephan Aßmus 125504c9d578SStephan Aßmus while (acquire_sem(window->fPackageToPopulateSem) == B_OK) { 125604c9d578SStephan Aßmus PackageInfoRef package; 1257a9edb9bfSAndrew Lindesay bool force; 125804c9d578SStephan Aßmus { 125904c9d578SStephan Aßmus AutoLocker<BLocker> lock(&window->fPackageToPopulateLock); 126004c9d578SStephan Aßmus package = window->fPackageToPopulate; 1261a9edb9bfSAndrew Lindesay force = window->fForcePopulatePackage; 126204c9d578SStephan Aßmus } 126304c9d578SStephan Aßmus 1264779ab335SX512 if (package.IsSet()) { 1265a9edb9bfSAndrew Lindesay uint32 populateFlags = Model::POPULATE_USER_RATINGS 1266a9edb9bfSAndrew Lindesay | Model::POPULATE_CHANGELOG; 1267a9edb9bfSAndrew Lindesay 1268a9edb9bfSAndrew Lindesay if (force) 1269a9edb9bfSAndrew Lindesay populateFlags |= Model::POPULATE_FORCE; 1270a9edb9bfSAndrew Lindesay 1271a9edb9bfSAndrew Lindesay window->fModel.PopulatePackage(package, populateFlags); 1272a9edb9bfSAndrew Lindesay 1273fa5c8097SAndrew Lindesay HDDEBUG("populating package [%s]", package->Name().String()); 127404c9d578SStephan Aßmus } 127504c9d578SStephan Aßmus } 127604c9d578SStephan Aßmus 127704c9d578SStephan Aßmus return 0; 127804c9d578SStephan Aßmus } 127904c9d578SStephan Aßmus 128004c9d578SStephan Aßmus 128104c9d578SStephan Aßmus void 1282133ebab6SAndrew Lindesay MainWindow::_OpenSettingsWindow() 1283133ebab6SAndrew Lindesay { 1284133ebab6SAndrew Lindesay SettingsWindow* window = new SettingsWindow(this, &fModel); 1285133ebab6SAndrew Lindesay window->Show(); 1286133ebab6SAndrew Lindesay } 1287133ebab6SAndrew Lindesay 1288133ebab6SAndrew Lindesay 1289133ebab6SAndrew Lindesay void 12901bbda92dSStephan Aßmus MainWindow::_OpenLoginWindow(const BMessage& onSuccessMessage) 129104c9d578SStephan Aßmus { 129204c9d578SStephan Aßmus UserLoginWindow* window = new UserLoginWindow(this, 129304c9d578SStephan Aßmus BRect(0, 0, 500, 400), fModel); 12941bbda92dSStephan Aßmus 12951bbda92dSStephan Aßmus if (onSuccessMessage.what != 0) 12961bbda92dSStephan Aßmus window->SetOnSuccessMessage(BMessenger(this), onSuccessMessage); 12971bbda92dSStephan Aßmus 129804c9d578SStephan Aßmus window->Show(); 129904c9d578SStephan Aßmus } 130004c9d578SStephan Aßmus 13018f03a0f9SStephan Aßmus 13028f03a0f9SStephan Aßmus void 130310cd325cSAndrew Lindesay MainWindow::_StartUserVerify() 130410cd325cSAndrew Lindesay { 130510cd325cSAndrew Lindesay if (!fModel.Nickname().IsEmpty()) { 130610cd325cSAndrew Lindesay _AddProcessCoordinator( 130710cd325cSAndrew Lindesay ProcessCoordinatorFactory::CreateUserDetailVerifierCoordinator( 130810cd325cSAndrew Lindesay this, 130910cd325cSAndrew Lindesay // UserDetailVerifierListener 131010cd325cSAndrew Lindesay &fModel) ); 131110cd325cSAndrew Lindesay } 131210cd325cSAndrew Lindesay } 131310cd325cSAndrew Lindesay 131410cd325cSAndrew Lindesay 131510cd325cSAndrew Lindesay void 13168f03a0f9SStephan Aßmus MainWindow::_UpdateAuthorization() 13178f03a0f9SStephan Aßmus { 1318d2d4866dSAndrew Lindesay BString nickname(fModel.Nickname()); 1319d2d4866dSAndrew Lindesay bool hasUser = !nickname.IsEmpty(); 1320e0a26dceSStephan Aßmus 13216d519fd1SStephan Aßmus if (fLogOutItem != NULL) 1322e0a26dceSStephan Aßmus fLogOutItem->SetEnabled(hasUser); 1323d2d4866dSAndrew Lindesay if (fUsersUserUsageConditionsMenuItem != NULL) 1324d2d4866dSAndrew Lindesay fUsersUserUsageConditionsMenuItem->SetEnabled(hasUser); 1325e0a26dceSStephan Aßmus if (fLogInItem != NULL) { 1326e0a26dceSStephan Aßmus if (hasUser) 1327e0a26dceSStephan Aßmus fLogInItem->SetLabel(B_TRANSLATE("Switch account" B_UTF8_ELLIPSIS)); 1328e0a26dceSStephan Aßmus else 1329e0a26dceSStephan Aßmus fLogInItem->SetLabel(B_TRANSLATE("Log in" B_UTF8_ELLIPSIS)); 1330e0a26dceSStephan Aßmus } 1331e0a26dceSStephan Aßmus 1332e0a26dceSStephan Aßmus if (fUserMenu != NULL) { 1333e0a26dceSStephan Aßmus BString label; 1334d2d4866dSAndrew Lindesay if (hasUser) { 1335e0a26dceSStephan Aßmus label = B_TRANSLATE("Logged in as %User%"); 1336d2d4866dSAndrew Lindesay label.ReplaceAll("%User%", nickname); 1337d2d4866dSAndrew Lindesay } else { 1338d2d4866dSAndrew Lindesay label = B_TRANSLATE("Not logged in"); 1339e0a26dceSStephan Aßmus } 1340e0a26dceSStephan Aßmus fUserMenu->Superitem()->SetLabel(label); 1341e0a26dceSStephan Aßmus } 13428f03a0f9SStephan Aßmus } 13431bbda92dSStephan Aßmus 13441bbda92dSStephan Aßmus 13451bbda92dSStephan Aßmus void 1346b965ce70SHumdinger MainWindow::_UpdateAvailableRepositories() 1347b965ce70SHumdinger { 1348b965ce70SHumdinger fRepositoryMenu->RemoveItems(0, fRepositoryMenu->CountItems(), true); 1349b965ce70SHumdinger 1350b965ce70SHumdinger fRepositoryMenu->AddItem(new BMenuItem(B_TRANSLATE("All repositories"), 1351b965ce70SHumdinger new BMessage(MSG_DEPOT_SELECTED))); 1352b965ce70SHumdinger 1353b965ce70SHumdinger fRepositoryMenu->AddItem(new BSeparatorItem()); 1354b965ce70SHumdinger 1355b965ce70SHumdinger bool foundSelectedDepot = false; 135605880d13SAndrew Lindesay std::vector<DepotInfoRef> depots = _CreateSnapshotOfDepots(); 135705880d13SAndrew Lindesay std::vector<DepotInfoRef>::iterator it; 1358d13c3d89SAndrew Lindesay 135905880d13SAndrew Lindesay for (it = depots.begin(); it != depots.end(); it++) { 136005880d13SAndrew Lindesay DepotInfoRef depot = *it; 136105880d13SAndrew Lindesay 136205880d13SAndrew Lindesay if (depot->Name().Length() != 0) { 1363b965ce70SHumdinger BMessage* message = new BMessage(MSG_DEPOT_SELECTED); 136405880d13SAndrew Lindesay message->AddString("name", depot->Name()); 136505880d13SAndrew Lindesay BMenuItem* item = new(std::nothrow) BMenuItem(depot->Name(), message); 136605880d13SAndrew Lindesay 136705880d13SAndrew Lindesay if (item == NULL) 136805880d13SAndrew Lindesay HDFATAL("memory exhaustion"); 136905880d13SAndrew Lindesay 1370b965ce70SHumdinger fRepositoryMenu->AddItem(item); 1371b965ce70SHumdinger 1372*363fc60bSAndrew Lindesay if (depot->Name() == fModel.PackageFilter()->DepotName()) { 1373b965ce70SHumdinger item->SetMarked(true); 1374b965ce70SHumdinger foundSelectedDepot = true; 1375b965ce70SHumdinger } 1376b965ce70SHumdinger } 1377d13c3d89SAndrew Lindesay } 1378b965ce70SHumdinger 1379b965ce70SHumdinger if (!foundSelectedDepot) 1380b965ce70SHumdinger fRepositoryMenu->ItemAt(0)->SetMarked(true); 1381b965ce70SHumdinger } 1382b965ce70SHumdinger 1383b965ce70SHumdinger 1384a9edb9bfSAndrew Lindesay bool 1385a9edb9bfSAndrew Lindesay MainWindow::_SelectedPackageHasWebAppRepositoryCode() 1386a9edb9bfSAndrew Lindesay { 1387a9edb9bfSAndrew Lindesay const PackageInfoRef& package = fPackageInfoView->Package(); 13886ab878c0SAndrew Lindesay const BString depotName = package->DepotName(); 1389a9edb9bfSAndrew Lindesay 13906ab878c0SAndrew Lindesay if (depotName.IsEmpty()) { 1391fa5c8097SAndrew Lindesay HDDEBUG("the package [%s] has no depot name", package->Name().String()); 13926ab878c0SAndrew Lindesay } else { 13936ab878c0SAndrew Lindesay const DepotInfo* depot = fModel.DepotForName(depotName); 1394a9edb9bfSAndrew Lindesay 13956ab878c0SAndrew Lindesay if (depot == NULL) { 1396f96d1f4dSAndrew Lindesay HDINFO("the depot [%s] was not able to be found", 1397fa5c8097SAndrew Lindesay depotName.String()); 13986ab878c0SAndrew Lindesay } else { 13996ab878c0SAndrew Lindesay BString repositoryCode = depot->WebAppRepositoryCode(); 1400a9edb9bfSAndrew Lindesay 14016ab878c0SAndrew Lindesay if (repositoryCode.IsEmpty()) { 1402f96d1f4dSAndrew Lindesay HDINFO("the depot [%s] has no web app repository code", 1403fa5c8097SAndrew Lindesay depotName.String()); 1404fa5c8097SAndrew Lindesay } else 14056ab878c0SAndrew Lindesay return true; 14066ab878c0SAndrew Lindesay } 14076ab878c0SAndrew Lindesay } 14086ab878c0SAndrew Lindesay 14096ab878c0SAndrew Lindesay return false; 1410a9edb9bfSAndrew Lindesay } 1411a9edb9bfSAndrew Lindesay 1412a9edb9bfSAndrew Lindesay 1413b965ce70SHumdinger void 14141bbda92dSStephan Aßmus MainWindow::_RatePackage() 14151bbda92dSStephan Aßmus { 1416a9edb9bfSAndrew Lindesay if (!_SelectedPackageHasWebAppRepositoryCode()) { 1417a9edb9bfSAndrew Lindesay BAlert* alert = new(std::nothrow) BAlert( 1418cbadcae1SHumdinger B_TRANSLATE("Rating not possible"), 1419cbadcae1SHumdinger B_TRANSLATE("This package doesn't seem to be on the HaikuDepot " 1420cbadcae1SHumdinger "Server, so it's not possible to create a new rating " 1421cbadcae1SHumdinger "or edit an existing rating."), 1422a9edb9bfSAndrew Lindesay B_TRANSLATE("OK")); 1423a9edb9bfSAndrew Lindesay alert->Go(); 1424a9edb9bfSAndrew Lindesay return; 1425a9edb9bfSAndrew Lindesay } 1426a9edb9bfSAndrew Lindesay 1427d2d4866dSAndrew Lindesay if (fModel.Nickname().IsEmpty()) { 14281bbda92dSStephan Aßmus BAlert* alert = new(std::nothrow) BAlert( 14291bbda92dSStephan Aßmus B_TRANSLATE("Not logged in"), 14301bbda92dSStephan Aßmus B_TRANSLATE("You need to be logged into an account before you " 14311bbda92dSStephan Aßmus "can rate packages."), 14321bbda92dSStephan Aßmus B_TRANSLATE("Cancel"), 14331bbda92dSStephan Aßmus B_TRANSLATE("Login or Create account")); 14341bbda92dSStephan Aßmus 14351bbda92dSStephan Aßmus if (alert == NULL) 14361bbda92dSStephan Aßmus return; 14371bbda92dSStephan Aßmus 14381bbda92dSStephan Aßmus int32 choice = alert->Go(); 14391bbda92dSStephan Aßmus if (choice == 1) 14401bbda92dSStephan Aßmus _OpenLoginWindow(BMessage(MSG_RATE_PACKAGE)); 14411bbda92dSStephan Aßmus return; 14421bbda92dSStephan Aßmus } 14431bbda92dSStephan Aßmus 14441bbda92dSStephan Aßmus // TODO: Allow only one RatePackageWindow 14451bbda92dSStephan Aßmus // TODO: Mechanism for remembering the window frame 14461bbda92dSStephan Aßmus RatePackageWindow* window = new RatePackageWindow(this, 14471bbda92dSStephan Aßmus BRect(0, 0, 500, 400), fModel); 14481bbda92dSStephan Aßmus window->SetPackage(fPackageInfoView->Package()); 14491bbda92dSStephan Aßmus window->Show(); 14501bbda92dSStephan Aßmus } 1451d5ef985eSStephan Aßmus 1452d5ef985eSStephan Aßmus 1453d5ef985eSStephan Aßmus void 1454d5ef985eSStephan Aßmus MainWindow::_ShowScreenshot() 1455d5ef985eSStephan Aßmus { 1456d5ef985eSStephan Aßmus // TODO: Mechanism for remembering the window frame 1457d5ef985eSStephan Aßmus if (fScreenshotWindow == NULL) 145888af15cfSAndrew Lindesay fScreenshotWindow = new ScreenshotWindow(this, BRect(0, 0, 500, 400), &fModel); 1459d5ef985eSStephan Aßmus 1460d5ef985eSStephan Aßmus if (fScreenshotWindow->LockWithTimeout(1000) != B_OK) 1461d5ef985eSStephan Aßmus return; 1462d5ef985eSStephan Aßmus 1463d5ef985eSStephan Aßmus fScreenshotWindow->SetPackage(fPackageInfoView->Package()); 1464d5ef985eSStephan Aßmus 1465d5ef985eSStephan Aßmus if (fScreenshotWindow->IsHidden()) 1466d5ef985eSStephan Aßmus fScreenshotWindow->Show(); 1467d5ef985eSStephan Aßmus else 1468d5ef985eSStephan Aßmus fScreenshotWindow->Activate(); 1469d5ef985eSStephan Aßmus 1470d5ef985eSStephan Aßmus fScreenshotWindow->Unlock(); 1471d5ef985eSStephan Aßmus } 147201339a54SAndrew Lindesay 147301339a54SAndrew Lindesay 147401339a54SAndrew Lindesay void 1475d2d4866dSAndrew Lindesay MainWindow::_ViewUserUsageConditions( 1476d2d4866dSAndrew Lindesay UserUsageConditionsSelectionMode mode) 147701339a54SAndrew Lindesay { 147801339a54SAndrew Lindesay UserUsageConditionsWindow* window = new UserUsageConditionsWindow( 1479d2d4866dSAndrew Lindesay fModel, mode); 148001339a54SAndrew Lindesay window->Show(); 148101339a54SAndrew Lindesay } 148210cd325cSAndrew Lindesay 148310cd325cSAndrew Lindesay 148410cd325cSAndrew Lindesay void 148510cd325cSAndrew Lindesay MainWindow::UserCredentialsFailed() 148610cd325cSAndrew Lindesay { 148710cd325cSAndrew Lindesay BString message = B_TRANSLATE("The password previously " 148810cd325cSAndrew Lindesay "supplied for the user [%Nickname%] is not currently " 148910cd325cSAndrew Lindesay "valid. The user will be logged-out of this application " 149010cd325cSAndrew Lindesay "and you should login again with your updated password."); 149110cd325cSAndrew Lindesay message.ReplaceAll("%Nickname%", fModel.Nickname()); 149210cd325cSAndrew Lindesay 149310cd325cSAndrew Lindesay AppUtils::NotifySimpleError(B_TRANSLATE("Login issue"), 149410cd325cSAndrew Lindesay message); 149510cd325cSAndrew Lindesay 149610cd325cSAndrew Lindesay { 149710cd325cSAndrew Lindesay AutoLocker<BLocker> locker(fModel.Lock()); 149810cd325cSAndrew Lindesay fModel.SetNickname(""); 149910cd325cSAndrew Lindesay } 150010cd325cSAndrew Lindesay } 150110cd325cSAndrew Lindesay 150210cd325cSAndrew Lindesay 150310cd325cSAndrew Lindesay /*! \brief This method is invoked from the UserDetailVerifierProcess on a 150410cd325cSAndrew Lindesay background thread. For this reason it lodges a message into itself 150510cd325cSAndrew Lindesay which can then be handled on the main thread. 150610cd325cSAndrew Lindesay */ 150710cd325cSAndrew Lindesay 150810cd325cSAndrew Lindesay void 150910cd325cSAndrew Lindesay MainWindow::UserUsageConditionsNotLatest(const UserDetail& userDetail) 151010cd325cSAndrew Lindesay { 151110cd325cSAndrew Lindesay BMessage message(MSG_USER_USAGE_CONDITIONS_NOT_LATEST); 151210cd325cSAndrew Lindesay BMessage detailsMessage; 151310cd325cSAndrew Lindesay if (userDetail.Archive(&detailsMessage, true) != B_OK 151410cd325cSAndrew Lindesay || message.AddMessage("userDetail", &detailsMessage) != B_OK) { 1515fa5c8097SAndrew Lindesay HDERROR("unable to archive the user detail into a message"); 151610cd325cSAndrew Lindesay } 151710cd325cSAndrew Lindesay else 151810cd325cSAndrew Lindesay BMessenger(this).SendMessage(&message); 151910cd325cSAndrew Lindesay } 152010cd325cSAndrew Lindesay 152110cd325cSAndrew Lindesay 152210cd325cSAndrew Lindesay void 152310cd325cSAndrew Lindesay MainWindow::_HandleUserUsageConditionsNotLatest( 152410cd325cSAndrew Lindesay const UserDetail& userDetail) 152510cd325cSAndrew Lindesay { 152610cd325cSAndrew Lindesay ToLatestUserUsageConditionsWindow* window = 152710cd325cSAndrew Lindesay new ToLatestUserUsageConditionsWindow(this, fModel, userDetail); 152810cd325cSAndrew Lindesay window->Show(); 152910cd325cSAndrew Lindesay } 153010cd325cSAndrew Lindesay 153110cd325cSAndrew Lindesay 153210cd325cSAndrew Lindesay void 153310cd325cSAndrew Lindesay MainWindow::_AddProcessCoordinator(ProcessCoordinator* item) 153410cd325cSAndrew Lindesay { 153510cd325cSAndrew Lindesay AutoLocker<BLocker> lock(&fCoordinatorLock); 153610cd325cSAndrew Lindesay 153795c7b018SAndrew Lindesay if (fShouldCloseWhenNoProcessesToCoordinate) { 153895c7b018SAndrew Lindesay HDINFO("system shutting down --> new process coordinator [%s] rejected", 153995c7b018SAndrew Lindesay item->Name().String()); 154095c7b018SAndrew Lindesay return; 154195c7b018SAndrew Lindesay } 154295c7b018SAndrew Lindesay 1543a18f873fSAndrew Lindesay item->SetListener(this); 1544a18f873fSAndrew Lindesay 1545409af934SAndrew Lindesay if (fCoordinator == NULL) { 154610cd325cSAndrew Lindesay if (acquire_sem(fCoordinatorRunningSem) != B_OK) 154710cd325cSAndrew Lindesay debugger("unable to acquire the process coordinator sem"); 1548f96d1f4dSAndrew Lindesay HDINFO("adding and starting a process coordinator [%s]", 1549fa5c8097SAndrew Lindesay item->Name().String()); 1550409af934SAndrew Lindesay delete fCoordinator; 1551409af934SAndrew Lindesay fCoordinator = item; 155210cd325cSAndrew Lindesay fCoordinator->Start(); 15537d7de135SAugustin Cavalier } else { 1554f96d1f4dSAndrew Lindesay HDINFO("adding process coordinator [%s] to the queue", 155510cd325cSAndrew Lindesay item->Name().String()); 155610cd325cSAndrew Lindesay fCoordinatorQueue.push(item); 155710cd325cSAndrew Lindesay } 155810cd325cSAndrew Lindesay } 155910cd325cSAndrew Lindesay 156010cd325cSAndrew Lindesay 156110cd325cSAndrew Lindesay void 156210cd325cSAndrew Lindesay MainWindow::_SpinUntilProcessCoordinatorComplete() 156310cd325cSAndrew Lindesay { 156410cd325cSAndrew Lindesay while (true) { 156510cd325cSAndrew Lindesay if (acquire_sem(fCoordinatorRunningSem) != B_OK) 156610cd325cSAndrew Lindesay debugger("unable to acquire the process coordinator sem"); 156710cd325cSAndrew Lindesay if (release_sem(fCoordinatorRunningSem) != B_OK) 156810cd325cSAndrew Lindesay debugger("unable to release the process coordinator sem"); 156910cd325cSAndrew Lindesay { 157010cd325cSAndrew Lindesay AutoLocker<BLocker> lock(&fCoordinatorLock); 1571409af934SAndrew Lindesay if (fCoordinator == NULL) 157210cd325cSAndrew Lindesay return; 157310cd325cSAndrew Lindesay } 157410cd325cSAndrew Lindesay } 157510cd325cSAndrew Lindesay } 157610cd325cSAndrew Lindesay 157710cd325cSAndrew Lindesay 157810cd325cSAndrew Lindesay void 157910cd325cSAndrew Lindesay MainWindow::_StopProcessCoordinators() 158010cd325cSAndrew Lindesay { 158195c7b018SAndrew Lindesay HDINFO("will stop all queued process coordinators"); 158210cd325cSAndrew Lindesay AutoLocker<BLocker> lock(&fCoordinatorLock); 158310cd325cSAndrew Lindesay 158410cd325cSAndrew Lindesay while (!fCoordinatorQueue.empty()) { 1585409af934SAndrew Lindesay ProcessCoordinator* processCoordinator 1586f96d1f4dSAndrew Lindesay = fCoordinatorQueue.front(); 1587f96d1f4dSAndrew Lindesay HDINFO("will drop queued process coordinator [%s]", 1588fa5c8097SAndrew Lindesay processCoordinator->Name().String()); 158910cd325cSAndrew Lindesay fCoordinatorQueue.pop(); 1590409af934SAndrew Lindesay delete processCoordinator; 159110cd325cSAndrew Lindesay } 159210cd325cSAndrew Lindesay 1593409af934SAndrew Lindesay if (fCoordinator != NULL) 159495c7b018SAndrew Lindesay fCoordinator->RequestStop(); 159510cd325cSAndrew Lindesay } 159610cd325cSAndrew Lindesay 159710cd325cSAndrew Lindesay 159810cd325cSAndrew Lindesay /*! This method is called when there is some change in the bulk load process 159910cd325cSAndrew Lindesay or other process coordinator. 160010cd325cSAndrew Lindesay A change may mean that a new process has started / stopped etc... or it 160110cd325cSAndrew Lindesay may mean that the entire coordinator has finished. 160210cd325cSAndrew Lindesay */ 160310cd325cSAndrew Lindesay 160410cd325cSAndrew Lindesay void 160510cd325cSAndrew Lindesay MainWindow::CoordinatorChanged(ProcessCoordinatorState& coordinatorState) 160610cd325cSAndrew Lindesay { 1607409af934SAndrew Lindesay BMessage message(MSG_PROCESS_COORDINATOR_CHANGED); 1608409af934SAndrew Lindesay if (coordinatorState.Archive(&message, true) != B_OK) { 1609409af934SAndrew Lindesay HDFATAL("unable to archive message when the process coordinator" 1610409af934SAndrew Lindesay " has changed"); 1611409af934SAndrew Lindesay } 1612409af934SAndrew Lindesay BMessenger(this).SendMessage(&message); 1613409af934SAndrew Lindesay } 1614409af934SAndrew Lindesay 1615409af934SAndrew Lindesay 1616409af934SAndrew Lindesay void 1617409af934SAndrew Lindesay MainWindow::_HandleProcessCoordinatorChanged(ProcessCoordinatorState& coordinatorState) 1618409af934SAndrew Lindesay { 161910cd325cSAndrew Lindesay AutoLocker<BLocker> lock(&fCoordinatorLock); 162010cd325cSAndrew Lindesay 1621409af934SAndrew Lindesay if (fCoordinator->Identifier() 1622409af934SAndrew Lindesay == coordinatorState.ProcessCoordinatorIdentifier()) { 162310cd325cSAndrew Lindesay if (!coordinatorState.IsRunning()) { 162410cd325cSAndrew Lindesay if (release_sem(fCoordinatorRunningSem) != B_OK) 162510cd325cSAndrew Lindesay debugger("unable to release the process coordinator sem"); 1626f96d1f4dSAndrew Lindesay HDINFO("process coordinator [%s] did complete", 1627fa5c8097SAndrew Lindesay fCoordinator->Name().String()); 162810cd325cSAndrew Lindesay // complete the last one that just finished 162910cd325cSAndrew Lindesay BMessage* message = fCoordinator->Message(); 163010cd325cSAndrew Lindesay 163110cd325cSAndrew Lindesay if (message != NULL) { 163210cd325cSAndrew Lindesay BMessenger messenger(this); 163310cd325cSAndrew Lindesay message->AddInt64(KEY_ERROR_STATUS, 163410cd325cSAndrew Lindesay (int64) fCoordinator->ErrorStatus()); 163510cd325cSAndrew Lindesay messenger.SendMessage(message); 163610cd325cSAndrew Lindesay } 163710cd325cSAndrew Lindesay 16383538133fSAndrew Lindesay HDDEBUG("process coordinator report;\n---\n%s\n----", 16393538133fSAndrew Lindesay fCoordinator->LogReport().String()); 16403538133fSAndrew Lindesay 1641409af934SAndrew Lindesay delete fCoordinator; 1642409af934SAndrew Lindesay fCoordinator = NULL; 164310cd325cSAndrew Lindesay 164410cd325cSAndrew Lindesay // now schedule the next one. 164510cd325cSAndrew Lindesay if (!fCoordinatorQueue.empty()) { 164610cd325cSAndrew Lindesay if (acquire_sem(fCoordinatorRunningSem) != B_OK) 164710cd325cSAndrew Lindesay debugger("unable to acquire the process coordinator sem"); 164810cd325cSAndrew Lindesay fCoordinator = fCoordinatorQueue.front(); 1649f96d1f4dSAndrew Lindesay HDINFO("starting next process coordinator [%s]", 165010cd325cSAndrew Lindesay fCoordinator->Name().String()); 165110cd325cSAndrew Lindesay fCoordinatorQueue.pop(); 165210cd325cSAndrew Lindesay fCoordinator->Start(); 165310cd325cSAndrew Lindesay } 165410cd325cSAndrew Lindesay else { 165510cd325cSAndrew Lindesay _NotifyWorkStatusClear(); 165695c7b018SAndrew Lindesay if (fShouldCloseWhenNoProcessesToCoordinate) { 165795c7b018SAndrew Lindesay HDINFO("no more processes to coord --> will quit"); 165895c7b018SAndrew Lindesay BMessage message(B_QUIT_REQUESTED); 165995c7b018SAndrew Lindesay PostMessage(&message); 166095c7b018SAndrew Lindesay } 166110cd325cSAndrew Lindesay } 166210cd325cSAndrew Lindesay } 166310cd325cSAndrew Lindesay else { 166410cd325cSAndrew Lindesay _NotifyWorkStatusChange(coordinatorState.Message(), 166510cd325cSAndrew Lindesay coordinatorState.Progress()); 166610cd325cSAndrew Lindesay // show the progress to the user. 166710cd325cSAndrew Lindesay } 166895c7b018SAndrew Lindesay } else { 166995c7b018SAndrew Lindesay _NotifyWorkStatusClear(); 1670fa5c8097SAndrew Lindesay HDINFO("! unknown process coordinator changed"); 167110cd325cSAndrew Lindesay } 167295c7b018SAndrew Lindesay } 1673ccf707d0SAndrew Lindesay 1674ccf707d0SAndrew Lindesay 1675ccf707d0SAndrew Lindesay static package_list_view_mode 1676ccf707d0SAndrew Lindesay main_window_tab_to_package_list_view_mode(int32 tab) 1677ccf707d0SAndrew Lindesay { 1678ccf707d0SAndrew Lindesay if (tab == TAB_PROMINENT_PACKAGES) 1679ccf707d0SAndrew Lindesay return PROMINENT; 1680ccf707d0SAndrew Lindesay return ALL; 1681ccf707d0SAndrew Lindesay } 1682ccf707d0SAndrew Lindesay 1683ccf707d0SAndrew Lindesay 1684ccf707d0SAndrew Lindesay void 1685ccf707d0SAndrew Lindesay MainWindow::_HandleChangePackageListViewMode() 1686ccf707d0SAndrew Lindesay { 1687ccf707d0SAndrew Lindesay package_list_view_mode tabMode = main_window_tab_to_package_list_view_mode( 1688ccf707d0SAndrew Lindesay fListTabs->Selection()); 1689ccf707d0SAndrew Lindesay package_list_view_mode modelMode = fModel.PackageListViewMode(); 1690ccf707d0SAndrew Lindesay 1691ccf707d0SAndrew Lindesay if (tabMode != modelMode) { 1692ccf707d0SAndrew Lindesay BAutolock locker(fModel.Lock()); 1693ccf707d0SAndrew Lindesay fModel.SetPackageListViewMode(tabMode); 1694ccf707d0SAndrew Lindesay } 1695ccf707d0SAndrew Lindesay } 169605880d13SAndrew Lindesay 169705880d13SAndrew Lindesay 169805880d13SAndrew Lindesay std::vector<DepotInfoRef> 169905880d13SAndrew Lindesay MainWindow::_CreateSnapshotOfDepots() 170005880d13SAndrew Lindesay { 170105880d13SAndrew Lindesay std::vector<DepotInfoRef> result; 170205880d13SAndrew Lindesay BAutolock locker(fModel.Lock()); 170305880d13SAndrew Lindesay int32 countDepots = fModel.CountDepots(); 170405880d13SAndrew Lindesay for(int32 i = 0; i < countDepots; i++) 170505880d13SAndrew Lindesay result.push_back(fModel.DepotAtIndex(i)); 170605880d13SAndrew Lindesay return result; 170705880d13SAndrew Lindesay } 170888af15cfSAndrew Lindesay 170988af15cfSAndrew Lindesay 171088af15cfSAndrew Lindesay /*! This will get invoked in the case that a screenshot has been cached 171188af15cfSAndrew Lindesay and so could now be loaded by some UI element. This method will then 171288af15cfSAndrew Lindesay signal to other UI elements that they could load a screenshot should 171388af15cfSAndrew Lindesay they have been waiting for it. 171488af15cfSAndrew Lindesay */ 171588af15cfSAndrew Lindesay 171688af15cfSAndrew Lindesay void 171788af15cfSAndrew Lindesay MainWindow::_HandleScreenshotCached(const BMessage* message) 171888af15cfSAndrew Lindesay { 171988af15cfSAndrew Lindesay ScreenshotCoordinate coordinate(message); 172088af15cfSAndrew Lindesay fPackageInfoView->HandleScreenshotCached(coordinate); 172188af15cfSAndrew Lindesay } 1722