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. 6*88af15cfSAndrew 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', 74*88af15cfSAndrew 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 130*88af15cfSAndrew Lindesay virtual void ScreenshotCached(const ScreenshotCoordinate& coordinate) 131*88af15cfSAndrew Lindesay { 132*88af15cfSAndrew Lindesay if (fMessenger.IsValid()) { 133*88af15cfSAndrew Lindesay BMessage message(MSG_SCREENSHOT_CACHED); 134*88af15cfSAndrew Lindesay if (coordinate.Archive(&message) != B_OK) 135*88af15cfSAndrew Lindesay debugger("unable to serialize a screenshot coordinate"); 136*88af15cfSAndrew Lindesay fMessenger.SendMessage(&message); 137*88af15cfSAndrew Lindesay } 138*88af15cfSAndrew Lindesay } 139*88af15cfSAndrew 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 265afe7affbSAndrew Lindesay MainWindow::MainWindow(const BMessage& settings, PackageInfoRef& package) 2666d519fd1SStephan Aßmus : 267f7c2983eSAxel Dörfler BWindow(BRect(50, 50, 650, 350), B_TRANSLATE_SYSTEM_NAME("HaikuDepot"), 2686d519fd1SStephan Aßmus B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, 2696d519fd1SStephan Aßmus B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS), 2709883929bSAndrew Lindesay fFeaturedPackagesView(NULL), 2719883929bSAndrew Lindesay fPackageListView(NULL), 272d78bfd8dSJulian Harnath fWorkStatusView(NULL), 273d5ef985eSStephan Aßmus fScreenshotWindow(NULL), 27495c7b018SAndrew Lindesay fShuttingDownWindow(NULL), 275e0a26dceSStephan Aßmus fUserMenu(NULL), 276e0a26dceSStephan Aßmus fLogInItem(NULL), 2776d519fd1SStephan Aßmus fLogOutItem(NULL), 278976cadf1SAndrew Lindesay fUsersUserUsageConditionsMenuItem(NULL), 27989b16bb4SAndrew Lindesay fModelListener(new MainWindowModelListener(BMessenger(this)), true), 28010cd325cSAndrew Lindesay fCoordinator(NULL), 28195c7b018SAndrew Lindesay fShouldCloseWhenNoProcessesToCoordinate(false), 28284674570SAndrew Lindesay fSinglePackageMode(true), 28384674570SAndrew Lindesay fIncrementViewCounterDelayedRunner(NULL) 2846d519fd1SStephan Aßmus { 28510cd325cSAndrew Lindesay if ((fCoordinatorRunningSem = create_sem(1, "ProcessCoordinatorSem")) < B_OK) 28610cd325cSAndrew Lindesay debugger("unable to create the process coordinator semaphore"); 28710cd325cSAndrew Lindesay 288409af934SAndrew Lindesay fPackageInfoListener = PackageInfoListenerRef( 289409af934SAndrew Lindesay new MainWindowPackageInfoListener(this), true); 290409af934SAndrew Lindesay 2916d519fd1SStephan Aßmus fFilterView = new FilterView(); 292f0e491d3SAndrew Lindesay fPackageInfoView = new PackageInfoView(&fModel, this); 29387016f8fSAndrew Lindesay fWorkStatusView = new WorkStatusView("work status"); 2946d519fd1SStephan Aßmus 2956d519fd1SStephan Aßmus BLayoutBuilder::Group<>(this, B_VERTICAL) 2966d519fd1SStephan Aßmus .Add(fPackageInfoView) 29787016f8fSAndrew Lindesay .Add(fWorkStatusView) 2986d519fd1SStephan Aßmus .SetInsets(0, B_USE_WINDOW_INSETS, 0, 0) 2996d519fd1SStephan Aßmus ; 3006d519fd1SStephan Aßmus 3016d519fd1SStephan Aßmus fModel.AddListener(fModelListener); 3026d519fd1SStephan Aßmus 303afe7affbSAndrew Lindesay // add the single package into the model so that any internal 304afe7affbSAndrew Lindesay // business logic is able to find the package. 305afe7affbSAndrew Lindesay DepotInfoRef depot(new DepotInfo("single-pkg-depot"), true); 306afe7affbSAndrew Lindesay depot->AddPackage(package); 307afe7affbSAndrew Lindesay fModel.MergeOrAddDepot(depot); 308afe7affbSAndrew Lindesay 3096d519fd1SStephan Aßmus // Restore settings 310d2d4866dSAndrew Lindesay _RestoreNickname(settings); 311ccf707d0SAndrew Lindesay _UpdateAuthorization(); 312f7c2983eSAxel Dörfler _RestoreWindowFrame(settings); 3136d519fd1SStephan Aßmus 3146d519fd1SStephan Aßmus fPackageInfoView->SetPackage(package); 31563975654SStephan Aßmus 316afe7affbSAndrew Lindesay // start worker threads 317afe7affbSAndrew Lindesay BPackageRoster().StartWatching(this, 318afe7affbSAndrew Lindesay B_WATCH_PACKAGE_INSTALLATION_LOCATIONS); 319afe7affbSAndrew Lindesay 32063975654SStephan Aßmus _InitWorkerThreads(); 3216d519fd1SStephan Aßmus } 3226d519fd1SStephan Aßmus 3236d519fd1SStephan Aßmus 32404c9d578SStephan Aßmus MainWindow::~MainWindow() 32504c9d578SStephan Aßmus { 32610cd325cSAndrew Lindesay _SpinUntilProcessCoordinatorComplete(); 32710cd325cSAndrew Lindesay delete_sem(fCoordinatorRunningSem); 32810cd325cSAndrew Lindesay fCoordinatorRunningSem = 0; 32910cd325cSAndrew Lindesay 33004c9d578SStephan Aßmus BPackageRoster().StopWatching(this); 33104c9d578SStephan Aßmus 33295c7b018SAndrew Lindesay if (fScreenshotWindow != NULL) { 33395c7b018SAndrew Lindesay if (fScreenshotWindow->Lock()) 334d5ef985eSStephan Aßmus fScreenshotWindow->Quit(); 33504c9d578SStephan Aßmus } 33604c9d578SStephan Aßmus 33795c7b018SAndrew Lindesay if (fShuttingDownWindow != NULL) { 33895c7b018SAndrew Lindesay if (fShuttingDownWindow->Lock()) 33995c7b018SAndrew Lindesay fShuttingDownWindow->Quit(); 34095c7b018SAndrew Lindesay } 341d5562247SAugustin Cavalier 342a3866854SAugustin Cavalier delete_sem(fPackageToPopulateSem); 343a3866854SAugustin Cavalier wait_for_thread(fPopulatePackageWorker, NULL); 344a3866854SAugustin Cavalier 3454329a83fSAugustin Cavalier // We must clear the model early to release references. 346d5562247SAugustin Cavalier fModel.Clear(); 34795c7b018SAndrew Lindesay } 34895c7b018SAndrew Lindesay 34904c9d578SStephan Aßmus 35004c9d578SStephan Aßmus bool 35104c9d578SStephan Aßmus MainWindow::QuitRequested() 35204c9d578SStephan Aßmus { 35304c9d578SStephan Aßmus 35410cd325cSAndrew Lindesay _StopProcessCoordinators(); 3553369e03dSAndrew Lindesay 35695c7b018SAndrew Lindesay // If there are any processes in flight we need to be careful to make 35795c7b018SAndrew Lindesay // sure that they are cleanly completed before actually quitting. By 35895c7b018SAndrew Lindesay // turning on the `fShouldCloseWhenNoProcessesToCoordinate` flag, when 35995c7b018SAndrew Lindesay // the process coordination has completed then it will detect this and 36095c7b018SAndrew Lindesay // quit again. 36195c7b018SAndrew Lindesay 36295c7b018SAndrew Lindesay { 36395c7b018SAndrew Lindesay AutoLocker<BLocker> lock(&fCoordinatorLock); 36495c7b018SAndrew Lindesay fShouldCloseWhenNoProcessesToCoordinate = true; 36595c7b018SAndrew Lindesay 366409af934SAndrew Lindesay if (fCoordinator != NULL) { 36795c7b018SAndrew Lindesay HDINFO("a coordinator is running --> will wait before quitting..."); 36895c7b018SAndrew Lindesay 36995c7b018SAndrew Lindesay if (fShuttingDownWindow == NULL) 37095c7b018SAndrew Lindesay fShuttingDownWindow = new ShuttingDownWindow(this); 37195c7b018SAndrew Lindesay fShuttingDownWindow->Show(); 37295c7b018SAndrew Lindesay 37395c7b018SAndrew Lindesay return false; 37495c7b018SAndrew Lindesay } 37595c7b018SAndrew Lindesay } 37695c7b018SAndrew Lindesay 37795c7b018SAndrew Lindesay BMessage settings; 37895c7b018SAndrew Lindesay StoreSettings(settings); 37995c7b018SAndrew Lindesay BMessage message(MSG_MAIN_WINDOW_CLOSED); 38095c7b018SAndrew Lindesay message.AddMessage(KEY_WINDOW_SETTINGS, &settings); 38195c7b018SAndrew Lindesay be_app->PostMessage(&message); 38295c7b018SAndrew Lindesay 38395c7b018SAndrew Lindesay if (fShuttingDownWindow != NULL) { 38495c7b018SAndrew Lindesay if (fShuttingDownWindow->Lock()) 38595c7b018SAndrew Lindesay fShuttingDownWindow->Quit(); 38695c7b018SAndrew Lindesay fShuttingDownWindow = NULL; 38795c7b018SAndrew Lindesay } 38895c7b018SAndrew Lindesay 38904c9d578SStephan Aßmus return true; 39004c9d578SStephan Aßmus } 39104c9d578SStephan Aßmus 39204c9d578SStephan Aßmus 39304c9d578SStephan Aßmus void 39404c9d578SStephan Aßmus MainWindow::MessageReceived(BMessage* message) 39504c9d578SStephan Aßmus { 39604c9d578SStephan Aßmus switch (message->what) { 3973369e03dSAndrew Lindesay case MSG_BULK_LOAD_DONE: 39810cd325cSAndrew Lindesay { 39910cd325cSAndrew Lindesay int64 errorStatus64; 40010cd325cSAndrew Lindesay if (message->FindInt64(KEY_ERROR_STATUS, &errorStatus64) == B_OK) 40110cd325cSAndrew Lindesay _BulkLoadCompleteReceived((status_t) errorStatus64); 40210cd325cSAndrew Lindesay else 403fa5c8097SAndrew Lindesay HDERROR("expected [%s] value in message", KEY_ERROR_STATUS); 40404c9d578SStephan Aßmus break; 40510cd325cSAndrew Lindesay } 40604c9d578SStephan Aßmus case B_SIMPLE_DATA: 40704c9d578SStephan Aßmus case B_REFS_RECEIVED: 40804c9d578SStephan Aßmus // TODO: ? 40904c9d578SStephan Aßmus break; 41004c9d578SStephan Aßmus 41104c9d578SStephan Aßmus case B_PACKAGE_UPDATE: 412f32d5c5cSAndrew Lindesay _HandleExternalPackageUpdateMessageReceived(message); 41304c9d578SStephan Aßmus break; 41404c9d578SStephan Aßmus 4155bf2b6ebSBrian Hill case MSG_REFRESH_REPOS: 4163369e03dSAndrew Lindesay _StartBulkLoad(true); 4173369e03dSAndrew Lindesay break; 4183369e03dSAndrew Lindesay 41910cd325cSAndrew Lindesay case MSG_WORK_STATUS_CLEAR: 42010cd325cSAndrew Lindesay _HandleWorkStatusClear(); 42110cd325cSAndrew Lindesay break; 42210cd325cSAndrew Lindesay 4233369e03dSAndrew Lindesay case MSG_WORK_STATUS_CHANGE: 4243369e03dSAndrew Lindesay _HandleWorkStatusChangeMessageReceived(message); 42504c9d578SStephan Aßmus break; 42604c9d578SStephan Aßmus 4275bf2b6ebSBrian Hill case MSG_MANAGE_REPOS: 4285bf2b6ebSBrian Hill be_roster->Launch("application/x-vnd.Haiku-Repositories"); 4295bf2b6ebSBrian Hill break; 4305bf2b6ebSBrian Hill 431d144f952SAugustin Cavalier case MSG_SOFTWARE_UPDATER: 432d144f952SAugustin Cavalier be_roster->Launch("application/x-vnd.haiku-softwareupdater"); 433d144f952SAugustin Cavalier break; 434d144f952SAugustin Cavalier 43504c9d578SStephan Aßmus case MSG_LOG_IN: 4361bbda92dSStephan Aßmus _OpenLoginWindow(BMessage()); 43704c9d578SStephan Aßmus break; 43804c9d578SStephan Aßmus 439133ebab6SAndrew Lindesay case MSG_SETTINGS: 440133ebab6SAndrew Lindesay _OpenSettingsWindow(); 441133ebab6SAndrew Lindesay break; 442133ebab6SAndrew Lindesay 4438f03a0f9SStephan Aßmus case MSG_LOG_OUT: 444d2d4866dSAndrew Lindesay fModel.SetNickname(""); 4458f03a0f9SStephan Aßmus break; 4468f03a0f9SStephan Aßmus 44701339a54SAndrew Lindesay case MSG_VIEW_LATEST_USER_USAGE_CONDITIONS: 448d2d4866dSAndrew Lindesay _ViewUserUsageConditions(LATEST); 449d2d4866dSAndrew Lindesay break; 450d2d4866dSAndrew Lindesay 451d2d4866dSAndrew Lindesay case MSG_VIEW_USERS_USER_USAGE_CONDITIONS: 452d2d4866dSAndrew Lindesay _ViewUserUsageConditions(USER); 45301339a54SAndrew Lindesay break; 45401339a54SAndrew Lindesay 4558f03a0f9SStephan Aßmus case MSG_AUTHORIZATION_CHANGED: 45610cd325cSAndrew Lindesay _StartUserVerify(); 4578f03a0f9SStephan Aßmus _UpdateAuthorization(); 4588f03a0f9SStephan Aßmus break; 4598f03a0f9SStephan Aßmus 460*88af15cfSAndrew Lindesay case MSG_SCREENSHOT_CACHED: 461*88af15cfSAndrew Lindesay _HandleScreenshotCached(message); 462*88af15cfSAndrew Lindesay break; 463*88af15cfSAndrew Lindesay 46489b16bb4SAndrew Lindesay case MSG_CATEGORIES_LIST_CHANGED: 46589b16bb4SAndrew Lindesay fFilterView->AdoptModel(fModel); 46689b16bb4SAndrew Lindesay break; 46789b16bb4SAndrew Lindesay 468ccf707d0SAndrew Lindesay case MSG_CHANGE_PACKAGE_LIST_VIEW_MODE: 469ccf707d0SAndrew Lindesay _HandleChangePackageListViewMode(); 4704fade61fSStephan Aßmus break; 4714fade61fSStephan Aßmus 472fdec4227SStephan Aßmus case MSG_SHOW_AVAILABLE_PACKAGES: 473fdec4227SStephan Aßmus { 474fdec4227SStephan Aßmus BAutolock locker(fModel.Lock()); 475fdec4227SStephan Aßmus fModel.SetShowAvailablePackages( 476fdec4227SStephan Aßmus !fModel.ShowAvailablePackages()); 477fdec4227SStephan Aßmus } 478fdec4227SStephan Aßmus _AdoptModel(); 479fdec4227SStephan Aßmus break; 480fdec4227SStephan Aßmus 481fdec4227SStephan Aßmus case MSG_SHOW_INSTALLED_PACKAGES: 482fdec4227SStephan Aßmus { 483fdec4227SStephan Aßmus BAutolock locker(fModel.Lock()); 484fdec4227SStephan Aßmus fModel.SetShowInstalledPackages( 485fdec4227SStephan Aßmus !fModel.ShowInstalledPackages()); 486fdec4227SStephan Aßmus } 487fdec4227SStephan Aßmus _AdoptModel(); 488fdec4227SStephan Aßmus break; 489fdec4227SStephan Aßmus 49004c9d578SStephan Aßmus case MSG_SHOW_SOURCE_PACKAGES: 49104c9d578SStephan Aßmus { 49204c9d578SStephan Aßmus BAutolock locker(fModel.Lock()); 49304c9d578SStephan Aßmus fModel.SetShowSourcePackages(!fModel.ShowSourcePackages()); 49404c9d578SStephan Aßmus } 49504c9d578SStephan Aßmus _AdoptModel(); 49604c9d578SStephan Aßmus break; 49704c9d578SStephan Aßmus 49804c9d578SStephan Aßmus case MSG_SHOW_DEVELOP_PACKAGES: 49904c9d578SStephan Aßmus { 50004c9d578SStephan Aßmus BAutolock locker(fModel.Lock()); 50104c9d578SStephan Aßmus fModel.SetShowDevelopPackages(!fModel.ShowDevelopPackages()); 50204c9d578SStephan Aßmus } 50304c9d578SStephan Aßmus _AdoptModel(); 50404c9d578SStephan Aßmus break; 50504c9d578SStephan Aßmus 506a9edb9bfSAndrew Lindesay // this may be triggered by, for example, a user rating being added 507a9edb9bfSAndrew Lindesay // or having been altered. 508a9edb9bfSAndrew Lindesay case MSG_SERVER_DATA_CHANGED: 509a9edb9bfSAndrew Lindesay { 510a9edb9bfSAndrew Lindesay BString name; 511a9edb9bfSAndrew Lindesay if (message->FindString("name", &name) == B_OK) { 512a9edb9bfSAndrew Lindesay BAutolock locker(fModel.Lock()); 513a9edb9bfSAndrew Lindesay if (fPackageInfoView->Package()->Name() == name) { 514a9edb9bfSAndrew Lindesay _PopulatePackageAsync(true); 515a9edb9bfSAndrew Lindesay } else { 516f96d1f4dSAndrew Lindesay HDDEBUG("pkg [%s] is updated on the server, but is " 517f96d1f4dSAndrew Lindesay "not selected so will not be updated.", 518fa5c8097SAndrew Lindesay name.String()); 519a9edb9bfSAndrew Lindesay } 520a9edb9bfSAndrew Lindesay } 521a9edb9bfSAndrew Lindesay break; 522a9edb9bfSAndrew Lindesay } 523a9edb9bfSAndrew Lindesay 52484674570SAndrew Lindesay case MSG_INCREMENT_VIEW_COUNTER: 52584674570SAndrew Lindesay _HandleIncrementViewCounter(message); 52684674570SAndrew Lindesay break; 52784674570SAndrew Lindesay 52804c9d578SStephan Aßmus case MSG_PACKAGE_SELECTED: 52904c9d578SStephan Aßmus { 53072992391SStephan Aßmus BString name; 53172992391SStephan Aßmus if (message->FindString("name", &name) == B_OK) { 532c4199192SAndrew Lindesay PackageInfoRef package; 533c4199192SAndrew Lindesay { 53475ba9dbfSStephan Aßmus BAutolock locker(fModel.Lock()); 535c4199192SAndrew Lindesay package = fModel.PackageForName(name); 536c4199192SAndrew Lindesay } 5376f07feadSAndrew Lindesay if (!package.IsSet() || name != package->Name()) 538c4199192SAndrew Lindesay debugger("unable to find the named package"); 539133ebab6SAndrew Lindesay else { 54004c9d578SStephan Aßmus _AdoptPackage(package); 54184674570SAndrew Lindesay _SetupDelayedIncrementViewCounter(package); 542133ebab6SAndrew Lindesay } 54304c9d578SStephan Aßmus } else { 54404c9d578SStephan Aßmus _ClearPackage(); 54504c9d578SStephan Aßmus } 54604c9d578SStephan Aßmus break; 54704c9d578SStephan Aßmus } 54804c9d578SStephan Aßmus 54904c9d578SStephan Aßmus case MSG_CATEGORY_SELECTED: 55004c9d578SStephan Aßmus { 55189b16bb4SAndrew Lindesay BString code; 55289b16bb4SAndrew Lindesay if (message->FindString("code", &code) != B_OK) 55389b16bb4SAndrew Lindesay code = ""; 55404c9d578SStephan Aßmus { 55504c9d578SStephan Aßmus BAutolock locker(fModel.Lock()); 55689b16bb4SAndrew Lindesay fModel.SetCategory(code); 55704c9d578SStephan Aßmus } 55804c9d578SStephan Aßmus _AdoptModel(); 55904c9d578SStephan Aßmus break; 56004c9d578SStephan Aßmus } 56104c9d578SStephan Aßmus 56204c9d578SStephan Aßmus case MSG_DEPOT_SELECTED: 56304c9d578SStephan Aßmus { 56404c9d578SStephan Aßmus BString name; 56504c9d578SStephan Aßmus if (message->FindString("name", &name) != B_OK) 56604c9d578SStephan Aßmus name = ""; 56704c9d578SStephan Aßmus { 56804c9d578SStephan Aßmus BAutolock locker(fModel.Lock()); 56904c9d578SStephan Aßmus fModel.SetDepot(name); 57004c9d578SStephan Aßmus } 57104c9d578SStephan Aßmus _AdoptModel(); 572b965ce70SHumdinger _UpdateAvailableRepositories(); 57304c9d578SStephan Aßmus break; 57404c9d578SStephan Aßmus } 57504c9d578SStephan Aßmus 57604c9d578SStephan Aßmus case MSG_SEARCH_TERMS_MODIFIED: 57704c9d578SStephan Aßmus { 57804c9d578SStephan Aßmus // TODO: Do this with a delay! 57904c9d578SStephan Aßmus BString searchTerms; 58004c9d578SStephan Aßmus if (message->FindString("search terms", &searchTerms) != B_OK) 58104c9d578SStephan Aßmus searchTerms = ""; 58204c9d578SStephan Aßmus { 58304c9d578SStephan Aßmus BAutolock locker(fModel.Lock()); 58404c9d578SStephan Aßmus fModel.SetSearchTerms(searchTerms); 58504c9d578SStephan Aßmus } 58604c9d578SStephan Aßmus _AdoptModel(); 58704c9d578SStephan Aßmus break; 58804c9d578SStephan Aßmus } 58904c9d578SStephan Aßmus 590da651104SStephan Aßmus case MSG_PACKAGE_CHANGED: 59104c9d578SStephan Aßmus { 59204c9d578SStephan Aßmus PackageInfo* info; 59304c9d578SStephan Aßmus if (message->FindPointer("package", (void**)&info) == B_OK) { 59404c9d578SStephan Aßmus PackageInfoRef ref(info, true); 5950b69420bSAndrew Lindesay fFeaturedPackagesView->BeginAddRemove(); 596c4199192SAndrew Lindesay _AddRemovePackageFromLists(ref); 5970b69420bSAndrew Lindesay fFeaturedPackagesView->EndAddRemove(); 59810cd325cSAndrew Lindesay } 59904c9d578SStephan Aßmus break; 60004c9d578SStephan Aßmus } 60104c9d578SStephan Aßmus 602409af934SAndrew Lindesay case MSG_PROCESS_COORDINATOR_CHANGED: 603409af934SAndrew Lindesay { 604409af934SAndrew Lindesay ProcessCoordinatorState state(message); 605409af934SAndrew Lindesay _HandleProcessCoordinatorChanged(state); 606409af934SAndrew Lindesay break; 607409af934SAndrew Lindesay } 608409af934SAndrew Lindesay 60904c9d578SStephan Aßmus case MSG_RATE_PACKAGE: 6101bbda92dSStephan Aßmus _RatePackage(); 61104c9d578SStephan Aßmus break; 61204c9d578SStephan Aßmus 613d5ef985eSStephan Aßmus case MSG_SHOW_SCREENSHOT: 614d5ef985eSStephan Aßmus _ShowScreenshot(); 615d5ef985eSStephan Aßmus break; 616d5ef985eSStephan Aßmus 617125d42d9SJulian Harnath case MSG_PACKAGE_WORKER_BUSY: 618125d42d9SJulian Harnath { 619125d42d9SJulian Harnath BString reason; 620125d42d9SJulian Harnath status_t status = message->FindString("reason", &reason); 621125d42d9SJulian Harnath if (status != B_OK) 622125d42d9SJulian Harnath break; 623125d42d9SJulian Harnath fWorkStatusView->SetBusy(reason); 624125d42d9SJulian Harnath break; 625125d42d9SJulian Harnath } 626125d42d9SJulian Harnath 627125d42d9SJulian Harnath case MSG_PACKAGE_WORKER_IDLE: 628125d42d9SJulian Harnath fWorkStatusView->SetIdle(); 629125d42d9SJulian Harnath break; 630125d42d9SJulian Harnath 63110cd325cSAndrew Lindesay case MSG_USER_USAGE_CONDITIONS_NOT_LATEST: 63210cd325cSAndrew Lindesay { 63310cd325cSAndrew Lindesay BMessage userDetailMsg; 63410cd325cSAndrew Lindesay if (message->FindMessage("userDetail", &userDetailMsg) != B_OK) { 63510cd325cSAndrew Lindesay debugger("expected the [userDetail] data to be carried in the " 63610cd325cSAndrew Lindesay "message."); 63710cd325cSAndrew Lindesay } 63810cd325cSAndrew Lindesay UserDetail userDetail(&userDetailMsg); 63910cd325cSAndrew Lindesay _HandleUserUsageConditionsNotLatest(userDetail); 64010cd325cSAndrew Lindesay break; 64110cd325cSAndrew Lindesay } 64210cd325cSAndrew Lindesay 64304c9d578SStephan Aßmus default: 64404c9d578SStephan Aßmus BWindow::MessageReceived(message); 64504c9d578SStephan Aßmus break; 64604c9d578SStephan Aßmus } 64704c9d578SStephan Aßmus } 64804c9d578SStephan Aßmus 64904c9d578SStephan Aßmus 650ccf707d0SAndrew Lindesay static const char* 651ccf707d0SAndrew Lindesay main_window_package_list_view_mode_str(package_list_view_mode mode) 652ccf707d0SAndrew Lindesay { 653ccf707d0SAndrew Lindesay if (mode == PROMINENT) 654ccf707d0SAndrew Lindesay return "PROMINENT"; 655ccf707d0SAndrew Lindesay return "ALL"; 656ccf707d0SAndrew Lindesay } 657ccf707d0SAndrew Lindesay 658ccf707d0SAndrew Lindesay 659ccf707d0SAndrew Lindesay static package_list_view_mode 660ccf707d0SAndrew Lindesay main_window_str_to_package_list_view_mode(const BString& str) 661ccf707d0SAndrew Lindesay { 662ccf707d0SAndrew Lindesay if (str == "PROMINENT") 663ccf707d0SAndrew Lindesay return PROMINENT; 664ccf707d0SAndrew Lindesay return ALL; 665ccf707d0SAndrew Lindesay } 666ccf707d0SAndrew Lindesay 667ccf707d0SAndrew Lindesay 66804c9d578SStephan Aßmus void 6694b347fccSAndrew Lindesay MainWindow::StoreSettings(BMessage& settings) 67004c9d578SStephan Aßmus { 671f7c2983eSAxel Dörfler settings.AddRect(_WindowFrameName(), Frame()); 672f7c2983eSAxel Dörfler if (!fSinglePackageMode) { 67304c9d578SStephan Aßmus settings.AddRect("window frame", Frame()); 67404c9d578SStephan Aßmus 67504c9d578SStephan Aßmus BMessage columnSettings; 6769883929bSAndrew Lindesay if (fPackageListView != NULL) 67704c9d578SStephan Aßmus fPackageListView->SaveState(&columnSettings); 67804c9d578SStephan Aßmus 67904c9d578SStephan Aßmus settings.AddMessage("column settings", &columnSettings); 68004c9d578SStephan Aßmus 681133ebab6SAndrew Lindesay settings.AddString(SETTING_PACKAGE_LIST_VIEW_MODE, 682ccf707d0SAndrew Lindesay main_window_package_list_view_mode_str( 683ccf707d0SAndrew Lindesay fModel.PackageListViewMode())); 684133ebab6SAndrew Lindesay settings.AddBool(SETTING_SHOW_AVAILABLE_PACKAGES, 6852997e05bSStephan Aßmus fModel.ShowAvailablePackages()); 686133ebab6SAndrew Lindesay settings.AddBool(SETTING_SHOW_INSTALLED_PACKAGES, 6872997e05bSStephan Aßmus fModel.ShowInstalledPackages()); 688133ebab6SAndrew Lindesay settings.AddBool(SETTING_SHOW_DEVELOP_PACKAGES, 689133ebab6SAndrew Lindesay fModel.ShowDevelopPackages()); 690133ebab6SAndrew Lindesay settings.AddBool(SETTING_SHOW_SOURCE_PACKAGES, 691133ebab6SAndrew Lindesay fModel.ShowSourcePackages()); 692133ebab6SAndrew Lindesay settings.AddBool(SETTING_CAN_SHARE_ANONYMOUS_USER_DATA, 693133ebab6SAndrew Lindesay fModel.CanShareAnonymousUsageData()); 6946d519fd1SStephan Aßmus } 6958f03a0f9SStephan Aßmus 696d2d4866dSAndrew Lindesay settings.AddString("username", fModel.Nickname()); 69704c9d578SStephan Aßmus } 69804c9d578SStephan Aßmus 69904c9d578SStephan Aßmus 70004c9d578SStephan Aßmus void 701a18f873fSAndrew Lindesay MainWindow::Consume(ProcessCoordinator *item) 702a18f873fSAndrew Lindesay { 703a18f873fSAndrew Lindesay _AddProcessCoordinator(item); 704a18f873fSAndrew Lindesay } 705a18f873fSAndrew Lindesay 706a18f873fSAndrew Lindesay 707a18f873fSAndrew Lindesay void 70804c9d578SStephan Aßmus MainWindow::PackageChanged(const PackageInfoEvent& event) 70904c9d578SStephan Aßmus { 710a9edb9bfSAndrew Lindesay uint32 watchedChanges = PKG_CHANGED_STATE | PKG_CHANGED_PROMINENCE; 711a9edb9bfSAndrew Lindesay if ((event.Changes() & watchedChanges) != 0) { 71204c9d578SStephan Aßmus PackageInfoRef ref(event.Package()); 713da651104SStephan Aßmus BMessage message(MSG_PACKAGE_CHANGED); 71404c9d578SStephan Aßmus message.AddPointer("package", ref.Get()); 71504c9d578SStephan Aßmus ref.Detach(); 71604c9d578SStephan Aßmus // reference needs to be released by MessageReceived(); 71704c9d578SStephan Aßmus PostMessage(&message); 71804c9d578SStephan Aßmus } 71904c9d578SStephan Aßmus } 72004c9d578SStephan Aßmus 72104c9d578SStephan Aßmus 72204c9d578SStephan Aßmus void 72304c9d578SStephan Aßmus MainWindow::_BuildMenu(BMenuBar* menuBar) 72404c9d578SStephan Aßmus { 7250b6928f1SHumdinger BMenu* menu = new BMenu(B_TRANSLATE_SYSTEM_NAME("HaikuDepot")); 7263369e03dSAndrew Lindesay fRefreshRepositoriesItem = new BMenuItem( 7273369e03dSAndrew Lindesay B_TRANSLATE("Refresh repositories"), new BMessage(MSG_REFRESH_REPOS)); 7283369e03dSAndrew Lindesay menu->AddItem(fRefreshRepositoriesItem); 729d7f78130SHumdinger menu->AddItem(new BMenuItem(B_TRANSLATE("Manage repositories" 730d7f78130SHumdinger B_UTF8_ELLIPSIS), new BMessage(MSG_MANAGE_REPOS))); 731d144f952SAugustin Cavalier menu->AddItem(new BMenuItem(B_TRANSLATE("Check for updates" 732d144f952SAugustin Cavalier B_UTF8_ELLIPSIS), new BMessage(MSG_SOFTWARE_UPDATER))); 7330b6928f1SHumdinger menu->AddSeparatorItem(); 7340b6928f1SHumdinger menu->AddItem(new BMenuItem(B_TRANSLATE("Settings" B_UTF8_ELLIPSIS), 735e1ae57abSJoachim Mairböck new BMessage(MSG_SETTINGS), ',')); 7360b6928f1SHumdinger menu->AddItem(new BMenuItem(B_TRANSLATE("Quit"), 7370b6928f1SHumdinger new BMessage(B_QUIT_REQUESTED), 'Q')); 73804c9d578SStephan Aßmus menuBar->AddItem(menu); 73904c9d578SStephan Aßmus 740b965ce70SHumdinger fRepositoryMenu = new BMenu(B_TRANSLATE("Repositories")); 741b965ce70SHumdinger menuBar->AddItem(fRepositoryMenu); 742b965ce70SHumdinger 7434fade61fSStephan Aßmus menu = new BMenu(B_TRANSLATE("Show")); 7444fade61fSStephan Aßmus 745fdec4227SStephan Aßmus fShowAvailablePackagesItem = new BMenuItem( 7464fade61fSStephan Aßmus B_TRANSLATE("Available packages"), 747fdec4227SStephan Aßmus new BMessage(MSG_SHOW_AVAILABLE_PACKAGES)); 748fdec4227SStephan Aßmus menu->AddItem(fShowAvailablePackagesItem); 749fdec4227SStephan Aßmus 750fdec4227SStephan Aßmus fShowInstalledPackagesItem = new BMenuItem( 7514fade61fSStephan Aßmus B_TRANSLATE("Installed packages"), 752fdec4227SStephan Aßmus new BMessage(MSG_SHOW_INSTALLED_PACKAGES)); 753fdec4227SStephan Aßmus menu->AddItem(fShowInstalledPackagesItem); 754fdec4227SStephan Aßmus 755fdec4227SStephan Aßmus menu->AddSeparatorItem(); 756fdec4227SStephan Aßmus 757fdec4227SStephan Aßmus fShowDevelopPackagesItem = new BMenuItem( 7584fade61fSStephan Aßmus B_TRANSLATE("Develop packages"), 759fdec4227SStephan Aßmus new BMessage(MSG_SHOW_DEVELOP_PACKAGES)); 760fdec4227SStephan Aßmus menu->AddItem(fShowDevelopPackagesItem); 761fdec4227SStephan Aßmus 762fdec4227SStephan Aßmus fShowSourcePackagesItem = new BMenuItem( 7634fade61fSStephan Aßmus B_TRANSLATE("Source packages"), 764fdec4227SStephan Aßmus new BMessage(MSG_SHOW_SOURCE_PACKAGES)); 765fdec4227SStephan Aßmus menu->AddItem(fShowSourcePackagesItem); 766fdec4227SStephan Aßmus 767fdec4227SStephan Aßmus menuBar->AddItem(menu); 76804c9d578SStephan Aßmus } 76904c9d578SStephan Aßmus 77004c9d578SStephan Aßmus 77104c9d578SStephan Aßmus void 772e0a26dceSStephan Aßmus MainWindow::_BuildUserMenu(BMenuBar* menuBar) 773e0a26dceSStephan Aßmus { 774e0a26dceSStephan Aßmus fUserMenu = new BMenu(B_TRANSLATE("Not logged in")); 775e0a26dceSStephan Aßmus 776e0a26dceSStephan Aßmus fLogInItem = new BMenuItem(B_TRANSLATE("Log in" B_UTF8_ELLIPSIS), 777e0a26dceSStephan Aßmus new BMessage(MSG_LOG_IN)); 778e0a26dceSStephan Aßmus fUserMenu->AddItem(fLogInItem); 779e0a26dceSStephan Aßmus 780e0a26dceSStephan Aßmus fLogOutItem = new BMenuItem(B_TRANSLATE("Log out"), 781e0a26dceSStephan Aßmus new BMessage(MSG_LOG_OUT)); 782e0a26dceSStephan Aßmus fUserMenu->AddItem(fLogOutItem); 783e0a26dceSStephan Aßmus 7840c82f64bSAndrew Lindesay BMenuItem *latestUserUsageConditionsMenuItem = 7851448ced0SHumdinger new BMenuItem(B_TRANSLATE("View latest usage conditions" 78601339a54SAndrew Lindesay B_UTF8_ELLIPSIS), 78701339a54SAndrew Lindesay new BMessage(MSG_VIEW_LATEST_USER_USAGE_CONDITIONS)); 7880c82f64bSAndrew Lindesay fUserMenu->AddItem(latestUserUsageConditionsMenuItem); 78901339a54SAndrew Lindesay 790d2d4866dSAndrew Lindesay fUsersUserUsageConditionsMenuItem = 791d2d4866dSAndrew Lindesay new BMenuItem(B_TRANSLATE("View agreed usage conditions" 792d2d4866dSAndrew Lindesay B_UTF8_ELLIPSIS), 793d2d4866dSAndrew Lindesay new BMessage(MSG_VIEW_USERS_USER_USAGE_CONDITIONS)); 794d2d4866dSAndrew Lindesay fUserMenu->AddItem(fUsersUserUsageConditionsMenuItem); 795d2d4866dSAndrew Lindesay 796e0a26dceSStephan Aßmus menuBar->AddItem(fUserMenu); 797e0a26dceSStephan Aßmus } 798e0a26dceSStephan Aßmus 799e0a26dceSStephan Aßmus 800e0a26dceSStephan Aßmus void 801d2d4866dSAndrew Lindesay MainWindow::_RestoreNickname(const BMessage& settings) 802f7c2983eSAxel Dörfler { 803d2d4866dSAndrew Lindesay BString nickname; 804d2d4866dSAndrew Lindesay if (settings.FindString("username", &nickname) == B_OK 805d2d4866dSAndrew Lindesay && nickname.Length() > 0) { 806d2d4866dSAndrew Lindesay fModel.SetNickname(nickname); 807f7c2983eSAxel Dörfler } 808f7c2983eSAxel Dörfler } 809f7c2983eSAxel Dörfler 810f7c2983eSAxel Dörfler 811f7c2983eSAxel Dörfler const char* 812f7c2983eSAxel Dörfler MainWindow::_WindowFrameName() const 813f7c2983eSAxel Dörfler { 814f7c2983eSAxel Dörfler if (fSinglePackageMode) 815f7c2983eSAxel Dörfler return "small window frame"; 816f7c2983eSAxel Dörfler 817f7c2983eSAxel Dörfler return "window frame"; 818f7c2983eSAxel Dörfler } 819f7c2983eSAxel Dörfler 820f7c2983eSAxel Dörfler 821f7c2983eSAxel Dörfler void 822f7c2983eSAxel Dörfler MainWindow::_RestoreWindowFrame(const BMessage& settings) 823f7c2983eSAxel Dörfler { 824f7c2983eSAxel Dörfler BRect frame = Frame(); 825f7c2983eSAxel Dörfler 826f7c2983eSAxel Dörfler BRect windowFrame; 827f7c2983eSAxel Dörfler bool fromSettings = false; 828f7c2983eSAxel Dörfler if (settings.FindRect(_WindowFrameName(), &windowFrame) == B_OK) { 829f7c2983eSAxel Dörfler frame = windowFrame; 830f7c2983eSAxel Dörfler fromSettings = true; 831f7c2983eSAxel Dörfler } else if (!fSinglePackageMode) { 832f7c2983eSAxel Dörfler // Resize to occupy a certain screen size 833f7c2983eSAxel Dörfler BRect screenFrame = BScreen(this).Frame(); 834f7c2983eSAxel Dörfler float width = frame.Width(); 835f7c2983eSAxel Dörfler float height = frame.Height(); 836f7c2983eSAxel Dörfler if (width < screenFrame.Width() * .666f 837f7c2983eSAxel Dörfler && height < screenFrame.Height() * .666f) { 838f7c2983eSAxel Dörfler frame.bottom = frame.top + screenFrame.Height() * .666f; 839f7c2983eSAxel Dörfler frame.right = frame.left 840f7c2983eSAxel Dörfler + std::min(screenFrame.Width() * .666f, height * 7 / 5); 841f7c2983eSAxel Dörfler } 842f7c2983eSAxel Dörfler } 843f7c2983eSAxel Dörfler 844f7c2983eSAxel Dörfler MoveTo(frame.LeftTop()); 845f7c2983eSAxel Dörfler ResizeTo(frame.Width(), frame.Height()); 846f7c2983eSAxel Dörfler 847f7c2983eSAxel Dörfler if (fromSettings) 8488e96ec34SAxel Dörfler MoveOnScreen(); 849f7c2983eSAxel Dörfler else 850f7c2983eSAxel Dörfler CenterOnScreen(); 851f7c2983eSAxel Dörfler } 852f7c2983eSAxel Dörfler 853f7c2983eSAxel Dörfler 854f7c2983eSAxel Dörfler void 855ccf707d0SAndrew Lindesay MainWindow::_RestoreModelSettings(const BMessage& settings) 856ccf707d0SAndrew Lindesay { 857ccf707d0SAndrew Lindesay BString packageListViewMode; 858133ebab6SAndrew Lindesay if (settings.FindString(SETTING_PACKAGE_LIST_VIEW_MODE, 859ccf707d0SAndrew Lindesay &packageListViewMode) == B_OK) { 860ccf707d0SAndrew Lindesay fModel.SetPackageListViewMode( 861ccf707d0SAndrew Lindesay main_window_str_to_package_list_view_mode(packageListViewMode)); 862ccf707d0SAndrew Lindesay } 863ccf707d0SAndrew Lindesay 864ccf707d0SAndrew Lindesay bool showOption; 865133ebab6SAndrew Lindesay if (settings.FindBool(SETTING_SHOW_AVAILABLE_PACKAGES, &showOption) == B_OK) 866ccf707d0SAndrew Lindesay fModel.SetShowAvailablePackages(showOption); 867133ebab6SAndrew Lindesay if (settings.FindBool(SETTING_SHOW_INSTALLED_PACKAGES, &showOption) == B_OK) 868ccf707d0SAndrew Lindesay fModel.SetShowInstalledPackages(showOption); 869133ebab6SAndrew Lindesay if (settings.FindBool(SETTING_SHOW_DEVELOP_PACKAGES, &showOption) == B_OK) 870ccf707d0SAndrew Lindesay fModel.SetShowDevelopPackages(showOption); 871133ebab6SAndrew Lindesay if (settings.FindBool(SETTING_SHOW_SOURCE_PACKAGES, &showOption) == B_OK) 872ccf707d0SAndrew Lindesay fModel.SetShowSourcePackages(showOption); 873133ebab6SAndrew Lindesay if (settings.FindBool(SETTING_CAN_SHARE_ANONYMOUS_USER_DATA, 874133ebab6SAndrew Lindesay &showOption) == B_OK) { 875133ebab6SAndrew Lindesay fModel.SetCanShareAnonymousUsageData(showOption); 876133ebab6SAndrew Lindesay } 877133ebab6SAndrew Lindesay } 878133ebab6SAndrew Lindesay 879133ebab6SAndrew Lindesay 880133ebab6SAndrew Lindesay void 881133ebab6SAndrew Lindesay MainWindow::_MaybePromptCanShareAnonymousUserData(const BMessage& settings) 882133ebab6SAndrew Lindesay { 883133ebab6SAndrew Lindesay bool showOption; 884133ebab6SAndrew Lindesay if (settings.FindBool(SETTING_CAN_SHARE_ANONYMOUS_USER_DATA, 885133ebab6SAndrew Lindesay &showOption) == B_NAME_NOT_FOUND) { 886133ebab6SAndrew Lindesay _PromptCanShareAnonymousUserData(); 887133ebab6SAndrew Lindesay } 888133ebab6SAndrew Lindesay } 889133ebab6SAndrew Lindesay 890133ebab6SAndrew Lindesay 891133ebab6SAndrew Lindesay void 892133ebab6SAndrew Lindesay MainWindow::_PromptCanShareAnonymousUserData() 893133ebab6SAndrew Lindesay { 894133ebab6SAndrew Lindesay BAlert* alert = new(std::nothrow) BAlert( 895133ebab6SAndrew Lindesay B_TRANSLATE("Sending anonymous usage data"), 896133ebab6SAndrew Lindesay B_TRANSLATE("Would it be acceptable to send anonymous usage data to the" 897133ebab6SAndrew Lindesay " HaikuDepotServer system from this computer? You can change your" 898133ebab6SAndrew Lindesay " preference in the \"Settings\" window later."), 899133ebab6SAndrew Lindesay B_TRANSLATE("No"), 900133ebab6SAndrew Lindesay B_TRANSLATE("Yes")); 901133ebab6SAndrew Lindesay 902133ebab6SAndrew Lindesay int32 result = alert->Go(); 903133ebab6SAndrew Lindesay fModel.SetCanShareAnonymousUsageData(1 == result); 904ccf707d0SAndrew Lindesay } 905ccf707d0SAndrew Lindesay 906ccf707d0SAndrew Lindesay 907ccf707d0SAndrew Lindesay void 90863975654SStephan Aßmus MainWindow::_InitWorkerThreads() 90963975654SStephan Aßmus { 91063975654SStephan Aßmus fPackageToPopulateSem = create_sem(0, "PopulatePackage"); 91163975654SStephan Aßmus if (fPackageToPopulateSem >= 0) { 91263975654SStephan Aßmus fPopulatePackageWorker = spawn_thread(&_PopulatePackageWorker, 91363975654SStephan Aßmus "Package Populator", B_NORMAL_PRIORITY, this); 91463975654SStephan Aßmus if (fPopulatePackageWorker >= 0) 91563975654SStephan Aßmus resume_thread(fPopulatePackageWorker); 91609f82905SStephan Aßmus } else 91709f82905SStephan Aßmus fPopulatePackageWorker = -1; 91863975654SStephan Aßmus } 91963975654SStephan Aßmus 92063975654SStephan Aßmus 92163975654SStephan Aßmus void 922c4199192SAndrew Lindesay MainWindow::_AdoptModelControls() 92304c9d578SStephan Aßmus { 9249883929bSAndrew Lindesay if (fSinglePackageMode) 9259883929bSAndrew Lindesay return; 9269883929bSAndrew Lindesay 92704c9d578SStephan Aßmus BAutolock locker(fModel.Lock()); 928fdec4227SStephan Aßmus fShowAvailablePackagesItem->SetMarked(fModel.ShowAvailablePackages()); 929fdec4227SStephan Aßmus fShowInstalledPackagesItem->SetMarked(fModel.ShowInstalledPackages()); 930fdec4227SStephan Aßmus fShowSourcePackagesItem->SetMarked(fModel.ShowSourcePackages()); 931fdec4227SStephan Aßmus fShowDevelopPackagesItem->SetMarked(fModel.ShowDevelopPackages()); 932da651104SStephan Aßmus 933ccf707d0SAndrew Lindesay if (fModel.PackageListViewMode() == PROMINENT) 934ccf707d0SAndrew Lindesay fListTabs->Select(TAB_PROMINENT_PACKAGES); 9354fade61fSStephan Aßmus else 936ccf707d0SAndrew Lindesay fListTabs->Select(TAB_ALL_PACKAGES); 937b965ce70SHumdinger 938b965ce70SHumdinger fFilterView->AdoptModel(fModel); 93904c9d578SStephan Aßmus } 94004c9d578SStephan Aßmus 94104c9d578SStephan Aßmus 94204c9d578SStephan Aßmus void 943c4199192SAndrew Lindesay MainWindow::_AdoptModel() 944c4199192SAndrew Lindesay { 945fa5c8097SAndrew Lindesay HDTRACE("adopting model to main window ui"); 946c4199192SAndrew Lindesay 947c4199192SAndrew Lindesay if (fSinglePackageMode) 948c4199192SAndrew Lindesay return; 949c4199192SAndrew Lindesay 95005880d13SAndrew Lindesay std::vector<DepotInfoRef> depots = _CreateSnapshotOfDepots(); 95105880d13SAndrew Lindesay std::vector<DepotInfoRef>::iterator it; 9520b69420bSAndrew Lindesay 9530b69420bSAndrew Lindesay fFeaturedPackagesView->BeginAddRemove(); 9540b69420bSAndrew Lindesay 95505880d13SAndrew Lindesay for (it = depots.begin(); it != depots.end(); it++) { 95605880d13SAndrew Lindesay DepotInfoRef depotInfoRef = *it; 957d75b4d61SAndrew Lindesay for (int i = 0; i < depotInfoRef->CountPackages(); i++) { 958d75b4d61SAndrew Lindesay PackageInfoRef package = depotInfoRef->PackageAtIndex(i); 959d75b4d61SAndrew Lindesay _AddRemovePackageFromLists(package); 960d75b4d61SAndrew Lindesay } 961c4199192SAndrew Lindesay } 962c4199192SAndrew Lindesay 9630b69420bSAndrew Lindesay fFeaturedPackagesView->EndAddRemove(); 9640b69420bSAndrew Lindesay 965c4199192SAndrew Lindesay _AdoptModelControls(); 966c4199192SAndrew Lindesay } 967c4199192SAndrew Lindesay 968c4199192SAndrew Lindesay 969c4199192SAndrew Lindesay void 970c4199192SAndrew Lindesay MainWindow::_AddRemovePackageFromLists(const PackageInfoRef& package) 971c4199192SAndrew Lindesay { 972c4199192SAndrew Lindesay bool matches; 973c4199192SAndrew Lindesay 974c4199192SAndrew Lindesay { 975c4199192SAndrew Lindesay AutoLocker<BLocker> modelLocker(fModel.Lock()); 976c4199192SAndrew Lindesay matches = fModel.MatchesFilter(package); 977c4199192SAndrew Lindesay } 978c4199192SAndrew Lindesay 979c4199192SAndrew Lindesay if (matches) { 980c4199192SAndrew Lindesay if (package->IsProminent()) 981c4199192SAndrew Lindesay fFeaturedPackagesView->AddPackage(package); 982c4199192SAndrew Lindesay fPackageListView->AddPackage(package); 983c4199192SAndrew Lindesay } else { 984c4199192SAndrew Lindesay fFeaturedPackagesView->RemovePackage(package); 985c4199192SAndrew Lindesay fPackageListView->RemovePackage(package); 986c4199192SAndrew Lindesay } 987c4199192SAndrew Lindesay } 988c4199192SAndrew Lindesay 989c4199192SAndrew Lindesay 990c4199192SAndrew Lindesay void 99184674570SAndrew Lindesay MainWindow::_SetupDelayedIncrementViewCounter(const PackageInfoRef package) { 99284674570SAndrew Lindesay if (fIncrementViewCounterDelayedRunner != NULL) { 99384674570SAndrew Lindesay fIncrementViewCounterDelayedRunner->SetCount(0); 99484674570SAndrew Lindesay delete fIncrementViewCounterDelayedRunner; 99584674570SAndrew Lindesay } 99684674570SAndrew Lindesay BMessage message(MSG_INCREMENT_VIEW_COUNTER); 99784674570SAndrew Lindesay message.SetString("name", package->Name()); 99884674570SAndrew Lindesay fIncrementViewCounterDelayedRunner = 99984674570SAndrew Lindesay new BMessageRunner(BMessenger(this), &message, 100084674570SAndrew Lindesay kIncrementViewCounterDelayMicros, 1); 100184674570SAndrew Lindesay if (fIncrementViewCounterDelayedRunner->InitCheck() 100284674570SAndrew Lindesay != B_OK) { 100384674570SAndrew Lindesay HDERROR("unable to init the increment view counter"); 100484674570SAndrew Lindesay } 100584674570SAndrew Lindesay } 100684674570SAndrew Lindesay 100784674570SAndrew Lindesay 100884674570SAndrew Lindesay void 100984674570SAndrew Lindesay MainWindow::_HandleIncrementViewCounter(const BMessage* message) 101084674570SAndrew Lindesay { 101184674570SAndrew Lindesay BString name; 101284674570SAndrew Lindesay if (message->FindString("name", &name) == B_OK) { 101384674570SAndrew Lindesay const PackageInfoRef& viewedPackage = 101484674570SAndrew Lindesay fPackageInfoView->Package(); 101584674570SAndrew Lindesay if (viewedPackage.IsSet()) { 101684674570SAndrew Lindesay if (viewedPackage->Name() == name) 101784674570SAndrew Lindesay _IncrementViewCounter(viewedPackage); 101884674570SAndrew Lindesay else 101984674570SAndrew Lindesay HDINFO("incr. view counter; name mismatch"); 102084674570SAndrew Lindesay } else 102184674570SAndrew Lindesay HDINFO("incr. view counter; no viewed pkg"); 102284674570SAndrew Lindesay } else 102384674570SAndrew Lindesay HDERROR("incr. view counter; no name"); 102484674570SAndrew Lindesay fIncrementViewCounterDelayedRunner->SetCount(0); 102584674570SAndrew Lindesay delete fIncrementViewCounterDelayedRunner; 102684674570SAndrew Lindesay fIncrementViewCounterDelayedRunner = NULL; 102784674570SAndrew Lindesay } 102884674570SAndrew Lindesay 102984674570SAndrew Lindesay 103084674570SAndrew Lindesay void 1031409af934SAndrew Lindesay MainWindow::_IncrementViewCounter(const PackageInfoRef package) 1032133ebab6SAndrew Lindesay { 1033133ebab6SAndrew Lindesay bool shouldIncrementViewCounter = false; 1034133ebab6SAndrew Lindesay 1035133ebab6SAndrew Lindesay { 1036133ebab6SAndrew Lindesay AutoLocker<BLocker> modelLocker(fModel.Lock()); 1037133ebab6SAndrew Lindesay bool canShareAnonymousUsageData = fModel.CanShareAnonymousUsageData(); 1038133ebab6SAndrew Lindesay if (canShareAnonymousUsageData && !package->Viewed()) { 1039133ebab6SAndrew Lindesay package->SetViewed(); 1040133ebab6SAndrew Lindesay shouldIncrementViewCounter = true; 1041133ebab6SAndrew Lindesay } 1042133ebab6SAndrew Lindesay } 1043133ebab6SAndrew Lindesay 1044133ebab6SAndrew Lindesay if (shouldIncrementViewCounter) { 1045467ffecdSAugustin Cavalier ProcessCoordinator* incrementViewCoordinator = 1046133ebab6SAndrew Lindesay ProcessCoordinatorFactory::CreateIncrementViewCounter( 1047133ebab6SAndrew Lindesay &fModel, package); 1048467ffecdSAugustin Cavalier _AddProcessCoordinator(incrementViewCoordinator); 1049133ebab6SAndrew Lindesay } 1050133ebab6SAndrew Lindesay } 1051133ebab6SAndrew Lindesay 1052133ebab6SAndrew Lindesay 1053133ebab6SAndrew Lindesay void 105404c9d578SStephan Aßmus MainWindow::_AdoptPackage(const PackageInfoRef& package) 105504c9d578SStephan Aßmus { 105675ba9dbfSStephan Aßmus { 105775ba9dbfSStephan Aßmus BAutolock locker(fModel.Lock()); 105804c9d578SStephan Aßmus fPackageInfoView->SetPackage(package); 10591986ab9fSStephan Aßmus 1060664372abSStephan Aßmus if (fFeaturedPackagesView != NULL) 1061664372abSStephan Aßmus fFeaturedPackagesView->SelectPackage(package); 10621986ab9fSStephan Aßmus if (fPackageListView != NULL) 10631986ab9fSStephan Aßmus fPackageListView->SelectPackage(package); 106475ba9dbfSStephan Aßmus } 106504c9d578SStephan Aßmus 1066a9edb9bfSAndrew Lindesay _PopulatePackageAsync(false); 106704c9d578SStephan Aßmus } 106804c9d578SStephan Aßmus 106904c9d578SStephan Aßmus 107004c9d578SStephan Aßmus void 107104c9d578SStephan Aßmus MainWindow::_ClearPackage() 107204c9d578SStephan Aßmus { 107304c9d578SStephan Aßmus fPackageInfoView->Clear(); 107404c9d578SStephan Aßmus } 107504c9d578SStephan Aßmus 107604c9d578SStephan Aßmus 107704c9d578SStephan Aßmus void 10783369e03dSAndrew Lindesay MainWindow::_StartBulkLoad(bool force) 107904c9d578SStephan Aßmus { 1080c4199192SAndrew Lindesay if (fFeaturedPackagesView != NULL) 1081c4199192SAndrew Lindesay fFeaturedPackagesView->Clear(); 1082c4199192SAndrew Lindesay if (fPackageListView != NULL) 1083c4199192SAndrew Lindesay fPackageListView->Clear(); 1084c4199192SAndrew Lindesay fPackageInfoView->Clear(); 1085c4199192SAndrew Lindesay 108610cd325cSAndrew Lindesay fRefreshRepositoriesItem->SetEnabled(false); 108710cd325cSAndrew Lindesay ProcessCoordinator* bulkLoadCoordinator = 108810cd325cSAndrew Lindesay ProcessCoordinatorFactory::CreateBulkLoadCoordinator( 1089409af934SAndrew Lindesay fPackageInfoListener, &fModel, force); 109010cd325cSAndrew Lindesay _AddProcessCoordinator(bulkLoadCoordinator); 109104c9d578SStephan Aßmus } 109204c9d578SStephan Aßmus 109304c9d578SStephan Aßmus 109404c9d578SStephan Aßmus void 109510cd325cSAndrew Lindesay MainWindow::_BulkLoadCompleteReceived(status_t errorStatus) 109604c9d578SStephan Aßmus { 109710cd325cSAndrew Lindesay if (errorStatus != B_OK) { 10983369e03dSAndrew Lindesay AppUtils::NotifySimpleError( 10991448ced0SHumdinger B_TRANSLATE("Package update error"), 11003369e03dSAndrew Lindesay B_TRANSLATE("While updating package data, a problem has arisen " 11013369e03dSAndrew Lindesay "that may cause data to be outdated or missing from the " 11023369e03dSAndrew Lindesay "application's display. Additional details regarding this " 11033369e03dSAndrew Lindesay "problem may be able to be obtained from the application " 1104b21c9447SAndrew Lindesay "logs." 1105b21c9447SAndrew Lindesay ALERT_MSG_LOGS_USER_GUIDE)); 110604c9d578SStephan Aßmus } 110710cd325cSAndrew Lindesay 11083369e03dSAndrew Lindesay fRefreshRepositoriesItem->SetEnabled(true); 110910cd325cSAndrew Lindesay _AdoptModel(); 111010cd325cSAndrew Lindesay _UpdateAvailableRepositories(); 1111ccf707d0SAndrew Lindesay 1112ccf707d0SAndrew Lindesay // if after loading everything in, it transpires that there are no 1113ccf707d0SAndrew Lindesay // featured packages then the featured packages should be disabled 1114ccf707d0SAndrew Lindesay // and the user should be switched to the "all packages" view so 1115ccf707d0SAndrew Lindesay // that they are not presented with a blank window! 1116ccf707d0SAndrew Lindesay 1117ccf707d0SAndrew Lindesay bool hasProminentPackages = fModel.HasAnyProminentPackages(); 1118ccf707d0SAndrew Lindesay fListTabs->TabAt(TAB_PROMINENT_PACKAGES)->SetEnabled(hasProminentPackages); 1119ccf707d0SAndrew Lindesay if (!hasProminentPackages 1120ccf707d0SAndrew Lindesay && fListTabs->Selection() == TAB_PROMINENT_PACKAGES) { 1121ccf707d0SAndrew Lindesay fModel.SetPackageListViewMode(ALL); 1122ccf707d0SAndrew Lindesay fListTabs->Select(TAB_ALL_PACKAGES); 1123ccf707d0SAndrew Lindesay } 112404c9d578SStephan Aßmus } 112504c9d578SStephan Aßmus 112604c9d578SStephan Aßmus 11273369e03dSAndrew Lindesay void 112810cd325cSAndrew Lindesay MainWindow::_NotifyWorkStatusClear() 112904c9d578SStephan Aßmus { 113010cd325cSAndrew Lindesay BMessage message(MSG_WORK_STATUS_CLEAR); 113110cd325cSAndrew Lindesay this->PostMessage(&message, this); 113210cd325cSAndrew Lindesay } 113310cd325cSAndrew Lindesay 113410cd325cSAndrew Lindesay 113510cd325cSAndrew Lindesay void 113610cd325cSAndrew Lindesay MainWindow::_HandleWorkStatusClear() 113710cd325cSAndrew Lindesay { 113810cd325cSAndrew Lindesay fWorkStatusView->SetText(""); 11393369e03dSAndrew Lindesay fWorkStatusView->SetIdle(); 11403369e03dSAndrew Lindesay } 114104c9d578SStephan Aßmus 114204c9d578SStephan Aßmus 11433369e03dSAndrew Lindesay /*! Sends off a message to the Window so that it can change the status view 11443369e03dSAndrew Lindesay on the front-end in the UI thread. 11453369e03dSAndrew Lindesay */ 114604c9d578SStephan Aßmus 11473369e03dSAndrew Lindesay void 11483369e03dSAndrew Lindesay MainWindow::_NotifyWorkStatusChange(const BString& text, float progress) 11493369e03dSAndrew Lindesay { 11503369e03dSAndrew Lindesay BMessage message(MSG_WORK_STATUS_CHANGE); 115104c9d578SStephan Aßmus 11523369e03dSAndrew Lindesay if (!text.IsEmpty()) 11533369e03dSAndrew Lindesay message.AddString(KEY_WORK_STATUS_TEXT, text); 11543369e03dSAndrew Lindesay message.AddFloat(KEY_WORK_STATUS_PROGRESS, progress); 115504c9d578SStephan Aßmus 11563369e03dSAndrew Lindesay this->PostMessage(&message, this); 11573369e03dSAndrew Lindesay } 115804c9d578SStephan Aßmus 11593369e03dSAndrew Lindesay 1160f32d5c5cSAndrew Lindesay void 1161f32d5c5cSAndrew Lindesay MainWindow::_HandleExternalPackageUpdateMessageReceived(const BMessage* message) 1162f32d5c5cSAndrew Lindesay { 1163f32d5c5cSAndrew Lindesay BStringList addedPackageNames; 1164f32d5c5cSAndrew Lindesay BStringList removedPackageNames; 1165f32d5c5cSAndrew Lindesay 1166f32d5c5cSAndrew Lindesay if (message->FindStrings("added package names", 1167f32d5c5cSAndrew Lindesay &addedPackageNames) == B_OK) { 1168f32d5c5cSAndrew Lindesay addedPackageNames.Sort(); 11690ebb9177SAndrew Lindesay AutoLocker<BLocker> locker(fModel.Lock()); 11700ebb9177SAndrew Lindesay fModel.SetStateForPackagesByName(addedPackageNames, ACTIVATED); 1171f32d5c5cSAndrew Lindesay } 1172f32d5c5cSAndrew Lindesay else 1173f32d5c5cSAndrew Lindesay HDINFO("no [added package names] key in inbound message"); 1174f32d5c5cSAndrew Lindesay 1175f32d5c5cSAndrew Lindesay if (message->FindStrings("removed package names", 1176f32d5c5cSAndrew Lindesay &removedPackageNames) == B_OK) { 1177f32d5c5cSAndrew Lindesay removedPackageNames.Sort(); 11780ebb9177SAndrew Lindesay AutoLocker<BLocker> locker(fModel.Lock()); 11790ebb9177SAndrew Lindesay fModel.SetStateForPackagesByName(addedPackageNames, UNINSTALLED); 1180f32d5c5cSAndrew Lindesay } else 1181f32d5c5cSAndrew Lindesay HDINFO("no [removed package names] key in inbound message"); 1182f32d5c5cSAndrew Lindesay } 1183f32d5c5cSAndrew Lindesay 1184f32d5c5cSAndrew Lindesay 11853369e03dSAndrew Lindesay void 11863369e03dSAndrew Lindesay MainWindow::_HandleWorkStatusChangeMessageReceived(const BMessage* message) 11873369e03dSAndrew Lindesay { 11889883929bSAndrew Lindesay if (fWorkStatusView == NULL) 11899883929bSAndrew Lindesay return; 11909883929bSAndrew Lindesay 11913369e03dSAndrew Lindesay BString text; 11923369e03dSAndrew Lindesay float progress; 11933369e03dSAndrew Lindesay 11943369e03dSAndrew Lindesay if (message->FindString(KEY_WORK_STATUS_TEXT, &text) == B_OK) 11953369e03dSAndrew Lindesay fWorkStatusView->SetText(text); 11963369e03dSAndrew Lindesay 1197a18f873fSAndrew Lindesay if (message->FindFloat(KEY_WORK_STATUS_PROGRESS, &progress) == B_OK) { 1198a18f873fSAndrew Lindesay if (progress < 0.0f) 1199a18f873fSAndrew Lindesay fWorkStatusView->SetBusy(); 1200a18f873fSAndrew Lindesay else 12013369e03dSAndrew Lindesay fWorkStatusView->SetProgress(progress); 1202a18f873fSAndrew Lindesay } else { 1203a18f873fSAndrew Lindesay HDERROR("work status change missing progress on update message"); 1204a18f873fSAndrew Lindesay fWorkStatusView->SetProgress(0.0f); 120504c9d578SStephan Aßmus } 120604c9d578SStephan Aßmus } 120704c9d578SStephan Aßmus 120804c9d578SStephan Aßmus 1209a9edb9bfSAndrew Lindesay /*! This method will cause the package to have its data refreshed from 1210a9edb9bfSAndrew Lindesay the server application. The refresh happens in the background; this method 1211a9edb9bfSAndrew Lindesay is asynchronous. 1212a9edb9bfSAndrew Lindesay */ 1213a9edb9bfSAndrew Lindesay 1214a9edb9bfSAndrew Lindesay void 1215a9edb9bfSAndrew Lindesay MainWindow::_PopulatePackageAsync(bool forcePopulate) 1216a9edb9bfSAndrew Lindesay { 1217a9edb9bfSAndrew Lindesay // Trigger asynchronous package population from the web-app 1218a9edb9bfSAndrew Lindesay { 1219a9edb9bfSAndrew Lindesay AutoLocker<BLocker> lock(&fPackageToPopulateLock); 1220a9edb9bfSAndrew Lindesay fPackageToPopulate = fPackageInfoView->Package(); 1221a9edb9bfSAndrew Lindesay fForcePopulatePackage = forcePopulate; 1222a9edb9bfSAndrew Lindesay } 1223a9edb9bfSAndrew Lindesay release_sem_etc(fPackageToPopulateSem, 1, 0); 1224a9edb9bfSAndrew Lindesay 1225f96d1f4dSAndrew Lindesay HDDEBUG("pkg [%s] will be updated from the server.", 1226fa5c8097SAndrew Lindesay fPackageToPopulate->Name().String()); 1227a9edb9bfSAndrew Lindesay } 1228a9edb9bfSAndrew Lindesay 1229a9edb9bfSAndrew Lindesay 1230a9edb9bfSAndrew Lindesay /*! This method will run in the background. The thread will block until there 1231a9edb9bfSAndrew Lindesay is a package to be updated. When the thread unblocks, it will update the 1232a9edb9bfSAndrew Lindesay package with information from the server. 1233a9edb9bfSAndrew Lindesay */ 1234a9edb9bfSAndrew Lindesay 123504c9d578SStephan Aßmus status_t 123604c9d578SStephan Aßmus MainWindow::_PopulatePackageWorker(void* arg) 123704c9d578SStephan Aßmus { 123804c9d578SStephan Aßmus MainWindow* window = reinterpret_cast<MainWindow*>(arg); 123904c9d578SStephan Aßmus 124004c9d578SStephan Aßmus while (acquire_sem(window->fPackageToPopulateSem) == B_OK) { 124104c9d578SStephan Aßmus PackageInfoRef package; 1242a9edb9bfSAndrew Lindesay bool force; 124304c9d578SStephan Aßmus { 124404c9d578SStephan Aßmus AutoLocker<BLocker> lock(&window->fPackageToPopulateLock); 124504c9d578SStephan Aßmus package = window->fPackageToPopulate; 1246a9edb9bfSAndrew Lindesay force = window->fForcePopulatePackage; 124704c9d578SStephan Aßmus } 124804c9d578SStephan Aßmus 1249779ab335SX512 if (package.IsSet()) { 1250a9edb9bfSAndrew Lindesay uint32 populateFlags = Model::POPULATE_USER_RATINGS 1251a9edb9bfSAndrew Lindesay | Model::POPULATE_CHANGELOG; 1252a9edb9bfSAndrew Lindesay 1253a9edb9bfSAndrew Lindesay if (force) 1254a9edb9bfSAndrew Lindesay populateFlags |= Model::POPULATE_FORCE; 1255a9edb9bfSAndrew Lindesay 1256a9edb9bfSAndrew Lindesay window->fModel.PopulatePackage(package, populateFlags); 1257a9edb9bfSAndrew Lindesay 1258fa5c8097SAndrew Lindesay HDDEBUG("populating package [%s]", package->Name().String()); 125904c9d578SStephan Aßmus } 126004c9d578SStephan Aßmus } 126104c9d578SStephan Aßmus 126204c9d578SStephan Aßmus return 0; 126304c9d578SStephan Aßmus } 126404c9d578SStephan Aßmus 126504c9d578SStephan Aßmus 126604c9d578SStephan Aßmus void 1267133ebab6SAndrew Lindesay MainWindow::_OpenSettingsWindow() 1268133ebab6SAndrew Lindesay { 1269133ebab6SAndrew Lindesay SettingsWindow* window = new SettingsWindow(this, &fModel); 1270133ebab6SAndrew Lindesay window->Show(); 1271133ebab6SAndrew Lindesay } 1272133ebab6SAndrew Lindesay 1273133ebab6SAndrew Lindesay 1274133ebab6SAndrew Lindesay void 12751bbda92dSStephan Aßmus MainWindow::_OpenLoginWindow(const BMessage& onSuccessMessage) 127604c9d578SStephan Aßmus { 127704c9d578SStephan Aßmus UserLoginWindow* window = new UserLoginWindow(this, 127804c9d578SStephan Aßmus BRect(0, 0, 500, 400), fModel); 12791bbda92dSStephan Aßmus 12801bbda92dSStephan Aßmus if (onSuccessMessage.what != 0) 12811bbda92dSStephan Aßmus window->SetOnSuccessMessage(BMessenger(this), onSuccessMessage); 12821bbda92dSStephan Aßmus 128304c9d578SStephan Aßmus window->Show(); 128404c9d578SStephan Aßmus } 128504c9d578SStephan Aßmus 12868f03a0f9SStephan Aßmus 12878f03a0f9SStephan Aßmus void 128810cd325cSAndrew Lindesay MainWindow::_StartUserVerify() 128910cd325cSAndrew Lindesay { 129010cd325cSAndrew Lindesay if (!fModel.Nickname().IsEmpty()) { 129110cd325cSAndrew Lindesay _AddProcessCoordinator( 129210cd325cSAndrew Lindesay ProcessCoordinatorFactory::CreateUserDetailVerifierCoordinator( 129310cd325cSAndrew Lindesay this, 129410cd325cSAndrew Lindesay // UserDetailVerifierListener 129510cd325cSAndrew Lindesay &fModel) ); 129610cd325cSAndrew Lindesay } 129710cd325cSAndrew Lindesay } 129810cd325cSAndrew Lindesay 129910cd325cSAndrew Lindesay 130010cd325cSAndrew Lindesay void 13018f03a0f9SStephan Aßmus MainWindow::_UpdateAuthorization() 13028f03a0f9SStephan Aßmus { 1303d2d4866dSAndrew Lindesay BString nickname(fModel.Nickname()); 1304d2d4866dSAndrew Lindesay bool hasUser = !nickname.IsEmpty(); 1305e0a26dceSStephan Aßmus 13066d519fd1SStephan Aßmus if (fLogOutItem != NULL) 1307e0a26dceSStephan Aßmus fLogOutItem->SetEnabled(hasUser); 1308d2d4866dSAndrew Lindesay if (fUsersUserUsageConditionsMenuItem != NULL) 1309d2d4866dSAndrew Lindesay fUsersUserUsageConditionsMenuItem->SetEnabled(hasUser); 1310e0a26dceSStephan Aßmus if (fLogInItem != NULL) { 1311e0a26dceSStephan Aßmus if (hasUser) 1312e0a26dceSStephan Aßmus fLogInItem->SetLabel(B_TRANSLATE("Switch account" B_UTF8_ELLIPSIS)); 1313e0a26dceSStephan Aßmus else 1314e0a26dceSStephan Aßmus fLogInItem->SetLabel(B_TRANSLATE("Log in" B_UTF8_ELLIPSIS)); 1315e0a26dceSStephan Aßmus } 1316e0a26dceSStephan Aßmus 1317e0a26dceSStephan Aßmus if (fUserMenu != NULL) { 1318e0a26dceSStephan Aßmus BString label; 1319d2d4866dSAndrew Lindesay if (hasUser) { 1320e0a26dceSStephan Aßmus label = B_TRANSLATE("Logged in as %User%"); 1321d2d4866dSAndrew Lindesay label.ReplaceAll("%User%", nickname); 1322d2d4866dSAndrew Lindesay } else { 1323d2d4866dSAndrew Lindesay label = B_TRANSLATE("Not logged in"); 1324e0a26dceSStephan Aßmus } 1325e0a26dceSStephan Aßmus fUserMenu->Superitem()->SetLabel(label); 1326e0a26dceSStephan Aßmus } 13278f03a0f9SStephan Aßmus } 13281bbda92dSStephan Aßmus 13291bbda92dSStephan Aßmus 13301bbda92dSStephan Aßmus void 1331b965ce70SHumdinger MainWindow::_UpdateAvailableRepositories() 1332b965ce70SHumdinger { 1333b965ce70SHumdinger fRepositoryMenu->RemoveItems(0, fRepositoryMenu->CountItems(), true); 1334b965ce70SHumdinger 1335b965ce70SHumdinger fRepositoryMenu->AddItem(new BMenuItem(B_TRANSLATE("All repositories"), 1336b965ce70SHumdinger new BMessage(MSG_DEPOT_SELECTED))); 1337b965ce70SHumdinger 1338b965ce70SHumdinger fRepositoryMenu->AddItem(new BSeparatorItem()); 1339b965ce70SHumdinger 1340b965ce70SHumdinger bool foundSelectedDepot = false; 134105880d13SAndrew Lindesay std::vector<DepotInfoRef> depots = _CreateSnapshotOfDepots(); 134205880d13SAndrew Lindesay std::vector<DepotInfoRef>::iterator it; 1343d13c3d89SAndrew Lindesay 134405880d13SAndrew Lindesay for (it = depots.begin(); it != depots.end(); it++) { 134505880d13SAndrew Lindesay DepotInfoRef depot = *it; 134605880d13SAndrew Lindesay 134705880d13SAndrew Lindesay if (depot->Name().Length() != 0) { 1348b965ce70SHumdinger BMessage* message = new BMessage(MSG_DEPOT_SELECTED); 134905880d13SAndrew Lindesay message->AddString("name", depot->Name()); 135005880d13SAndrew Lindesay BMenuItem* item = new(std::nothrow) BMenuItem(depot->Name(), message); 135105880d13SAndrew Lindesay 135205880d13SAndrew Lindesay if (item == NULL) 135305880d13SAndrew Lindesay HDFATAL("memory exhaustion"); 135405880d13SAndrew Lindesay 1355b965ce70SHumdinger fRepositoryMenu->AddItem(item); 1356b965ce70SHumdinger 135705880d13SAndrew Lindesay if (depot->Name() == fModel.Depot()) { 1358b965ce70SHumdinger item->SetMarked(true); 1359b965ce70SHumdinger foundSelectedDepot = true; 1360b965ce70SHumdinger } 1361b965ce70SHumdinger } 1362d13c3d89SAndrew Lindesay } 1363b965ce70SHumdinger 1364b965ce70SHumdinger if (!foundSelectedDepot) 1365b965ce70SHumdinger fRepositoryMenu->ItemAt(0)->SetMarked(true); 1366b965ce70SHumdinger } 1367b965ce70SHumdinger 1368b965ce70SHumdinger 1369a9edb9bfSAndrew Lindesay bool 1370a9edb9bfSAndrew Lindesay MainWindow::_SelectedPackageHasWebAppRepositoryCode() 1371a9edb9bfSAndrew Lindesay { 1372a9edb9bfSAndrew Lindesay const PackageInfoRef& package = fPackageInfoView->Package(); 13736ab878c0SAndrew Lindesay const BString depotName = package->DepotName(); 1374a9edb9bfSAndrew Lindesay 13756ab878c0SAndrew Lindesay if (depotName.IsEmpty()) { 1376fa5c8097SAndrew Lindesay HDDEBUG("the package [%s] has no depot name", package->Name().String()); 13776ab878c0SAndrew Lindesay } else { 13786ab878c0SAndrew Lindesay const DepotInfo* depot = fModel.DepotForName(depotName); 1379a9edb9bfSAndrew Lindesay 13806ab878c0SAndrew Lindesay if (depot == NULL) { 1381f96d1f4dSAndrew Lindesay HDINFO("the depot [%s] was not able to be found", 1382fa5c8097SAndrew Lindesay depotName.String()); 13836ab878c0SAndrew Lindesay } else { 13846ab878c0SAndrew Lindesay BString repositoryCode = depot->WebAppRepositoryCode(); 1385a9edb9bfSAndrew Lindesay 13866ab878c0SAndrew Lindesay if (repositoryCode.IsEmpty()) { 1387f96d1f4dSAndrew Lindesay HDINFO("the depot [%s] has no web app repository code", 1388fa5c8097SAndrew Lindesay depotName.String()); 1389fa5c8097SAndrew Lindesay } else 13906ab878c0SAndrew Lindesay return true; 13916ab878c0SAndrew Lindesay } 13926ab878c0SAndrew Lindesay } 13936ab878c0SAndrew Lindesay 13946ab878c0SAndrew Lindesay return false; 1395a9edb9bfSAndrew Lindesay } 1396a9edb9bfSAndrew Lindesay 1397a9edb9bfSAndrew Lindesay 1398b965ce70SHumdinger void 13991bbda92dSStephan Aßmus MainWindow::_RatePackage() 14001bbda92dSStephan Aßmus { 1401a9edb9bfSAndrew Lindesay if (!_SelectedPackageHasWebAppRepositoryCode()) { 1402a9edb9bfSAndrew Lindesay BAlert* alert = new(std::nothrow) BAlert( 1403cbadcae1SHumdinger B_TRANSLATE("Rating not possible"), 1404cbadcae1SHumdinger B_TRANSLATE("This package doesn't seem to be on the HaikuDepot " 1405cbadcae1SHumdinger "Server, so it's not possible to create a new rating " 1406cbadcae1SHumdinger "or edit an existing rating."), 1407a9edb9bfSAndrew Lindesay B_TRANSLATE("OK")); 1408a9edb9bfSAndrew Lindesay alert->Go(); 1409a9edb9bfSAndrew Lindesay return; 1410a9edb9bfSAndrew Lindesay } 1411a9edb9bfSAndrew Lindesay 1412d2d4866dSAndrew Lindesay if (fModel.Nickname().IsEmpty()) { 14131bbda92dSStephan Aßmus BAlert* alert = new(std::nothrow) BAlert( 14141bbda92dSStephan Aßmus B_TRANSLATE("Not logged in"), 14151bbda92dSStephan Aßmus B_TRANSLATE("You need to be logged into an account before you " 14161bbda92dSStephan Aßmus "can rate packages."), 14171bbda92dSStephan Aßmus B_TRANSLATE("Cancel"), 14181bbda92dSStephan Aßmus B_TRANSLATE("Login or Create account")); 14191bbda92dSStephan Aßmus 14201bbda92dSStephan Aßmus if (alert == NULL) 14211bbda92dSStephan Aßmus return; 14221bbda92dSStephan Aßmus 14231bbda92dSStephan Aßmus int32 choice = alert->Go(); 14241bbda92dSStephan Aßmus if (choice == 1) 14251bbda92dSStephan Aßmus _OpenLoginWindow(BMessage(MSG_RATE_PACKAGE)); 14261bbda92dSStephan Aßmus return; 14271bbda92dSStephan Aßmus } 14281bbda92dSStephan Aßmus 14291bbda92dSStephan Aßmus // TODO: Allow only one RatePackageWindow 14301bbda92dSStephan Aßmus // TODO: Mechanism for remembering the window frame 14311bbda92dSStephan Aßmus RatePackageWindow* window = new RatePackageWindow(this, 14321bbda92dSStephan Aßmus BRect(0, 0, 500, 400), fModel); 14331bbda92dSStephan Aßmus window->SetPackage(fPackageInfoView->Package()); 14341bbda92dSStephan Aßmus window->Show(); 14351bbda92dSStephan Aßmus } 1436d5ef985eSStephan Aßmus 1437d5ef985eSStephan Aßmus 1438d5ef985eSStephan Aßmus void 1439d5ef985eSStephan Aßmus MainWindow::_ShowScreenshot() 1440d5ef985eSStephan Aßmus { 1441d5ef985eSStephan Aßmus // TODO: Mechanism for remembering the window frame 1442d5ef985eSStephan Aßmus if (fScreenshotWindow == NULL) 1443*88af15cfSAndrew Lindesay fScreenshotWindow = new ScreenshotWindow(this, BRect(0, 0, 500, 400), &fModel); 1444d5ef985eSStephan Aßmus 1445d5ef985eSStephan Aßmus if (fScreenshotWindow->LockWithTimeout(1000) != B_OK) 1446d5ef985eSStephan Aßmus return; 1447d5ef985eSStephan Aßmus 1448d5ef985eSStephan Aßmus fScreenshotWindow->SetPackage(fPackageInfoView->Package()); 1449d5ef985eSStephan Aßmus 1450d5ef985eSStephan Aßmus if (fScreenshotWindow->IsHidden()) 1451d5ef985eSStephan Aßmus fScreenshotWindow->Show(); 1452d5ef985eSStephan Aßmus else 1453d5ef985eSStephan Aßmus fScreenshotWindow->Activate(); 1454d5ef985eSStephan Aßmus 1455d5ef985eSStephan Aßmus fScreenshotWindow->Unlock(); 1456d5ef985eSStephan Aßmus } 145701339a54SAndrew Lindesay 145801339a54SAndrew Lindesay 145901339a54SAndrew Lindesay void 1460d2d4866dSAndrew Lindesay MainWindow::_ViewUserUsageConditions( 1461d2d4866dSAndrew Lindesay UserUsageConditionsSelectionMode mode) 146201339a54SAndrew Lindesay { 146301339a54SAndrew Lindesay UserUsageConditionsWindow* window = new UserUsageConditionsWindow( 1464d2d4866dSAndrew Lindesay fModel, mode); 146501339a54SAndrew Lindesay window->Show(); 146601339a54SAndrew Lindesay } 146710cd325cSAndrew Lindesay 146810cd325cSAndrew Lindesay 146910cd325cSAndrew Lindesay void 147010cd325cSAndrew Lindesay MainWindow::UserCredentialsFailed() 147110cd325cSAndrew Lindesay { 147210cd325cSAndrew Lindesay BString message = B_TRANSLATE("The password previously " 147310cd325cSAndrew Lindesay "supplied for the user [%Nickname%] is not currently " 147410cd325cSAndrew Lindesay "valid. The user will be logged-out of this application " 147510cd325cSAndrew Lindesay "and you should login again with your updated password."); 147610cd325cSAndrew Lindesay message.ReplaceAll("%Nickname%", fModel.Nickname()); 147710cd325cSAndrew Lindesay 147810cd325cSAndrew Lindesay AppUtils::NotifySimpleError(B_TRANSLATE("Login issue"), 147910cd325cSAndrew Lindesay message); 148010cd325cSAndrew Lindesay 148110cd325cSAndrew Lindesay { 148210cd325cSAndrew Lindesay AutoLocker<BLocker> locker(fModel.Lock()); 148310cd325cSAndrew Lindesay fModel.SetNickname(""); 148410cd325cSAndrew Lindesay } 148510cd325cSAndrew Lindesay } 148610cd325cSAndrew Lindesay 148710cd325cSAndrew Lindesay 148810cd325cSAndrew Lindesay /*! \brief This method is invoked from the UserDetailVerifierProcess on a 148910cd325cSAndrew Lindesay background thread. For this reason it lodges a message into itself 149010cd325cSAndrew Lindesay which can then be handled on the main thread. 149110cd325cSAndrew Lindesay */ 149210cd325cSAndrew Lindesay 149310cd325cSAndrew Lindesay void 149410cd325cSAndrew Lindesay MainWindow::UserUsageConditionsNotLatest(const UserDetail& userDetail) 149510cd325cSAndrew Lindesay { 149610cd325cSAndrew Lindesay BMessage message(MSG_USER_USAGE_CONDITIONS_NOT_LATEST); 149710cd325cSAndrew Lindesay BMessage detailsMessage; 149810cd325cSAndrew Lindesay if (userDetail.Archive(&detailsMessage, true) != B_OK 149910cd325cSAndrew Lindesay || message.AddMessage("userDetail", &detailsMessage) != B_OK) { 1500fa5c8097SAndrew Lindesay HDERROR("unable to archive the user detail into a message"); 150110cd325cSAndrew Lindesay } 150210cd325cSAndrew Lindesay else 150310cd325cSAndrew Lindesay BMessenger(this).SendMessage(&message); 150410cd325cSAndrew Lindesay } 150510cd325cSAndrew Lindesay 150610cd325cSAndrew Lindesay 150710cd325cSAndrew Lindesay void 150810cd325cSAndrew Lindesay MainWindow::_HandleUserUsageConditionsNotLatest( 150910cd325cSAndrew Lindesay const UserDetail& userDetail) 151010cd325cSAndrew Lindesay { 151110cd325cSAndrew Lindesay ToLatestUserUsageConditionsWindow* window = 151210cd325cSAndrew Lindesay new ToLatestUserUsageConditionsWindow(this, fModel, userDetail); 151310cd325cSAndrew Lindesay window->Show(); 151410cd325cSAndrew Lindesay } 151510cd325cSAndrew Lindesay 151610cd325cSAndrew Lindesay 151710cd325cSAndrew Lindesay void 151810cd325cSAndrew Lindesay MainWindow::_AddProcessCoordinator(ProcessCoordinator* item) 151910cd325cSAndrew Lindesay { 152010cd325cSAndrew Lindesay AutoLocker<BLocker> lock(&fCoordinatorLock); 152110cd325cSAndrew Lindesay 152295c7b018SAndrew Lindesay if (fShouldCloseWhenNoProcessesToCoordinate) { 152395c7b018SAndrew Lindesay HDINFO("system shutting down --> new process coordinator [%s] rejected", 152495c7b018SAndrew Lindesay item->Name().String()); 152595c7b018SAndrew Lindesay return; 152695c7b018SAndrew Lindesay } 152795c7b018SAndrew Lindesay 1528a18f873fSAndrew Lindesay item->SetListener(this); 1529a18f873fSAndrew Lindesay 1530409af934SAndrew Lindesay if (fCoordinator == NULL) { 153110cd325cSAndrew Lindesay if (acquire_sem(fCoordinatorRunningSem) != B_OK) 153210cd325cSAndrew Lindesay debugger("unable to acquire the process coordinator sem"); 1533f96d1f4dSAndrew Lindesay HDINFO("adding and starting a process coordinator [%s]", 1534fa5c8097SAndrew Lindesay item->Name().String()); 1535409af934SAndrew Lindesay delete fCoordinator; 1536409af934SAndrew Lindesay fCoordinator = item; 153710cd325cSAndrew Lindesay fCoordinator->Start(); 15387d7de135SAugustin Cavalier } else { 1539f96d1f4dSAndrew Lindesay HDINFO("adding process coordinator [%s] to the queue", 154010cd325cSAndrew Lindesay item->Name().String()); 154110cd325cSAndrew Lindesay fCoordinatorQueue.push(item); 154210cd325cSAndrew Lindesay } 154310cd325cSAndrew Lindesay } 154410cd325cSAndrew Lindesay 154510cd325cSAndrew Lindesay 154610cd325cSAndrew Lindesay void 154710cd325cSAndrew Lindesay MainWindow::_SpinUntilProcessCoordinatorComplete() 154810cd325cSAndrew Lindesay { 154910cd325cSAndrew Lindesay while (true) { 155010cd325cSAndrew Lindesay if (acquire_sem(fCoordinatorRunningSem) != B_OK) 155110cd325cSAndrew Lindesay debugger("unable to acquire the process coordinator sem"); 155210cd325cSAndrew Lindesay if (release_sem(fCoordinatorRunningSem) != B_OK) 155310cd325cSAndrew Lindesay debugger("unable to release the process coordinator sem"); 155410cd325cSAndrew Lindesay { 155510cd325cSAndrew Lindesay AutoLocker<BLocker> lock(&fCoordinatorLock); 1556409af934SAndrew Lindesay if (fCoordinator == NULL) 155710cd325cSAndrew Lindesay return; 155810cd325cSAndrew Lindesay } 155910cd325cSAndrew Lindesay } 156010cd325cSAndrew Lindesay } 156110cd325cSAndrew Lindesay 156210cd325cSAndrew Lindesay 156310cd325cSAndrew Lindesay void 156410cd325cSAndrew Lindesay MainWindow::_StopProcessCoordinators() 156510cd325cSAndrew Lindesay { 156695c7b018SAndrew Lindesay HDINFO("will stop all queued process coordinators"); 156710cd325cSAndrew Lindesay AutoLocker<BLocker> lock(&fCoordinatorLock); 156810cd325cSAndrew Lindesay 156910cd325cSAndrew Lindesay while (!fCoordinatorQueue.empty()) { 1570409af934SAndrew Lindesay ProcessCoordinator* processCoordinator 1571f96d1f4dSAndrew Lindesay = fCoordinatorQueue.front(); 1572f96d1f4dSAndrew Lindesay HDINFO("will drop queued process coordinator [%s]", 1573fa5c8097SAndrew Lindesay processCoordinator->Name().String()); 157410cd325cSAndrew Lindesay fCoordinatorQueue.pop(); 1575409af934SAndrew Lindesay delete processCoordinator; 157610cd325cSAndrew Lindesay } 157710cd325cSAndrew Lindesay 1578409af934SAndrew Lindesay if (fCoordinator != NULL) 157995c7b018SAndrew Lindesay fCoordinator->RequestStop(); 158010cd325cSAndrew Lindesay } 158110cd325cSAndrew Lindesay 158210cd325cSAndrew Lindesay 158310cd325cSAndrew Lindesay /*! This method is called when there is some change in the bulk load process 158410cd325cSAndrew Lindesay or other process coordinator. 158510cd325cSAndrew Lindesay A change may mean that a new process has started / stopped etc... or it 158610cd325cSAndrew Lindesay may mean that the entire coordinator has finished. 158710cd325cSAndrew Lindesay */ 158810cd325cSAndrew Lindesay 158910cd325cSAndrew Lindesay void 159010cd325cSAndrew Lindesay MainWindow::CoordinatorChanged(ProcessCoordinatorState& coordinatorState) 159110cd325cSAndrew Lindesay { 1592409af934SAndrew Lindesay BMessage message(MSG_PROCESS_COORDINATOR_CHANGED); 1593409af934SAndrew Lindesay if (coordinatorState.Archive(&message, true) != B_OK) { 1594409af934SAndrew Lindesay HDFATAL("unable to archive message when the process coordinator" 1595409af934SAndrew Lindesay " has changed"); 1596409af934SAndrew Lindesay } 1597409af934SAndrew Lindesay BMessenger(this).SendMessage(&message); 1598409af934SAndrew Lindesay } 1599409af934SAndrew Lindesay 1600409af934SAndrew Lindesay 1601409af934SAndrew Lindesay void 1602409af934SAndrew Lindesay MainWindow::_HandleProcessCoordinatorChanged(ProcessCoordinatorState& coordinatorState) 1603409af934SAndrew Lindesay { 160410cd325cSAndrew Lindesay AutoLocker<BLocker> lock(&fCoordinatorLock); 160510cd325cSAndrew Lindesay 1606409af934SAndrew Lindesay if (fCoordinator->Identifier() 1607409af934SAndrew Lindesay == coordinatorState.ProcessCoordinatorIdentifier()) { 160810cd325cSAndrew Lindesay if (!coordinatorState.IsRunning()) { 160910cd325cSAndrew Lindesay if (release_sem(fCoordinatorRunningSem) != B_OK) 161010cd325cSAndrew Lindesay debugger("unable to release the process coordinator sem"); 1611f96d1f4dSAndrew Lindesay HDINFO("process coordinator [%s] did complete", 1612fa5c8097SAndrew Lindesay fCoordinator->Name().String()); 161310cd325cSAndrew Lindesay // complete the last one that just finished 161410cd325cSAndrew Lindesay BMessage* message = fCoordinator->Message(); 161510cd325cSAndrew Lindesay 161610cd325cSAndrew Lindesay if (message != NULL) { 161710cd325cSAndrew Lindesay BMessenger messenger(this); 161810cd325cSAndrew Lindesay message->AddInt64(KEY_ERROR_STATUS, 161910cd325cSAndrew Lindesay (int64) fCoordinator->ErrorStatus()); 162010cd325cSAndrew Lindesay messenger.SendMessage(message); 162110cd325cSAndrew Lindesay } 162210cd325cSAndrew Lindesay 16233538133fSAndrew Lindesay HDDEBUG("process coordinator report;\n---\n%s\n----", 16243538133fSAndrew Lindesay fCoordinator->LogReport().String()); 16253538133fSAndrew Lindesay 1626409af934SAndrew Lindesay delete fCoordinator; 1627409af934SAndrew Lindesay fCoordinator = NULL; 162810cd325cSAndrew Lindesay 162910cd325cSAndrew Lindesay // now schedule the next one. 163010cd325cSAndrew Lindesay if (!fCoordinatorQueue.empty()) { 163110cd325cSAndrew Lindesay if (acquire_sem(fCoordinatorRunningSem) != B_OK) 163210cd325cSAndrew Lindesay debugger("unable to acquire the process coordinator sem"); 163310cd325cSAndrew Lindesay fCoordinator = fCoordinatorQueue.front(); 1634f96d1f4dSAndrew Lindesay HDINFO("starting next process coordinator [%s]", 163510cd325cSAndrew Lindesay fCoordinator->Name().String()); 163610cd325cSAndrew Lindesay fCoordinatorQueue.pop(); 163710cd325cSAndrew Lindesay fCoordinator->Start(); 163810cd325cSAndrew Lindesay } 163910cd325cSAndrew Lindesay else { 164010cd325cSAndrew Lindesay _NotifyWorkStatusClear(); 164195c7b018SAndrew Lindesay if (fShouldCloseWhenNoProcessesToCoordinate) { 164295c7b018SAndrew Lindesay HDINFO("no more processes to coord --> will quit"); 164395c7b018SAndrew Lindesay BMessage message(B_QUIT_REQUESTED); 164495c7b018SAndrew Lindesay PostMessage(&message); 164595c7b018SAndrew Lindesay } 164610cd325cSAndrew Lindesay } 164710cd325cSAndrew Lindesay } 164810cd325cSAndrew Lindesay else { 164910cd325cSAndrew Lindesay _NotifyWorkStatusChange(coordinatorState.Message(), 165010cd325cSAndrew Lindesay coordinatorState.Progress()); 165110cd325cSAndrew Lindesay // show the progress to the user. 165210cd325cSAndrew Lindesay } 165395c7b018SAndrew Lindesay } else { 165495c7b018SAndrew Lindesay _NotifyWorkStatusClear(); 1655fa5c8097SAndrew Lindesay HDINFO("! unknown process coordinator changed"); 165610cd325cSAndrew Lindesay } 165795c7b018SAndrew Lindesay } 1658ccf707d0SAndrew Lindesay 1659ccf707d0SAndrew Lindesay 1660ccf707d0SAndrew Lindesay static package_list_view_mode 1661ccf707d0SAndrew Lindesay main_window_tab_to_package_list_view_mode(int32 tab) 1662ccf707d0SAndrew Lindesay { 1663ccf707d0SAndrew Lindesay if (tab == TAB_PROMINENT_PACKAGES) 1664ccf707d0SAndrew Lindesay return PROMINENT; 1665ccf707d0SAndrew Lindesay return ALL; 1666ccf707d0SAndrew Lindesay } 1667ccf707d0SAndrew Lindesay 1668ccf707d0SAndrew Lindesay 1669ccf707d0SAndrew Lindesay void 1670ccf707d0SAndrew Lindesay MainWindow::_HandleChangePackageListViewMode() 1671ccf707d0SAndrew Lindesay { 1672ccf707d0SAndrew Lindesay package_list_view_mode tabMode = main_window_tab_to_package_list_view_mode( 1673ccf707d0SAndrew Lindesay fListTabs->Selection()); 1674ccf707d0SAndrew Lindesay package_list_view_mode modelMode = fModel.PackageListViewMode(); 1675ccf707d0SAndrew Lindesay 1676ccf707d0SAndrew Lindesay if (tabMode != modelMode) { 1677ccf707d0SAndrew Lindesay BAutolock locker(fModel.Lock()); 1678ccf707d0SAndrew Lindesay fModel.SetPackageListViewMode(tabMode); 1679ccf707d0SAndrew Lindesay } 1680ccf707d0SAndrew Lindesay } 168105880d13SAndrew Lindesay 168205880d13SAndrew Lindesay 168305880d13SAndrew Lindesay std::vector<DepotInfoRef> 168405880d13SAndrew Lindesay MainWindow::_CreateSnapshotOfDepots() 168505880d13SAndrew Lindesay { 168605880d13SAndrew Lindesay std::vector<DepotInfoRef> result; 168705880d13SAndrew Lindesay BAutolock locker(fModel.Lock()); 168805880d13SAndrew Lindesay int32 countDepots = fModel.CountDepots(); 168905880d13SAndrew Lindesay for(int32 i = 0; i < countDepots; i++) 169005880d13SAndrew Lindesay result.push_back(fModel.DepotAtIndex(i)); 169105880d13SAndrew Lindesay return result; 169205880d13SAndrew Lindesay } 1693*88af15cfSAndrew Lindesay 1694*88af15cfSAndrew Lindesay 1695*88af15cfSAndrew Lindesay /*! This will get invoked in the case that a screenshot has been cached 1696*88af15cfSAndrew Lindesay and so could now be loaded by some UI element. This method will then 1697*88af15cfSAndrew Lindesay signal to other UI elements that they could load a screenshot should 1698*88af15cfSAndrew Lindesay they have been waiting for it. 1699*88af15cfSAndrew Lindesay */ 1700*88af15cfSAndrew Lindesay 1701*88af15cfSAndrew Lindesay void 1702*88af15cfSAndrew Lindesay MainWindow::_HandleScreenshotCached(const BMessage* message) 1703*88af15cfSAndrew Lindesay { 1704*88af15cfSAndrew Lindesay ScreenshotCoordinate coordinate(message); 1705*88af15cfSAndrew Lindesay fPackageInfoView->HandleScreenshotCached(coordinate); 1706*88af15cfSAndrew Lindesay } 1707