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. 6d13c3d89SAndrew Lindesay * Copyright 2016-2018, Andrew Lindesay <apl@lindesay.co.nz>. 7125d42d9SJulian Harnath * Copyright 2017, Julian Harnath <julian.harnath@rwth-aachen.de>. 804c9d578SStephan Aßmus * All rights reserved. Distributed under the terms of the MIT License. 904c9d578SStephan Aßmus */ 1004c9d578SStephan Aßmus 11f7c2983eSAxel Dörfler 1204c9d578SStephan Aßmus #include "MainWindow.h" 1304c9d578SStephan Aßmus 1404c9d578SStephan Aßmus #include <map> 153b17d8ddSAndrew Lindesay #include <vector> 1604c9d578SStephan Aßmus 1704c9d578SStephan Aßmus #include <stdio.h> 1804c9d578SStephan Aßmus #include <Alert.h> 1904c9d578SStephan Aßmus #include <Autolock.h> 2004c9d578SStephan Aßmus #include <Application.h> 2104c9d578SStephan Aßmus #include <Button.h> 2204c9d578SStephan Aßmus #include <Catalog.h> 234b930ccaSStephan Aßmus #include <CardLayout.h> 2404c9d578SStephan Aßmus #include <LayoutBuilder.h> 2504c9d578SStephan Aßmus #include <MenuBar.h> 2604c9d578SStephan Aßmus #include <MenuItem.h> 2704c9d578SStephan Aßmus #include <Messenger.h> 285bf2b6ebSBrian Hill #include <Roster.h> 29f7c2983eSAxel Dörfler #include <Screen.h> 3004c9d578SStephan Aßmus #include <ScrollView.h> 3104c9d578SStephan Aßmus #include <StringList.h> 320a9c9029SStephan Aßmus #include <StringView.h> 3304c9d578SStephan Aßmus #include <TabView.h> 3404c9d578SStephan Aßmus 3504c9d578SStephan Aßmus #include <package/Context.h> 3604c9d578SStephan Aßmus #include <package/manager/Exceptions.h> 3704c9d578SStephan Aßmus #include <package/manager/RepositoryBuilder.h> 3804c9d578SStephan Aßmus #include <package/RefreshRepositoryRequest.h> 3904c9d578SStephan Aßmus #include <package/PackageRoster.h> 4004c9d578SStephan Aßmus #include "package/RepositoryCache.h" 4104c9d578SStephan Aßmus #include <package/solver/SolverPackage.h> 4204c9d578SStephan Aßmus #include <package/solver/SolverProblem.h> 4304c9d578SStephan Aßmus #include <package/solver/SolverProblemSolution.h> 4404c9d578SStephan Aßmus #include <package/solver/SolverRepository.h> 4504c9d578SStephan Aßmus #include <package/solver/SolverResult.h> 4604c9d578SStephan Aßmus 4704c9d578SStephan Aßmus #include "AutoDeleter.h" 4804c9d578SStephan Aßmus #include "AutoLocker.h" 4904c9d578SStephan Aßmus #include "DecisionProvider.h" 504b930ccaSStephan Aßmus #include "FeaturedPackagesView.h" 5104c9d578SStephan Aßmus #include "FilterView.h" 5204c9d578SStephan Aßmus #include "JobStateListener.h" 53d13c3d89SAndrew Lindesay #include "Logger.h" 5404c9d578SStephan Aßmus #include "PackageInfoView.h" 5504c9d578SStephan Aßmus #include "PackageListView.h" 5604c9d578SStephan Aßmus #include "PackageManager.h" 5704c9d578SStephan Aßmus #include "RatePackageWindow.h" 583b17d8ddSAndrew Lindesay #include "RepositoryUrlUtils.h" 59e0a26dceSStephan Aßmus #include "support.h" 60d5ef985eSStephan Aßmus #include "ScreenshotWindow.h" 6104c9d578SStephan Aßmus #include "UserLoginWindow.h" 62125d42d9SJulian Harnath #include "WorkStatusView.h" 6304c9d578SStephan Aßmus 6404c9d578SStephan Aßmus 6504c9d578SStephan Aßmus #undef B_TRANSLATION_CONTEXT 6604c9d578SStephan Aßmus #define B_TRANSLATION_CONTEXT "MainWindow" 6704c9d578SStephan Aßmus 6804c9d578SStephan Aßmus 6904c9d578SStephan Aßmus enum { 7004c9d578SStephan Aßmus MSG_MODEL_WORKER_DONE = 'mmwd', 715bf2b6ebSBrian Hill MSG_REFRESH_REPOS = 'mrrp', 725bf2b6ebSBrian Hill MSG_MANAGE_REPOS = 'mmrp', 73d144f952SAugustin Cavalier MSG_SOFTWARE_UPDATER = 'mswu', 7404c9d578SStephan Aßmus MSG_LOG_IN = 'lgin', 758f03a0f9SStephan Aßmus MSG_LOG_OUT = 'lgot', 768f03a0f9SStephan Aßmus MSG_AUTHORIZATION_CHANGED = 'athc', 77da651104SStephan Aßmus MSG_PACKAGE_CHANGED = 'pchd', 78fdec4227SStephan Aßmus 79*e00a489bSAugustin Cavalier MSG_SHOW_FEATURED_PACKAGES = 'sofp', 80fdec4227SStephan Aßmus MSG_SHOW_AVAILABLE_PACKAGES = 'savl', 81fdec4227SStephan Aßmus MSG_SHOW_INSTALLED_PACKAGES = 'sins', 8204c9d578SStephan Aßmus MSG_SHOW_SOURCE_PACKAGES = 'ssrc', 8304c9d578SStephan Aßmus MSG_SHOW_DEVELOP_PACKAGES = 'sdvl' 8404c9d578SStephan Aßmus }; 8504c9d578SStephan Aßmus 8604c9d578SStephan Aßmus 8704c9d578SStephan Aßmus using namespace BPackageKit; 8804c9d578SStephan Aßmus using namespace BPackageKit::BManager::BPrivate; 8904c9d578SStephan Aßmus 9004c9d578SStephan Aßmus 9104c9d578SStephan Aßmus typedef std::map<BString, PackageInfoRef> PackageInfoMap; 9204c9d578SStephan Aßmus 9304c9d578SStephan Aßmus 9404c9d578SStephan Aßmus struct RefreshWorkerParameters { 9504c9d578SStephan Aßmus MainWindow* window; 9604c9d578SStephan Aßmus bool forceRefresh; 9704c9d578SStephan Aßmus 9804c9d578SStephan Aßmus RefreshWorkerParameters(MainWindow* window, bool forceRefresh) 9904c9d578SStephan Aßmus : 10004c9d578SStephan Aßmus window(window), 10104c9d578SStephan Aßmus forceRefresh(forceRefresh) 10204c9d578SStephan Aßmus { 10304c9d578SStephan Aßmus } 10404c9d578SStephan Aßmus }; 10504c9d578SStephan Aßmus 10604c9d578SStephan Aßmus 1078f03a0f9SStephan Aßmus class MessageModelListener : public ModelListener { 1088f03a0f9SStephan Aßmus public: 1098f03a0f9SStephan Aßmus MessageModelListener(const BMessenger& messenger) 1108f03a0f9SStephan Aßmus : 1118f03a0f9SStephan Aßmus fMessenger(messenger) 1128f03a0f9SStephan Aßmus { 1138f03a0f9SStephan Aßmus } 1148f03a0f9SStephan Aßmus 1158f03a0f9SStephan Aßmus virtual void AuthorizationChanged() 1168f03a0f9SStephan Aßmus { 1178f03a0f9SStephan Aßmus if (fMessenger.IsValid()) 1188f03a0f9SStephan Aßmus fMessenger.SendMessage(MSG_AUTHORIZATION_CHANGED); 1198f03a0f9SStephan Aßmus } 1208f03a0f9SStephan Aßmus 1218f03a0f9SStephan Aßmus private: 1228f03a0f9SStephan Aßmus BMessenger fMessenger; 1238f03a0f9SStephan Aßmus }; 1248f03a0f9SStephan Aßmus 1258f03a0f9SStephan Aßmus 126f7c2983eSAxel Dörfler MainWindow::MainWindow(const BMessage& settings) 12704c9d578SStephan Aßmus : 128f7c2983eSAxel Dörfler BWindow(BRect(50, 50, 650, 550), B_TRANSLATE_SYSTEM_NAME("HaikuDepot"), 12904c9d578SStephan Aßmus B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, 13004c9d578SStephan Aßmus B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS), 131d5ef985eSStephan Aßmus fScreenshotWindow(NULL), 132e0a26dceSStephan Aßmus fUserMenu(NULL), 133e0a26dceSStephan Aßmus fLogInItem(NULL), 134e0a26dceSStephan Aßmus fLogOutItem(NULL), 1358f03a0f9SStephan Aßmus fModelListener(new MessageModelListener(BMessenger(this)), true), 1363094fef3SAndrew Lindesay fBulkLoadStateMachine(&fModel), 13704c9d578SStephan Aßmus fTerminating(false), 1386d519fd1SStephan Aßmus fSinglePackageMode(false), 13904c9d578SStephan Aßmus fModelWorker(B_BAD_THREAD_ID) 14004c9d578SStephan Aßmus { 141cbadcae1SHumdinger BMenuBar* menuBar = new BMenuBar("Main Menu"); 14204c9d578SStephan Aßmus _BuildMenu(menuBar); 14304c9d578SStephan Aßmus 144cbadcae1SHumdinger BMenuBar* userMenuBar = new BMenuBar("User Menu"); 145e0a26dceSStephan Aßmus _BuildUserMenu(userMenuBar); 146e0a26dceSStephan Aßmus set_small_font(userMenuBar); 147e0a26dceSStephan Aßmus userMenuBar->SetExplicitMaxSize(BSize(B_SIZE_UNSET, 148e0a26dceSStephan Aßmus menuBar->MaxSize().height)); 149e0a26dceSStephan Aßmus 15004c9d578SStephan Aßmus fFilterView = new FilterView(); 1514b930ccaSStephan Aßmus fFeaturedPackagesView = new FeaturedPackagesView(); 15204c9d578SStephan Aßmus fPackageListView = new PackageListView(fModel.Lock()); 15304c9d578SStephan Aßmus fPackageInfoView = new PackageInfoView(fModel.Lock(), this); 15404c9d578SStephan Aßmus 15504c9d578SStephan Aßmus fSplitView = new BSplitView(B_VERTICAL, 5.0f); 15604c9d578SStephan Aßmus 157125d42d9SJulian Harnath fWorkStatusView = new WorkStatusView("work status"); 158125d42d9SJulian Harnath fPackageListView->AttachWorkStatusView(fWorkStatusView); 159125d42d9SJulian Harnath 160*e00a489bSAugustin Cavalier fListTabs = new TabView(BMessenger(this), 161*e00a489bSAugustin Cavalier BMessage(MSG_SHOW_FEATURED_PACKAGES), "list tabs"); 162*e00a489bSAugustin Cavalier fListTabs->AddTab(fFeaturedPackagesView); 163*e00a489bSAugustin Cavalier fListTabs->AddTab(fPackageListView); 1644b930ccaSStephan Aßmus 16504c9d578SStephan Aßmus BLayoutBuilder::Group<>(this, B_VERTICAL, 0.0f) 166e0a26dceSStephan Aßmus .AddGroup(B_HORIZONTAL, 0.0f) 167e0a26dceSStephan Aßmus .Add(menuBar, 1.0f) 168e0a26dceSStephan Aßmus .Add(userMenuBar, 0.0f) 169e0a26dceSStephan Aßmus .End() 17004c9d578SStephan Aßmus .Add(fFilterView) 17104c9d578SStephan Aßmus .AddSplit(fSplitView) 17204c9d578SStephan Aßmus .AddGroup(B_VERTICAL) 173*e00a489bSAugustin Cavalier .Add(fListTabs) 17404c9d578SStephan Aßmus .SetInsets( 17504c9d578SStephan Aßmus B_USE_DEFAULT_SPACING, 0.0f, 17604c9d578SStephan Aßmus B_USE_DEFAULT_SPACING, 0.0f) 17704c9d578SStephan Aßmus .End() 17804c9d578SStephan Aßmus .Add(fPackageInfoView) 17904c9d578SStephan Aßmus .End() 180125d42d9SJulian Harnath .Add(fWorkStatusView) 18104c9d578SStephan Aßmus ; 18204c9d578SStephan Aßmus 18304c9d578SStephan Aßmus fSplitView->SetCollapsible(0, false); 18404c9d578SStephan Aßmus fSplitView->SetCollapsible(1, false); 18504c9d578SStephan Aßmus 1868f03a0f9SStephan Aßmus fModel.AddListener(fModelListener); 1878f03a0f9SStephan Aßmus 18804c9d578SStephan Aßmus // Restore settings 18904c9d578SStephan Aßmus BMessage columnSettings; 19004c9d578SStephan Aßmus if (settings.FindMessage("column settings", &columnSettings) == B_OK) 19104c9d578SStephan Aßmus fPackageListView->LoadState(&columnSettings); 19204c9d578SStephan Aßmus 19304c9d578SStephan Aßmus bool showOption; 1942997e05bSStephan Aßmus if (settings.FindBool("show featured packages", &showOption) == B_OK) 1952997e05bSStephan Aßmus fModel.SetShowFeaturedPackages(showOption); 1962997e05bSStephan Aßmus if (settings.FindBool("show available packages", &showOption) == B_OK) 1972997e05bSStephan Aßmus fModel.SetShowAvailablePackages(showOption); 1982997e05bSStephan Aßmus if (settings.FindBool("show installed packages", &showOption) == B_OK) 1992997e05bSStephan Aßmus fModel.SetShowInstalledPackages(showOption); 20004c9d578SStephan Aßmus if (settings.FindBool("show develop packages", &showOption) == B_OK) 20104c9d578SStephan Aßmus fModel.SetShowDevelopPackages(showOption); 20204c9d578SStephan Aßmus if (settings.FindBool("show source packages", &showOption) == B_OK) 20304c9d578SStephan Aßmus fModel.SetShowSourcePackages(showOption); 20404c9d578SStephan Aßmus 2052997e05bSStephan Aßmus if (fModel.ShowFeaturedPackages()) 206*e00a489bSAugustin Cavalier fListTabs->Select(0); 2072997e05bSStephan Aßmus else 208*e00a489bSAugustin Cavalier fListTabs->Select(1); 2092997e05bSStephan Aßmus 210f7c2983eSAxel Dörfler _RestoreUserName(settings); 211f7c2983eSAxel Dörfler _RestoreWindowFrame(settings); 212f7c2983eSAxel Dörfler 21372fff6d3SJulian Harnath atomic_set(&fPackagesToShowListID, 0); 21472fff6d3SJulian Harnath 2158f03a0f9SStephan Aßmus // start worker threads 21604c9d578SStephan Aßmus BPackageRoster().StartWatching(this, 21704c9d578SStephan Aßmus B_WATCH_PACKAGE_INSTALLATION_LOCATIONS); 21804c9d578SStephan Aßmus 21904c9d578SStephan Aßmus _StartRefreshWorker(); 22004c9d578SStephan Aßmus 22163975654SStephan Aßmus _InitWorkerThreads(); 22204c9d578SStephan Aßmus } 22304c9d578SStephan Aßmus 22404c9d578SStephan Aßmus 225f7c2983eSAxel Dörfler MainWindow::MainWindow(const BMessage& settings, const PackageInfoRef& package) 2266d519fd1SStephan Aßmus : 227f7c2983eSAxel Dörfler BWindow(BRect(50, 50, 650, 350), B_TRANSLATE_SYSTEM_NAME("HaikuDepot"), 2286d519fd1SStephan Aßmus B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, 2296d519fd1SStephan Aßmus B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS), 230d78bfd8dSJulian Harnath fWorkStatusView(NULL), 231d5ef985eSStephan Aßmus fScreenshotWindow(NULL), 232e0a26dceSStephan Aßmus fUserMenu(NULL), 233e0a26dceSStephan Aßmus fLogInItem(NULL), 2346d519fd1SStephan Aßmus fLogOutItem(NULL), 2356d519fd1SStephan Aßmus fModelListener(new MessageModelListener(BMessenger(this)), true), 2363094fef3SAndrew Lindesay fBulkLoadStateMachine(&fModel), 2376d519fd1SStephan Aßmus fTerminating(false), 2386d519fd1SStephan Aßmus fSinglePackageMode(true), 2396d519fd1SStephan Aßmus fModelWorker(B_BAD_THREAD_ID) 2406d519fd1SStephan Aßmus { 2416d519fd1SStephan Aßmus fFilterView = new FilterView(); 2426d519fd1SStephan Aßmus fPackageListView = new PackageListView(fModel.Lock()); 2436d519fd1SStephan Aßmus fPackageInfoView = new PackageInfoView(fModel.Lock(), this); 2446d519fd1SStephan Aßmus 2456d519fd1SStephan Aßmus BLayoutBuilder::Group<>(this, B_VERTICAL) 2466d519fd1SStephan Aßmus .Add(fPackageInfoView) 2476d519fd1SStephan Aßmus .SetInsets(0, B_USE_WINDOW_INSETS, 0, 0) 2486d519fd1SStephan Aßmus ; 2496d519fd1SStephan Aßmus 2506d519fd1SStephan Aßmus fModel.AddListener(fModelListener); 2516d519fd1SStephan Aßmus 2526d519fd1SStephan Aßmus // Restore settings 253f7c2983eSAxel Dörfler _RestoreUserName(settings); 254f7c2983eSAxel Dörfler _RestoreWindowFrame(settings); 2556d519fd1SStephan Aßmus 2566d519fd1SStephan Aßmus fPackageInfoView->SetPackage(package); 25763975654SStephan Aßmus 25863975654SStephan Aßmus _InitWorkerThreads(); 2596d519fd1SStephan Aßmus } 2606d519fd1SStephan Aßmus 2616d519fd1SStephan Aßmus 26204c9d578SStephan Aßmus MainWindow::~MainWindow() 26304c9d578SStephan Aßmus { 26404c9d578SStephan Aßmus BPackageRoster().StopWatching(this); 26504c9d578SStephan Aßmus 26604c9d578SStephan Aßmus fTerminating = true; 26705bffa62SStephan Aßmus if (fModelWorker >= 0) 26804c9d578SStephan Aßmus wait_for_thread(fModelWorker, NULL); 26904c9d578SStephan Aßmus 27004c9d578SStephan Aßmus delete_sem(fPendingActionsSem); 27105bffa62SStephan Aßmus if (fPendingActionsWorker >= 0) 27204c9d578SStephan Aßmus wait_for_thread(fPendingActionsWorker, NULL); 27304c9d578SStephan Aßmus 27404c9d578SStephan Aßmus delete_sem(fPackageToPopulateSem); 27505bffa62SStephan Aßmus if (fPopulatePackageWorker >= 0) 27604c9d578SStephan Aßmus wait_for_thread(fPopulatePackageWorker, NULL); 277d5ef985eSStephan Aßmus 27872fff6d3SJulian Harnath delete_sem(fNewPackagesToShowSem); 27972fff6d3SJulian Harnath delete_sem(fShowPackagesAcknowledgeSem); 28072fff6d3SJulian Harnath if (fShowPackagesWorker >= 0) 28172fff6d3SJulian Harnath wait_for_thread(fShowPackagesWorker, NULL); 28272fff6d3SJulian Harnath 283d5ef985eSStephan Aßmus if (fScreenshotWindow != NULL && fScreenshotWindow->Lock()) 284d5ef985eSStephan Aßmus fScreenshotWindow->Quit(); 28504c9d578SStephan Aßmus } 28604c9d578SStephan Aßmus 28704c9d578SStephan Aßmus 28804c9d578SStephan Aßmus bool 28904c9d578SStephan Aßmus MainWindow::QuitRequested() 29004c9d578SStephan Aßmus { 29104c9d578SStephan Aßmus BMessage settings; 29204c9d578SStephan Aßmus StoreSettings(settings); 29304c9d578SStephan Aßmus 29404c9d578SStephan Aßmus BMessage message(MSG_MAIN_WINDOW_CLOSED); 29504c9d578SStephan Aßmus message.AddMessage("window settings", &settings); 29604c9d578SStephan Aßmus 29704c9d578SStephan Aßmus be_app->PostMessage(&message); 29804c9d578SStephan Aßmus 29904c9d578SStephan Aßmus return true; 30004c9d578SStephan Aßmus } 30104c9d578SStephan Aßmus 30204c9d578SStephan Aßmus 30304c9d578SStephan Aßmus void 30404c9d578SStephan Aßmus MainWindow::MessageReceived(BMessage* message) 30504c9d578SStephan Aßmus { 30604c9d578SStephan Aßmus switch (message->what) { 30704c9d578SStephan Aßmus case MSG_MODEL_WORKER_DONE: 30804c9d578SStephan Aßmus { 30904c9d578SStephan Aßmus fModelWorker = B_BAD_THREAD_ID; 31004c9d578SStephan Aßmus _AdoptModel(); 311b965ce70SHumdinger _UpdateAvailableRepositories(); 312125d42d9SJulian Harnath fWorkStatusView->SetIdle(); 31304c9d578SStephan Aßmus break; 31404c9d578SStephan Aßmus } 31504c9d578SStephan Aßmus case B_SIMPLE_DATA: 31604c9d578SStephan Aßmus case B_REFS_RECEIVED: 31704c9d578SStephan Aßmus // TODO: ? 31804c9d578SStephan Aßmus break; 31904c9d578SStephan Aßmus 32004c9d578SStephan Aßmus case B_PACKAGE_UPDATE: 32104c9d578SStephan Aßmus // TODO: We should do a more selective update depending on the 32204c9d578SStephan Aßmus // "event", "location", and "change count" fields! 32304c9d578SStephan Aßmus _StartRefreshWorker(false); 32404c9d578SStephan Aßmus break; 32504c9d578SStephan Aßmus 3265bf2b6ebSBrian Hill case MSG_REFRESH_REPOS: 32704c9d578SStephan Aßmus _StartRefreshWorker(true); 32804c9d578SStephan Aßmus break; 32904c9d578SStephan Aßmus 3305bf2b6ebSBrian Hill case MSG_MANAGE_REPOS: 3315bf2b6ebSBrian Hill be_roster->Launch("application/x-vnd.Haiku-Repositories"); 3325bf2b6ebSBrian Hill break; 3335bf2b6ebSBrian Hill 334d144f952SAugustin Cavalier case MSG_SOFTWARE_UPDATER: 335d144f952SAugustin Cavalier be_roster->Launch("application/x-vnd.haiku-softwareupdater"); 336d144f952SAugustin Cavalier break; 337d144f952SAugustin Cavalier 33804c9d578SStephan Aßmus case MSG_LOG_IN: 3391bbda92dSStephan Aßmus _OpenLoginWindow(BMessage()); 34004c9d578SStephan Aßmus break; 34104c9d578SStephan Aßmus 3428f03a0f9SStephan Aßmus case MSG_LOG_OUT: 3438f03a0f9SStephan Aßmus fModel.SetUsername(""); 3448f03a0f9SStephan Aßmus break; 3458f03a0f9SStephan Aßmus 3468f03a0f9SStephan Aßmus case MSG_AUTHORIZATION_CHANGED: 3478f03a0f9SStephan Aßmus _UpdateAuthorization(); 3488f03a0f9SStephan Aßmus break; 3498f03a0f9SStephan Aßmus 3504fade61fSStephan Aßmus case MSG_SHOW_FEATURED_PACKAGES: 351*e00a489bSAugustin Cavalier // check to see if we aren't already on the current tab 352*e00a489bSAugustin Cavalier if (fListTabs->Selection() == 353*e00a489bSAugustin Cavalier (fModel.ShowFeaturedPackages() ? 0 : 1)) 354*e00a489bSAugustin Cavalier break; 3554fade61fSStephan Aßmus { 3564fade61fSStephan Aßmus BAutolock locker(fModel.Lock()); 3574fade61fSStephan Aßmus fModel.SetShowFeaturedPackages( 358*e00a489bSAugustin Cavalier fListTabs->Selection() == 0); 3594fade61fSStephan Aßmus } 3604fade61fSStephan Aßmus _AdoptModel(); 3614fade61fSStephan Aßmus break; 3624fade61fSStephan Aßmus 363fdec4227SStephan Aßmus case MSG_SHOW_AVAILABLE_PACKAGES: 364fdec4227SStephan Aßmus { 365fdec4227SStephan Aßmus BAutolock locker(fModel.Lock()); 366fdec4227SStephan Aßmus fModel.SetShowAvailablePackages( 367fdec4227SStephan Aßmus !fModel.ShowAvailablePackages()); 368fdec4227SStephan Aßmus } 369fdec4227SStephan Aßmus _AdoptModel(); 370fdec4227SStephan Aßmus break; 371fdec4227SStephan Aßmus 372fdec4227SStephan Aßmus case MSG_SHOW_INSTALLED_PACKAGES: 373fdec4227SStephan Aßmus { 374fdec4227SStephan Aßmus BAutolock locker(fModel.Lock()); 375fdec4227SStephan Aßmus fModel.SetShowInstalledPackages( 376fdec4227SStephan Aßmus !fModel.ShowInstalledPackages()); 377fdec4227SStephan Aßmus } 378fdec4227SStephan Aßmus _AdoptModel(); 379fdec4227SStephan Aßmus break; 380fdec4227SStephan Aßmus 38104c9d578SStephan Aßmus case MSG_SHOW_SOURCE_PACKAGES: 38204c9d578SStephan Aßmus { 38304c9d578SStephan Aßmus BAutolock locker(fModel.Lock()); 38404c9d578SStephan Aßmus fModel.SetShowSourcePackages(!fModel.ShowSourcePackages()); 38504c9d578SStephan Aßmus } 38604c9d578SStephan Aßmus _AdoptModel(); 38704c9d578SStephan Aßmus break; 38804c9d578SStephan Aßmus 38904c9d578SStephan Aßmus case MSG_SHOW_DEVELOP_PACKAGES: 39004c9d578SStephan Aßmus { 39104c9d578SStephan Aßmus BAutolock locker(fModel.Lock()); 39204c9d578SStephan Aßmus fModel.SetShowDevelopPackages(!fModel.ShowDevelopPackages()); 39304c9d578SStephan Aßmus } 39404c9d578SStephan Aßmus _AdoptModel(); 39504c9d578SStephan Aßmus break; 39604c9d578SStephan Aßmus 397a9edb9bfSAndrew Lindesay // this may be triggered by, for example, a user rating being added 398a9edb9bfSAndrew Lindesay // or having been altered. 399a9edb9bfSAndrew Lindesay case MSG_SERVER_DATA_CHANGED: 400a9edb9bfSAndrew Lindesay { 401a9edb9bfSAndrew Lindesay BString name; 402a9edb9bfSAndrew Lindesay if (message->FindString("name", &name) == B_OK) { 403a9edb9bfSAndrew Lindesay BAutolock locker(fModel.Lock()); 404a9edb9bfSAndrew Lindesay if (fPackageInfoView->Package()->Name() == name) { 405a9edb9bfSAndrew Lindesay _PopulatePackageAsync(true); 406a9edb9bfSAndrew Lindesay } else { 407a9edb9bfSAndrew Lindesay if (Logger::IsDebugEnabled()) { 408a9edb9bfSAndrew Lindesay printf("pkg [%s] is updated on the server, but is " 409a9edb9bfSAndrew Lindesay "not selected so will not be updated.\n", 410a9edb9bfSAndrew Lindesay name.String()); 411a9edb9bfSAndrew Lindesay } 412a9edb9bfSAndrew Lindesay } 413a9edb9bfSAndrew Lindesay } 414a9edb9bfSAndrew Lindesay break; 415a9edb9bfSAndrew Lindesay } 416a9edb9bfSAndrew Lindesay 41704c9d578SStephan Aßmus case MSG_PACKAGE_SELECTED: 41804c9d578SStephan Aßmus { 41972992391SStephan Aßmus BString name; 42072992391SStephan Aßmus if (message->FindString("name", &name) == B_OK) { 42175ba9dbfSStephan Aßmus BAutolock locker(fModel.Lock()); 42204c9d578SStephan Aßmus int count = fVisiblePackages.CountItems(); 42304c9d578SStephan Aßmus for (int i = 0; i < count; i++) { 42404c9d578SStephan Aßmus const PackageInfoRef& package 42504c9d578SStephan Aßmus = fVisiblePackages.ItemAtFast(i); 42672992391SStephan Aßmus if (package.Get() != NULL && package->Name() == name) { 42775ba9dbfSStephan Aßmus locker.Unlock(); 42804c9d578SStephan Aßmus _AdoptPackage(package); 42904c9d578SStephan Aßmus break; 43004c9d578SStephan Aßmus } 43104c9d578SStephan Aßmus } 43204c9d578SStephan Aßmus } else { 43304c9d578SStephan Aßmus _ClearPackage(); 43404c9d578SStephan Aßmus } 43504c9d578SStephan Aßmus break; 43604c9d578SStephan Aßmus } 43704c9d578SStephan Aßmus 43804c9d578SStephan Aßmus case MSG_CATEGORY_SELECTED: 43904c9d578SStephan Aßmus { 44004c9d578SStephan Aßmus BString name; 44104c9d578SStephan Aßmus if (message->FindString("name", &name) != B_OK) 44204c9d578SStephan Aßmus name = ""; 44304c9d578SStephan Aßmus { 44404c9d578SStephan Aßmus BAutolock locker(fModel.Lock()); 44504c9d578SStephan Aßmus fModel.SetCategory(name); 44604c9d578SStephan Aßmus } 44704c9d578SStephan Aßmus _AdoptModel(); 44804c9d578SStephan Aßmus break; 44904c9d578SStephan Aßmus } 45004c9d578SStephan Aßmus 45104c9d578SStephan Aßmus case MSG_DEPOT_SELECTED: 45204c9d578SStephan Aßmus { 45304c9d578SStephan Aßmus BString name; 45404c9d578SStephan Aßmus if (message->FindString("name", &name) != B_OK) 45504c9d578SStephan Aßmus name = ""; 45604c9d578SStephan Aßmus { 45704c9d578SStephan Aßmus BAutolock locker(fModel.Lock()); 45804c9d578SStephan Aßmus fModel.SetDepot(name); 45904c9d578SStephan Aßmus } 46004c9d578SStephan Aßmus _AdoptModel(); 461b965ce70SHumdinger _UpdateAvailableRepositories(); 46204c9d578SStephan Aßmus break; 46304c9d578SStephan Aßmus } 46404c9d578SStephan Aßmus 46504c9d578SStephan Aßmus case MSG_SEARCH_TERMS_MODIFIED: 46604c9d578SStephan Aßmus { 46704c9d578SStephan Aßmus // TODO: Do this with a delay! 46804c9d578SStephan Aßmus BString searchTerms; 46904c9d578SStephan Aßmus if (message->FindString("search terms", &searchTerms) != B_OK) 47004c9d578SStephan Aßmus searchTerms = ""; 47104c9d578SStephan Aßmus { 47204c9d578SStephan Aßmus BAutolock locker(fModel.Lock()); 47304c9d578SStephan Aßmus fModel.SetSearchTerms(searchTerms); 47404c9d578SStephan Aßmus } 47504c9d578SStephan Aßmus _AdoptModel(); 47604c9d578SStephan Aßmus break; 47704c9d578SStephan Aßmus } 47804c9d578SStephan Aßmus 479da651104SStephan Aßmus case MSG_PACKAGE_CHANGED: 48004c9d578SStephan Aßmus { 48104c9d578SStephan Aßmus PackageInfo* info; 48204c9d578SStephan Aßmus if (message->FindPointer("package", (void**)&info) == B_OK) { 48304c9d578SStephan Aßmus PackageInfoRef ref(info, true); 484da651104SStephan Aßmus uint32 changes; 485da651104SStephan Aßmus if (message->FindUInt32("changes", &changes) != B_OK) 486da651104SStephan Aßmus changes = 0; 487da651104SStephan Aßmus if ((changes & PKG_CHANGED_STATE) != 0) { 48804c9d578SStephan Aßmus BAutolock locker(fModel.Lock()); 48904c9d578SStephan Aßmus fModel.SetPackageState(ref, ref->State()); 49004c9d578SStephan Aßmus } 49157e51fffSStephan Aßmus 49257e51fffSStephan Aßmus // Asynchronous updates to the package information 49357e51fffSStephan Aßmus // can mean that the package needs to be added or 49457e51fffSStephan Aßmus // removed to/from the visible packages when the current 49557e51fffSStephan Aßmus // filter parameters are re-evaluated on this package. 49657e51fffSStephan Aßmus bool wasVisible = fVisiblePackages.Contains(ref); 49757e51fffSStephan Aßmus bool isVisible; 49857e51fffSStephan Aßmus { 499da651104SStephan Aßmus BAutolock locker(fModel.Lock()); 5000c6df5d5SStephan Aßmus // The package didn't get a chance yet to be in the 5010c6df5d5SStephan Aßmus // visible package list 50239f49f70SJulian Harnath isVisible = fModel.MatchesFilter(ref); 50357e51fffSStephan Aßmus 50457e51fffSStephan Aßmus // Transfer this single package, otherwise we miss 50557e51fffSStephan Aßmus // other packages if they appear or disappear along 50657e51fffSStephan Aßmus // with this one before receive a notification for 50757e51fffSStephan Aßmus // them. 50857e51fffSStephan Aßmus if (isVisible) { 50957e51fffSStephan Aßmus fVisiblePackages.Add(ref); 51057e51fffSStephan Aßmus } else if (wasVisible) 51157e51fffSStephan Aßmus fVisiblePackages.Remove(ref); 51257e51fffSStephan Aßmus } 51357e51fffSStephan Aßmus 51457e51fffSStephan Aßmus if (wasVisible != isVisible) { 51557e51fffSStephan Aßmus if (!isVisible) { 51657e51fffSStephan Aßmus fPackageListView->RemovePackage(ref); 51757e51fffSStephan Aßmus fFeaturedPackagesView->RemovePackage(ref); 51857e51fffSStephan Aßmus } else { 51957e51fffSStephan Aßmus fPackageListView->AddPackage(ref); 52057e51fffSStephan Aßmus if (ref->IsProminent()) 521da651104SStephan Aßmus fFeaturedPackagesView->AddPackage(ref); 522da651104SStephan Aßmus } 523da651104SStephan Aßmus } 5244e6fbe03SJulian Harnath 5254e6fbe03SJulian Harnath if (!fSinglePackageMode && (changes & PKG_CHANGED_STATE) != 0) 5264e6fbe03SJulian Harnath fWorkStatusView->PackageStatusChanged(ref); 52757e51fffSStephan Aßmus } 52804c9d578SStephan Aßmus break; 52904c9d578SStephan Aßmus } 53004c9d578SStephan Aßmus 53104c9d578SStephan Aßmus case MSG_RATE_PACKAGE: 5321bbda92dSStephan Aßmus _RatePackage(); 53304c9d578SStephan Aßmus break; 53404c9d578SStephan Aßmus 535d5ef985eSStephan Aßmus case MSG_SHOW_SCREENSHOT: 536d5ef985eSStephan Aßmus _ShowScreenshot(); 537d5ef985eSStephan Aßmus break; 538d5ef985eSStephan Aßmus 539125d42d9SJulian Harnath case MSG_PACKAGE_WORKER_BUSY: 540125d42d9SJulian Harnath { 541125d42d9SJulian Harnath BString reason; 542125d42d9SJulian Harnath status_t status = message->FindString("reason", &reason); 543125d42d9SJulian Harnath if (status != B_OK) 544125d42d9SJulian Harnath break; 545d78bfd8dSJulian Harnath if (!fSinglePackageMode) 546125d42d9SJulian Harnath fWorkStatusView->SetBusy(reason); 547125d42d9SJulian Harnath break; 548125d42d9SJulian Harnath } 549125d42d9SJulian Harnath 550125d42d9SJulian Harnath case MSG_PACKAGE_WORKER_IDLE: 551d78bfd8dSJulian Harnath if (!fSinglePackageMode) 552125d42d9SJulian Harnath fWorkStatusView->SetIdle(); 553125d42d9SJulian Harnath break; 554125d42d9SJulian Harnath 55572fff6d3SJulian Harnath case MSG_ADD_VISIBLE_PACKAGES: 55672fff6d3SJulian Harnath { 55772fff6d3SJulian Harnath struct SemaphoreReleaser { 55872fff6d3SJulian Harnath SemaphoreReleaser(sem_id semaphore) 55972fff6d3SJulian Harnath : 56072fff6d3SJulian Harnath fSemaphore(semaphore) 56172fff6d3SJulian Harnath { } 56272fff6d3SJulian Harnath 56372fff6d3SJulian Harnath ~SemaphoreReleaser() { release_sem(fSemaphore); } 56472fff6d3SJulian Harnath 56572fff6d3SJulian Harnath sem_id fSemaphore; 56672fff6d3SJulian Harnath }; 56772fff6d3SJulian Harnath 56872fff6d3SJulian Harnath // Make sure acknowledge semaphore is released even on error, 56972fff6d3SJulian Harnath // so the worker thread won't be blocked 57072fff6d3SJulian Harnath SemaphoreReleaser acknowledger(fShowPackagesAcknowledgeSem); 57172fff6d3SJulian Harnath 57272fff6d3SJulian Harnath int32 numPackages = 0; 57372fff6d3SJulian Harnath type_code unused; 57472fff6d3SJulian Harnath status_t status = message->GetInfo("package_ref", &unused, 57572fff6d3SJulian Harnath &numPackages); 57672fff6d3SJulian Harnath if (status != B_OK || numPackages == 0) 57772fff6d3SJulian Harnath break; 57872fff6d3SJulian Harnath 57972fff6d3SJulian Harnath int32 listID = 0; 58072fff6d3SJulian Harnath status = message->FindInt32("list_id", &listID); 58172fff6d3SJulian Harnath if (status != B_OK) 58272fff6d3SJulian Harnath break; 58372fff6d3SJulian Harnath if (listID != atomic_get(&fPackagesToShowListID)) { 58472fff6d3SJulian Harnath // list is outdated, ignore 58572fff6d3SJulian Harnath break; 58672fff6d3SJulian Harnath } 58772fff6d3SJulian Harnath 58872fff6d3SJulian Harnath for (int i = 0; i < numPackages; i++) { 58972fff6d3SJulian Harnath PackageInfo* packageRaw = NULL; 59072fff6d3SJulian Harnath status = message->FindPointer("package_ref", i, 59172fff6d3SJulian Harnath (void**)&packageRaw); 59272fff6d3SJulian Harnath if (status != B_OK) 59372fff6d3SJulian Harnath break; 59472fff6d3SJulian Harnath PackageInfoRef package(packageRaw, true); 59572fff6d3SJulian Harnath 59672fff6d3SJulian Harnath fPackageListView->AddPackage(package); 59772fff6d3SJulian Harnath if (package->IsProminent()) 59872fff6d3SJulian Harnath fFeaturedPackagesView->AddPackage(package); 59972fff6d3SJulian Harnath } 60072fff6d3SJulian Harnath break; 60172fff6d3SJulian Harnath } 60272fff6d3SJulian Harnath 60372fff6d3SJulian Harnath case MSG_UPDATE_SELECTED_PACKAGE: 60472fff6d3SJulian Harnath { 60572fff6d3SJulian Harnath const PackageInfoRef& selectedPackage = fPackageInfoView->Package(); 60672fff6d3SJulian Harnath fFeaturedPackagesView->SelectPackage(selectedPackage, true); 60772fff6d3SJulian Harnath fPackageListView->SelectPackage(selectedPackage); 60872fff6d3SJulian Harnath 60972fff6d3SJulian Harnath AutoLocker<BLocker> modelLocker(fModel.Lock()); 61072fff6d3SJulian Harnath if (!fVisiblePackages.Contains(fPackageInfoView->Package())) 61172fff6d3SJulian Harnath fPackageInfoView->Clear(); 61272fff6d3SJulian Harnath break; 61372fff6d3SJulian Harnath } 61472fff6d3SJulian Harnath 61504c9d578SStephan Aßmus default: 61604c9d578SStephan Aßmus BWindow::MessageReceived(message); 61704c9d578SStephan Aßmus break; 61804c9d578SStephan Aßmus } 61904c9d578SStephan Aßmus } 62004c9d578SStephan Aßmus 62104c9d578SStephan Aßmus 62204c9d578SStephan Aßmus void 62304c9d578SStephan Aßmus MainWindow::StoreSettings(BMessage& settings) const 62404c9d578SStephan Aßmus { 625f7c2983eSAxel Dörfler settings.AddRect(_WindowFrameName(), Frame()); 626f7c2983eSAxel Dörfler if (!fSinglePackageMode) { 62704c9d578SStephan Aßmus settings.AddRect("window frame", Frame()); 62804c9d578SStephan Aßmus 62904c9d578SStephan Aßmus BMessage columnSettings; 63004c9d578SStephan Aßmus fPackageListView->SaveState(&columnSettings); 63104c9d578SStephan Aßmus 63204c9d578SStephan Aßmus settings.AddMessage("column settings", &columnSettings); 63304c9d578SStephan Aßmus 6342997e05bSStephan Aßmus settings.AddBool("show featured packages", 6352997e05bSStephan Aßmus fModel.ShowFeaturedPackages()); 6362997e05bSStephan Aßmus settings.AddBool("show available packages", 6372997e05bSStephan Aßmus fModel.ShowAvailablePackages()); 6382997e05bSStephan Aßmus settings.AddBool("show installed packages", 6392997e05bSStephan Aßmus fModel.ShowInstalledPackages()); 64004c9d578SStephan Aßmus settings.AddBool("show develop packages", fModel.ShowDevelopPackages()); 64104c9d578SStephan Aßmus settings.AddBool("show source packages", fModel.ShowSourcePackages()); 6426d519fd1SStephan Aßmus } 6438f03a0f9SStephan Aßmus 6448f03a0f9SStephan Aßmus settings.AddString("username", fModel.Username()); 64504c9d578SStephan Aßmus } 64604c9d578SStephan Aßmus 64704c9d578SStephan Aßmus 64804c9d578SStephan Aßmus void 64904c9d578SStephan Aßmus MainWindow::PackageChanged(const PackageInfoEvent& event) 65004c9d578SStephan Aßmus { 651a9edb9bfSAndrew Lindesay uint32 watchedChanges = PKG_CHANGED_STATE | PKG_CHANGED_PROMINENCE; 652a9edb9bfSAndrew Lindesay if ((event.Changes() & watchedChanges) != 0) { 65304c9d578SStephan Aßmus PackageInfoRef ref(event.Package()); 654da651104SStephan Aßmus BMessage message(MSG_PACKAGE_CHANGED); 65504c9d578SStephan Aßmus message.AddPointer("package", ref.Get()); 656da651104SStephan Aßmus message.AddUInt32("changes", event.Changes()); 65704c9d578SStephan Aßmus ref.Detach(); 65804c9d578SStephan Aßmus // reference needs to be released by MessageReceived(); 65904c9d578SStephan Aßmus PostMessage(&message); 66004c9d578SStephan Aßmus } 66104c9d578SStephan Aßmus } 66204c9d578SStephan Aßmus 66304c9d578SStephan Aßmus 66404c9d578SStephan Aßmus status_t 66504c9d578SStephan Aßmus MainWindow::SchedulePackageActions(PackageActionList& list) 66604c9d578SStephan Aßmus { 66704c9d578SStephan Aßmus AutoLocker<BLocker> lock(&fPendingActionsLock); 66804c9d578SStephan Aßmus for (int32 i = 0; i < list.CountItems(); i++) { 66904c9d578SStephan Aßmus if (!fPendingActions.Add(list.ItemAtFast(i))) 67004c9d578SStephan Aßmus return B_NO_MEMORY; 67104c9d578SStephan Aßmus } 67204c9d578SStephan Aßmus 67304c9d578SStephan Aßmus return release_sem_etc(fPendingActionsSem, list.CountItems(), 0); 67404c9d578SStephan Aßmus } 67504c9d578SStephan Aßmus 67604c9d578SStephan Aßmus 67704c9d578SStephan Aßmus Model* 67804c9d578SStephan Aßmus MainWindow::GetModel() 67904c9d578SStephan Aßmus { 68004c9d578SStephan Aßmus return &fModel; 68104c9d578SStephan Aßmus } 68204c9d578SStephan Aßmus 68304c9d578SStephan Aßmus 68404c9d578SStephan Aßmus void 68504c9d578SStephan Aßmus MainWindow::_BuildMenu(BMenuBar* menuBar) 68604c9d578SStephan Aßmus { 68704c9d578SStephan Aßmus BMenu* menu = new BMenu(B_TRANSLATE("Tools")); 6885bf2b6ebSBrian Hill menu->AddItem(new BMenuItem(B_TRANSLATE("Refresh repositories"), 6895bf2b6ebSBrian Hill new BMessage(MSG_REFRESH_REPOS))); 690d7f78130SHumdinger menu->AddItem(new BMenuItem(B_TRANSLATE("Manage repositories" 691d7f78130SHumdinger B_UTF8_ELLIPSIS), new BMessage(MSG_MANAGE_REPOS))); 692d144f952SAugustin Cavalier menu->AddItem(new BMenuItem(B_TRANSLATE("Check for updates" 693d144f952SAugustin Cavalier B_UTF8_ELLIPSIS), new BMessage(MSG_SOFTWARE_UPDATER))); 694e0a26dceSStephan Aßmus 69504c9d578SStephan Aßmus menuBar->AddItem(menu); 69604c9d578SStephan Aßmus 697b965ce70SHumdinger fRepositoryMenu = new BMenu(B_TRANSLATE("Repositories")); 698b965ce70SHumdinger menuBar->AddItem(fRepositoryMenu); 699b965ce70SHumdinger 7004fade61fSStephan Aßmus menu = new BMenu(B_TRANSLATE("Show")); 7014fade61fSStephan Aßmus 702fdec4227SStephan Aßmus fShowAvailablePackagesItem = new BMenuItem( 7034fade61fSStephan Aßmus B_TRANSLATE("Available packages"), 704fdec4227SStephan Aßmus new BMessage(MSG_SHOW_AVAILABLE_PACKAGES)); 705fdec4227SStephan Aßmus menu->AddItem(fShowAvailablePackagesItem); 706fdec4227SStephan Aßmus 707fdec4227SStephan Aßmus fShowInstalledPackagesItem = new BMenuItem( 7084fade61fSStephan Aßmus B_TRANSLATE("Installed packages"), 709fdec4227SStephan Aßmus new BMessage(MSG_SHOW_INSTALLED_PACKAGES)); 710fdec4227SStephan Aßmus menu->AddItem(fShowInstalledPackagesItem); 711fdec4227SStephan Aßmus 712fdec4227SStephan Aßmus menu->AddSeparatorItem(); 713fdec4227SStephan Aßmus 714fdec4227SStephan Aßmus fShowDevelopPackagesItem = new BMenuItem( 7154fade61fSStephan Aßmus B_TRANSLATE("Develop packages"), 716fdec4227SStephan Aßmus new BMessage(MSG_SHOW_DEVELOP_PACKAGES)); 717fdec4227SStephan Aßmus menu->AddItem(fShowDevelopPackagesItem); 718fdec4227SStephan Aßmus 719fdec4227SStephan Aßmus fShowSourcePackagesItem = new BMenuItem( 7204fade61fSStephan Aßmus B_TRANSLATE("Source packages"), 721fdec4227SStephan Aßmus new BMessage(MSG_SHOW_SOURCE_PACKAGES)); 722fdec4227SStephan Aßmus menu->AddItem(fShowSourcePackagesItem); 723fdec4227SStephan Aßmus 724fdec4227SStephan Aßmus menuBar->AddItem(menu); 72504c9d578SStephan Aßmus } 72604c9d578SStephan Aßmus 72704c9d578SStephan Aßmus 72804c9d578SStephan Aßmus void 729e0a26dceSStephan Aßmus MainWindow::_BuildUserMenu(BMenuBar* menuBar) 730e0a26dceSStephan Aßmus { 731e0a26dceSStephan Aßmus fUserMenu = new BMenu(B_TRANSLATE("Not logged in")); 732e0a26dceSStephan Aßmus 733e0a26dceSStephan Aßmus fLogInItem = new BMenuItem(B_TRANSLATE("Log in" B_UTF8_ELLIPSIS), 734e0a26dceSStephan Aßmus new BMessage(MSG_LOG_IN)); 735e0a26dceSStephan Aßmus fUserMenu->AddItem(fLogInItem); 736e0a26dceSStephan Aßmus 737e0a26dceSStephan Aßmus fLogOutItem = new BMenuItem(B_TRANSLATE("Log out"), 738e0a26dceSStephan Aßmus new BMessage(MSG_LOG_OUT)); 739e0a26dceSStephan Aßmus fUserMenu->AddItem(fLogOutItem); 740e0a26dceSStephan Aßmus 741e0a26dceSStephan Aßmus menuBar->AddItem(fUserMenu); 742e0a26dceSStephan Aßmus } 743e0a26dceSStephan Aßmus 744e0a26dceSStephan Aßmus 745e0a26dceSStephan Aßmus void 746f7c2983eSAxel Dörfler MainWindow::_RestoreUserName(const BMessage& settings) 747f7c2983eSAxel Dörfler { 748f7c2983eSAxel Dörfler BString username; 749f7c2983eSAxel Dörfler if (settings.FindString("username", &username) == B_OK 750f7c2983eSAxel Dörfler && username.Length() > 0) { 751f7c2983eSAxel Dörfler fModel.SetUsername(username); 752f7c2983eSAxel Dörfler } 753f7c2983eSAxel Dörfler } 754f7c2983eSAxel Dörfler 755f7c2983eSAxel Dörfler 756f7c2983eSAxel Dörfler const char* 757f7c2983eSAxel Dörfler MainWindow::_WindowFrameName() const 758f7c2983eSAxel Dörfler { 759f7c2983eSAxel Dörfler if (fSinglePackageMode) 760f7c2983eSAxel Dörfler return "small window frame"; 761f7c2983eSAxel Dörfler 762f7c2983eSAxel Dörfler return "window frame"; 763f7c2983eSAxel Dörfler } 764f7c2983eSAxel Dörfler 765f7c2983eSAxel Dörfler 766f7c2983eSAxel Dörfler void 767f7c2983eSAxel Dörfler MainWindow::_RestoreWindowFrame(const BMessage& settings) 768f7c2983eSAxel Dörfler { 769f7c2983eSAxel Dörfler BRect frame = Frame(); 770f7c2983eSAxel Dörfler 771f7c2983eSAxel Dörfler BRect windowFrame; 772f7c2983eSAxel Dörfler bool fromSettings = false; 773f7c2983eSAxel Dörfler if (settings.FindRect(_WindowFrameName(), &windowFrame) == B_OK) { 774f7c2983eSAxel Dörfler frame = windowFrame; 775f7c2983eSAxel Dörfler fromSettings = true; 776f7c2983eSAxel Dörfler } else if (!fSinglePackageMode) { 777f7c2983eSAxel Dörfler // Resize to occupy a certain screen size 778f7c2983eSAxel Dörfler BRect screenFrame = BScreen(this).Frame(); 779f7c2983eSAxel Dörfler float width = frame.Width(); 780f7c2983eSAxel Dörfler float height = frame.Height(); 781f7c2983eSAxel Dörfler if (width < screenFrame.Width() * .666f 782f7c2983eSAxel Dörfler && height < screenFrame.Height() * .666f) { 783f7c2983eSAxel Dörfler frame.bottom = frame.top + screenFrame.Height() * .666f; 784f7c2983eSAxel Dörfler frame.right = frame.left 785f7c2983eSAxel Dörfler + std::min(screenFrame.Width() * .666f, height * 7 / 5); 786f7c2983eSAxel Dörfler } 787f7c2983eSAxel Dörfler } 788f7c2983eSAxel Dörfler 789f7c2983eSAxel Dörfler MoveTo(frame.LeftTop()); 790f7c2983eSAxel Dörfler ResizeTo(frame.Width(), frame.Height()); 791f7c2983eSAxel Dörfler 792f7c2983eSAxel Dörfler if (fromSettings) 7938e96ec34SAxel Dörfler MoveOnScreen(); 794f7c2983eSAxel Dörfler else 795f7c2983eSAxel Dörfler CenterOnScreen(); 796f7c2983eSAxel Dörfler } 797f7c2983eSAxel Dörfler 798f7c2983eSAxel Dörfler 799f7c2983eSAxel Dörfler void 80063975654SStephan Aßmus MainWindow::_InitWorkerThreads() 80163975654SStephan Aßmus { 80263975654SStephan Aßmus fPendingActionsSem = create_sem(0, "PendingPackageActions"); 80363975654SStephan Aßmus if (fPendingActionsSem >= 0) { 80463975654SStephan Aßmus fPendingActionsWorker = spawn_thread(&_PackageActionWorker, 80563975654SStephan Aßmus "Planet Express", B_NORMAL_PRIORITY, this); 80663975654SStephan Aßmus if (fPendingActionsWorker >= 0) 80763975654SStephan Aßmus resume_thread(fPendingActionsWorker); 80809f82905SStephan Aßmus } else 80909f82905SStephan Aßmus fPendingActionsWorker = -1; 81063975654SStephan Aßmus 81163975654SStephan Aßmus fPackageToPopulateSem = create_sem(0, "PopulatePackage"); 81263975654SStephan Aßmus if (fPackageToPopulateSem >= 0) { 81363975654SStephan Aßmus fPopulatePackageWorker = spawn_thread(&_PopulatePackageWorker, 81463975654SStephan Aßmus "Package Populator", B_NORMAL_PRIORITY, this); 81563975654SStephan Aßmus if (fPopulatePackageWorker >= 0) 81663975654SStephan Aßmus resume_thread(fPopulatePackageWorker); 81709f82905SStephan Aßmus } else 81809f82905SStephan Aßmus fPopulatePackageWorker = -1; 81972fff6d3SJulian Harnath 82072fff6d3SJulian Harnath fNewPackagesToShowSem = create_sem(0, "ShowPackages"); 82172fff6d3SJulian Harnath fShowPackagesAcknowledgeSem = create_sem(0, "ShowPackagesAck"); 82272fff6d3SJulian Harnath if (fNewPackagesToShowSem >= 0 && fShowPackagesAcknowledgeSem >= 0) { 82372fff6d3SJulian Harnath fShowPackagesWorker = spawn_thread(&_PackagesToShowWorker, 82472fff6d3SJulian Harnath "Good news everyone", B_NORMAL_PRIORITY, this); 82572fff6d3SJulian Harnath if (fShowPackagesWorker >= 0) 82672fff6d3SJulian Harnath resume_thread(fShowPackagesWorker); 82772fff6d3SJulian Harnath } else 82872fff6d3SJulian Harnath fShowPackagesWorker = -1; 82963975654SStephan Aßmus } 83063975654SStephan Aßmus 83163975654SStephan Aßmus 83263975654SStephan Aßmus void 83304c9d578SStephan Aßmus MainWindow::_AdoptModel() 83404c9d578SStephan Aßmus { 83504c9d578SStephan Aßmus fVisiblePackages = fModel.CreatePackageList(); 83604c9d578SStephan Aßmus 83772fff6d3SJulian Harnath { 83872fff6d3SJulian Harnath AutoLocker<BLocker> modelLocker(fModel.Lock()); 83972fff6d3SJulian Harnath AutoLocker<BLocker> listLocker(fPackagesToShowListLock); 84072fff6d3SJulian Harnath fPackagesToShowList = fVisiblePackages; 84172fff6d3SJulian Harnath atomic_add(&fPackagesToShowListID, 1); 84272fff6d3SJulian Harnath } 84372fff6d3SJulian Harnath 8444b930ccaSStephan Aßmus fFeaturedPackagesView->Clear(); 84504c9d578SStephan Aßmus fPackageListView->Clear(); 8464b930ccaSStephan Aßmus 84772fff6d3SJulian Harnath release_sem(fNewPackagesToShowSem); 84804c9d578SStephan Aßmus 84904c9d578SStephan Aßmus BAutolock locker(fModel.Lock()); 850fdec4227SStephan Aßmus fShowAvailablePackagesItem->SetMarked(fModel.ShowAvailablePackages()); 851fdec4227SStephan Aßmus fShowInstalledPackagesItem->SetMarked(fModel.ShowInstalledPackages()); 852fdec4227SStephan Aßmus fShowSourcePackagesItem->SetMarked(fModel.ShowSourcePackages()); 853fdec4227SStephan Aßmus fShowDevelopPackagesItem->SetMarked(fModel.ShowDevelopPackages()); 854da651104SStephan Aßmus 855b965ce70SHumdinger if (fModel.ShowFeaturedPackages()) 856*e00a489bSAugustin Cavalier fListTabs->Select(0); 8574fade61fSStephan Aßmus else 858*e00a489bSAugustin Cavalier fListTabs->Select(1); 859b965ce70SHumdinger 860b965ce70SHumdinger fFilterView->AdoptModel(fModel); 86104c9d578SStephan Aßmus } 86204c9d578SStephan Aßmus 86304c9d578SStephan Aßmus 86404c9d578SStephan Aßmus void 86504c9d578SStephan Aßmus MainWindow::_AdoptPackage(const PackageInfoRef& package) 86604c9d578SStephan Aßmus { 86775ba9dbfSStephan Aßmus { 86875ba9dbfSStephan Aßmus BAutolock locker(fModel.Lock()); 86904c9d578SStephan Aßmus fPackageInfoView->SetPackage(package); 8701986ab9fSStephan Aßmus 871664372abSStephan Aßmus if (fFeaturedPackagesView != NULL) 872664372abSStephan Aßmus fFeaturedPackagesView->SelectPackage(package); 8731986ab9fSStephan Aßmus if (fPackageListView != NULL) 8741986ab9fSStephan Aßmus fPackageListView->SelectPackage(package); 87575ba9dbfSStephan Aßmus } 87604c9d578SStephan Aßmus 877a9edb9bfSAndrew Lindesay _PopulatePackageAsync(false); 87804c9d578SStephan Aßmus } 87904c9d578SStephan Aßmus 88004c9d578SStephan Aßmus 88104c9d578SStephan Aßmus void 88204c9d578SStephan Aßmus MainWindow::_ClearPackage() 88304c9d578SStephan Aßmus { 88404c9d578SStephan Aßmus fPackageInfoView->Clear(); 88504c9d578SStephan Aßmus } 88604c9d578SStephan Aßmus 88704c9d578SStephan Aßmus 88804c9d578SStephan Aßmus void 88904c9d578SStephan Aßmus MainWindow::_RefreshRepositories(bool force) 89004c9d578SStephan Aßmus { 891448f707cSStephan Aßmus if (fSinglePackageMode) 892448f707cSStephan Aßmus return; 893448f707cSStephan Aßmus 89404c9d578SStephan Aßmus BPackageRoster roster; 89504c9d578SStephan Aßmus BStringList repositoryNames; 89604c9d578SStephan Aßmus 89704c9d578SStephan Aßmus status_t result = roster.GetRepositoryNames(repositoryNames); 89804c9d578SStephan Aßmus if (result != B_OK) 89904c9d578SStephan Aßmus return; 90004c9d578SStephan Aßmus 90104c9d578SStephan Aßmus DecisionProvider decisionProvider; 90204c9d578SStephan Aßmus JobStateListener listener; 90304c9d578SStephan Aßmus BContext context(decisionProvider, listener); 90404c9d578SStephan Aßmus 90504c9d578SStephan Aßmus BRepositoryCache cache; 90604c9d578SStephan Aßmus for (int32 i = 0; i < repositoryNames.CountStrings(); ++i) { 90704c9d578SStephan Aßmus const BString& repoName = repositoryNames.StringAt(i); 90804c9d578SStephan Aßmus BRepositoryConfig repoConfig; 90904c9d578SStephan Aßmus result = roster.GetRepositoryConfig(repoName, &repoConfig); 91004c9d578SStephan Aßmus if (result != B_OK) { 91104c9d578SStephan Aßmus // TODO: notify user 91204c9d578SStephan Aßmus continue; 91304c9d578SStephan Aßmus } 91404c9d578SStephan Aßmus 91504c9d578SStephan Aßmus if (roster.GetRepositoryCache(repoName, &cache) != B_OK || force) { 91604c9d578SStephan Aßmus try { 91704c9d578SStephan Aßmus BRefreshRepositoryRequest refreshRequest(context, repoConfig); 91804c9d578SStephan Aßmus 91904c9d578SStephan Aßmus result = refreshRequest.Process(); 92004c9d578SStephan Aßmus } catch (BFatalErrorException ex) { 92104c9d578SStephan Aßmus BString message(B_TRANSLATE("An error occurred while " 92204c9d578SStephan Aßmus "refreshing the repository: %error% (%details%)")); 92304c9d578SStephan Aßmus message.ReplaceFirst("%error%", ex.Message()); 92404c9d578SStephan Aßmus message.ReplaceFirst("%details%", ex.Details()); 92504c9d578SStephan Aßmus _NotifyUser("Error", message.String()); 92604c9d578SStephan Aßmus } catch (BException ex) { 92704c9d578SStephan Aßmus BString message(B_TRANSLATE("An error occurred while " 92804c9d578SStephan Aßmus "refreshing the repository: %error%")); 92904c9d578SStephan Aßmus message.ReplaceFirst("%error%", ex.Message()); 93004c9d578SStephan Aßmus _NotifyUser("Error", message.String()); 93104c9d578SStephan Aßmus } 93204c9d578SStephan Aßmus } 93304c9d578SStephan Aßmus } 93404c9d578SStephan Aßmus } 93504c9d578SStephan Aßmus 93604c9d578SStephan Aßmus 93704c9d578SStephan Aßmus void 9387b2c59b9SStephan Aßmus MainWindow::_RefreshPackageList(bool force) 93904c9d578SStephan Aßmus { 940448f707cSStephan Aßmus if (fSinglePackageMode) 941448f707cSStephan Aßmus return; 942448f707cSStephan Aßmus 9436d18e980SAndrew Lindesay if (Logger::IsDebugEnabled()) 9446d18e980SAndrew Lindesay printf("will refresh the package list\n"); 9456d18e980SAndrew Lindesay 94604c9d578SStephan Aßmus BPackageRoster roster; 94704c9d578SStephan Aßmus BStringList repositoryNames; 94804c9d578SStephan Aßmus 94904c9d578SStephan Aßmus status_t result = roster.GetRepositoryNames(repositoryNames); 95004c9d578SStephan Aßmus if (result != B_OK) 95104c9d578SStephan Aßmus return; 95204c9d578SStephan Aßmus 9533b17d8ddSAndrew Lindesay std::vector<DepotInfo> depots(repositoryNames.CountStrings()); 95404c9d578SStephan Aßmus for (int32 i = 0; i < repositoryNames.CountStrings(); i++) { 95504c9d578SStephan Aßmus const BString& repoName = repositoryNames.StringAt(i); 956ebb1a01cSAndrew Lindesay DepotInfo depotInfo = DepotInfo(repoName); 957ebb1a01cSAndrew Lindesay 958ebb1a01cSAndrew Lindesay BRepositoryConfig repoConfig; 959ebb1a01cSAndrew Lindesay status_t getRepositoryConfigStatus = roster.GetRepositoryConfig( 960ebb1a01cSAndrew Lindesay repoName, &repoConfig); 961ebb1a01cSAndrew Lindesay 962ebb1a01cSAndrew Lindesay if (getRepositoryConfigStatus == B_OK) { 963ebb1a01cSAndrew Lindesay depotInfo.SetBaseURL(repoConfig.BaseURL()); 9643b17d8ddSAndrew Lindesay depotInfo.SetURL(repoConfig.URL()); 9653b17d8ddSAndrew Lindesay 9663b17d8ddSAndrew Lindesay if (Logger::IsDebugEnabled()) { 9673b17d8ddSAndrew Lindesay printf("local repository [%s] info;\n" 9683b17d8ddSAndrew Lindesay " * base url [%s]\n" 9693b17d8ddSAndrew Lindesay " * url [%s]\n", 9703b17d8ddSAndrew Lindesay repoName.String(), repoConfig.BaseURL().String(), 9713b17d8ddSAndrew Lindesay repoConfig.URL().String()); 9723b17d8ddSAndrew Lindesay } 973ebb1a01cSAndrew Lindesay } else { 974ebb1a01cSAndrew Lindesay printf("unable to obtain the repository config for local " 975ebb1a01cSAndrew Lindesay "repository '%s'; %s\n", 976ebb1a01cSAndrew Lindesay repoName.String(), strerror(getRepositoryConfigStatus)); 977ebb1a01cSAndrew Lindesay } 978ebb1a01cSAndrew Lindesay 9793b17d8ddSAndrew Lindesay depots[i] = depotInfo; 98004c9d578SStephan Aßmus } 98104c9d578SStephan Aßmus 98204c9d578SStephan Aßmus PackageManager manager(B_PACKAGE_INSTALLATION_LOCATION_HOME); 98304c9d578SStephan Aßmus try { 98404c9d578SStephan Aßmus manager.Init(PackageManager::B_ADD_INSTALLED_REPOSITORIES 98504c9d578SStephan Aßmus | PackageManager::B_ADD_REMOTE_REPOSITORIES); 98604c9d578SStephan Aßmus } catch (BException ex) { 98704c9d578SStephan Aßmus BString message(B_TRANSLATE("An error occurred while " 98804c9d578SStephan Aßmus "initializing the package manager: %message%")); 98904c9d578SStephan Aßmus message.ReplaceFirst("%message%", ex.Message()); 99004c9d578SStephan Aßmus _NotifyUser("Error", message.String()); 99104c9d578SStephan Aßmus return; 99204c9d578SStephan Aßmus } 99304c9d578SStephan Aßmus 99404c9d578SStephan Aßmus BObjectList<BSolverPackage> packages; 99504c9d578SStephan Aßmus result = manager.Solver()->FindPackages("", 99604c9d578SStephan Aßmus BSolver::B_FIND_CASE_INSENSITIVE | BSolver::B_FIND_IN_NAME 99704c9d578SStephan Aßmus | BSolver::B_FIND_IN_SUMMARY | BSolver::B_FIND_IN_DESCRIPTION 99804c9d578SStephan Aßmus | BSolver::B_FIND_IN_PROVIDES, 99904c9d578SStephan Aßmus packages); 100004c9d578SStephan Aßmus if (result != B_OK) { 100104c9d578SStephan Aßmus BString message(B_TRANSLATE("An error occurred while " 100204c9d578SStephan Aßmus "obtaining the package list: %message%")); 100304c9d578SStephan Aßmus message.ReplaceFirst("%message%", strerror(result)); 100404c9d578SStephan Aßmus _NotifyUser("Error", message.String()); 100504c9d578SStephan Aßmus return; 100604c9d578SStephan Aßmus } 100704c9d578SStephan Aßmus 100804c9d578SStephan Aßmus if (packages.IsEmpty()) 100904c9d578SStephan Aßmus return; 101004c9d578SStephan Aßmus 101104c9d578SStephan Aßmus PackageInfoMap foundPackages; 101204c9d578SStephan Aßmus // if a given package is installed locally, we will potentially 101304c9d578SStephan Aßmus // get back multiple entries, one for each local installation 101404c9d578SStephan Aßmus // location, and one for each remote repository the package 101504c9d578SStephan Aßmus // is available in. The above map is used to ensure that in such 101604c9d578SStephan Aßmus // cases we consolidate the information, rather than displaying 101704c9d578SStephan Aßmus // duplicates 101804c9d578SStephan Aßmus PackageInfoMap remotePackages; 101904c9d578SStephan Aßmus // any package that we find in a remote repository goes in this map. 102004c9d578SStephan Aßmus // this is later used to discern which packages came from a local 102104c9d578SStephan Aßmus // installation only, as those must be handled a bit differently 102204c9d578SStephan Aßmus // upon uninstallation, since we'd no longer be able to pull them 102304c9d578SStephan Aßmus // down remotely. 102404c9d578SStephan Aßmus BStringList systemFlaggedPackages; 102504c9d578SStephan Aßmus // any packages flagged as a system package are added to this list. 102604c9d578SStephan Aßmus // such packages cannot be uninstalled, nor can any of their deps. 102704c9d578SStephan Aßmus PackageInfoMap systemInstalledPackages; 102804c9d578SStephan Aßmus // any packages installed in system are added to this list. 102904c9d578SStephan Aßmus // This is later used for dependency resolution of the actual 103004c9d578SStephan Aßmus // system packages in order to compute the list of protected 103104c9d578SStephan Aßmus // dependencies indicated above. 103204c9d578SStephan Aßmus 103304c9d578SStephan Aßmus for (int32 i = 0; i < packages.CountItems(); i++) { 103404c9d578SStephan Aßmus BSolverPackage* package = packages.ItemAt(i); 103504c9d578SStephan Aßmus const BPackageInfo& repoPackageInfo = package->Info(); 1036ebb1a01cSAndrew Lindesay const BString repositoryName = package->Repository()->Name(); 103704c9d578SStephan Aßmus PackageInfoRef modelInfo; 103804c9d578SStephan Aßmus PackageInfoMap::iterator it = foundPackages.find( 103904c9d578SStephan Aßmus repoPackageInfo.Name()); 104004c9d578SStephan Aßmus if (it != foundPackages.end()) 104104c9d578SStephan Aßmus modelInfo.SetTo(it->second); 104204c9d578SStephan Aßmus else { 104304c9d578SStephan Aßmus // Add new package info 10446d519fd1SStephan Aßmus modelInfo.SetTo(new(std::nothrow) PackageInfo(repoPackageInfo), 104504c9d578SStephan Aßmus true); 104604c9d578SStephan Aßmus 104704c9d578SStephan Aßmus if (modelInfo.Get() == NULL) 104804c9d578SStephan Aßmus return; 104904c9d578SStephan Aßmus 105004c9d578SStephan Aßmus foundPackages[repoPackageInfo.Name()] = modelInfo; 105104c9d578SStephan Aßmus } 105204c9d578SStephan Aßmus 10536ab878c0SAndrew Lindesay // The package list here considers those packages that are installed 10546ab878c0SAndrew Lindesay // in the system as well as those that exist in remote repositories. 10556ab878c0SAndrew Lindesay // It is better if the 'depot name' is from the remote repository 10566ab878c0SAndrew Lindesay // because then it will be possible to perform a rating on it later. 10576ab878c0SAndrew Lindesay 10586ab878c0SAndrew Lindesay if (modelInfo->DepotName().IsEmpty() 10596ab878c0SAndrew Lindesay || modelInfo->DepotName() == REPOSITORY_NAME_SYSTEM 10606ab878c0SAndrew Lindesay || modelInfo->DepotName() == REPOSITORY_NAME_INSTALLED) { 10616ab878c0SAndrew Lindesay modelInfo->SetDepotName(repositoryName); 10626ab878c0SAndrew Lindesay } 10636ab878c0SAndrew Lindesay 106404c9d578SStephan Aßmus modelInfo->AddListener(this); 106504c9d578SStephan Aßmus 106604c9d578SStephan Aßmus BSolverRepository* repository = package->Repository(); 10673b17d8ddSAndrew Lindesay BPackageManager::RemoteRepository* remoteRepository = 10683b17d8ddSAndrew Lindesay dynamic_cast<BPackageManager::RemoteRepository*>(repository); 10693b17d8ddSAndrew Lindesay 10703b17d8ddSAndrew Lindesay if (remoteRepository != NULL) { 10713b17d8ddSAndrew Lindesay 10723b17d8ddSAndrew Lindesay std::vector<DepotInfo>::iterator it; 10733b17d8ddSAndrew Lindesay 10743b17d8ddSAndrew Lindesay for (it = depots.begin(); it != depots.end(); it++) { 10753b17d8ddSAndrew Lindesay if (RepositoryUrlUtils::EqualsOnUrlOrBaseUrl( 10763b17d8ddSAndrew Lindesay it->URL(), remoteRepository->Config().URL(), 10773b17d8ddSAndrew Lindesay it->BaseURL(), remoteRepository->Config().BaseURL())) { 10783b17d8ddSAndrew Lindesay break; 10793b17d8ddSAndrew Lindesay } 10803b17d8ddSAndrew Lindesay } 10813b17d8ddSAndrew Lindesay 10823b17d8ddSAndrew Lindesay if (it == depots.end()) { 1083d13c3d89SAndrew Lindesay if (Logger::IsDebugEnabled()) { 10843b17d8ddSAndrew Lindesay printf("pkg [%s] repository [%s] not recognized" 10853b17d8ddSAndrew Lindesay " --> ignored\n", 1086d13c3d89SAndrew Lindesay modelInfo->Name().String(), repositoryName.String()); 1087d13c3d89SAndrew Lindesay } 1088d13c3d89SAndrew Lindesay } else { 10893b17d8ddSAndrew Lindesay it->AddPackage(modelInfo); 10903b17d8ddSAndrew Lindesay 10913b17d8ddSAndrew Lindesay if (Logger::IsTraceEnabled()) { 10923b17d8ddSAndrew Lindesay printf("pkg [%s] assigned to [%s]\n", 10933b17d8ddSAndrew Lindesay modelInfo->Name().String(), repositoryName.String()); 10943b17d8ddSAndrew Lindesay } 1095d13c3d89SAndrew Lindesay } 1096d13c3d89SAndrew Lindesay 109772992391SStephan Aßmus remotePackages[modelInfo->Name()] = modelInfo; 109804c9d578SStephan Aßmus } else { 109904c9d578SStephan Aßmus if (repository == static_cast<const BSolverRepository*>( 110004c9d578SStephan Aßmus manager.SystemRepository())) { 110104c9d578SStephan Aßmus modelInfo->AddInstallationLocation( 110204c9d578SStephan Aßmus B_PACKAGE_INSTALLATION_LOCATION_SYSTEM); 110304c9d578SStephan Aßmus if (!modelInfo->IsSystemPackage()) { 110404c9d578SStephan Aßmus systemInstalledPackages[repoPackageInfo.FileName()] 110504c9d578SStephan Aßmus = modelInfo; 110604c9d578SStephan Aßmus } 110704c9d578SStephan Aßmus } else if (repository == static_cast<const BSolverRepository*>( 110804c9d578SStephan Aßmus manager.HomeRepository())) { 110904c9d578SStephan Aßmus modelInfo->AddInstallationLocation( 111004c9d578SStephan Aßmus B_PACKAGE_INSTALLATION_LOCATION_HOME); 111104c9d578SStephan Aßmus } 111204c9d578SStephan Aßmus } 111304c9d578SStephan Aßmus 111404c9d578SStephan Aßmus if (modelInfo->IsSystemPackage()) 111504c9d578SStephan Aßmus systemFlaggedPackages.Add(repoPackageInfo.FileName()); 111604c9d578SStephan Aßmus } 111704c9d578SStephan Aßmus 11187b2c59b9SStephan Aßmus bool wasEmpty = fModel.Depots().IsEmpty(); 11197b2c59b9SStephan Aßmus if (force || wasEmpty) 11203094fef3SAndrew Lindesay fBulkLoadStateMachine.Stop(); 112104c9d578SStephan Aßmus 11226b147523SStephan Aßmus BAutolock lock(fModel.Lock()); 11237b2c59b9SStephan Aßmus 11247b2c59b9SStephan Aßmus if (force) 112504c9d578SStephan Aßmus fModel.Clear(); 112604c9d578SStephan Aßmus 112704c9d578SStephan Aßmus // filter remote packages from the found list 112804c9d578SStephan Aßmus // any packages remaining will be locally installed packages 112904c9d578SStephan Aßmus // that weren't acquired from a repository 113004c9d578SStephan Aßmus for (PackageInfoMap::iterator it = remotePackages.begin(); 113104c9d578SStephan Aßmus it != remotePackages.end(); it++) { 113204c9d578SStephan Aßmus foundPackages.erase(it->first); 113304c9d578SStephan Aßmus } 113404c9d578SStephan Aßmus 113504c9d578SStephan Aßmus if (!foundPackages.empty()) { 113604c9d578SStephan Aßmus BString repoName = B_TRANSLATE("Local"); 11373b17d8ddSAndrew Lindesay depots.push_back(DepotInfo(repoName)); 11383b17d8ddSAndrew Lindesay 113904c9d578SStephan Aßmus for (PackageInfoMap::iterator it = foundPackages.begin(); 114004c9d578SStephan Aßmus it != foundPackages.end(); ++it) { 11413b17d8ddSAndrew Lindesay depots.back().AddPackage(it->second); 114204c9d578SStephan Aßmus } 114304c9d578SStephan Aßmus } 114404c9d578SStephan Aßmus 11453b17d8ddSAndrew Lindesay { 11463b17d8ddSAndrew Lindesay std::vector<DepotInfo>::iterator it; 11473b17d8ddSAndrew Lindesay 11483b17d8ddSAndrew Lindesay for (it = depots.begin(); it != depots.end(); it++) { 11493b17d8ddSAndrew Lindesay if (fModel.HasDepot(it->Name())) 11503b17d8ddSAndrew Lindesay fModel.SyncDepot(*it); 11517b2c59b9SStephan Aßmus else 11523b17d8ddSAndrew Lindesay fModel.AddDepot(*it); 11533b17d8ddSAndrew Lindesay } 115404c9d578SStephan Aßmus } 115504c9d578SStephan Aßmus 115604c9d578SStephan Aßmus // start retrieving package icons and average ratings 11573094fef3SAndrew Lindesay if (force || wasEmpty) { 11583094fef3SAndrew Lindesay fBulkLoadStateMachine.Start(); 11593094fef3SAndrew Lindesay } 116004c9d578SStephan Aßmus 116104c9d578SStephan Aßmus // compute the OS package dependencies 116204c9d578SStephan Aßmus try { 116304c9d578SStephan Aßmus // create the solver 116404c9d578SStephan Aßmus BSolver* solver; 116504c9d578SStephan Aßmus status_t error = BSolver::Create(solver); 116604c9d578SStephan Aßmus if (error != B_OK) 116704c9d578SStephan Aßmus throw BFatalErrorException(error, "Failed to create solver."); 116804c9d578SStephan Aßmus 116904c9d578SStephan Aßmus ObjectDeleter<BSolver> solverDeleter(solver); 117004c9d578SStephan Aßmus BPath systemPath; 117104c9d578SStephan Aßmus error = find_directory(B_SYSTEM_PACKAGES_DIRECTORY, &systemPath); 117204c9d578SStephan Aßmus if (error != B_OK) { 117304c9d578SStephan Aßmus throw BFatalErrorException(error, 117404c9d578SStephan Aßmus "Unable to retrieve system packages directory."); 117504c9d578SStephan Aßmus } 117604c9d578SStephan Aßmus 117704c9d578SStephan Aßmus // add the "installed" repository with the given packages 117804c9d578SStephan Aßmus BSolverRepository installedRepository; 117904c9d578SStephan Aßmus { 118004c9d578SStephan Aßmus BRepositoryBuilder installedRepositoryBuilder(installedRepository, 11816ab878c0SAndrew Lindesay REPOSITORY_NAME_INSTALLED); 118204c9d578SStephan Aßmus for (int32 i = 0; i < systemFlaggedPackages.CountStrings(); i++) { 118304c9d578SStephan Aßmus BPath packagePath(systemPath); 118404c9d578SStephan Aßmus packagePath.Append(systemFlaggedPackages.StringAt(i)); 118504c9d578SStephan Aßmus installedRepositoryBuilder.AddPackage(packagePath.Path()); 118604c9d578SStephan Aßmus } 118704c9d578SStephan Aßmus installedRepositoryBuilder.AddToSolver(solver, true); 118804c9d578SStephan Aßmus } 118904c9d578SStephan Aßmus 119004c9d578SStephan Aßmus // add system repository 119104c9d578SStephan Aßmus BSolverRepository systemRepository; 119204c9d578SStephan Aßmus { 119304c9d578SStephan Aßmus BRepositoryBuilder systemRepositoryBuilder(systemRepository, 11946ab878c0SAndrew Lindesay REPOSITORY_NAME_SYSTEM); 119504c9d578SStephan Aßmus for (PackageInfoMap::iterator it = systemInstalledPackages.begin(); 119604c9d578SStephan Aßmus it != systemInstalledPackages.end(); it++) { 119704c9d578SStephan Aßmus BPath packagePath(systemPath); 119804c9d578SStephan Aßmus packagePath.Append(it->first); 119904c9d578SStephan Aßmus systemRepositoryBuilder.AddPackage(packagePath.Path()); 120004c9d578SStephan Aßmus } 120104c9d578SStephan Aßmus systemRepositoryBuilder.AddToSolver(solver, false); 120204c9d578SStephan Aßmus } 120304c9d578SStephan Aßmus 120404c9d578SStephan Aßmus // solve 120504c9d578SStephan Aßmus error = solver->VerifyInstallation(); 120604c9d578SStephan Aßmus if (error != B_OK) { 120704c9d578SStephan Aßmus throw BFatalErrorException(error, "Failed to compute packages to " 120804c9d578SStephan Aßmus "install."); 120904c9d578SStephan Aßmus } 121004c9d578SStephan Aßmus 121104c9d578SStephan Aßmus BSolverResult solverResult; 121204c9d578SStephan Aßmus error = solver->GetResult(solverResult); 121304c9d578SStephan Aßmus if (error != B_OK) { 121404c9d578SStephan Aßmus throw BFatalErrorException(error, "Failed to retrieve system " 121504c9d578SStephan Aßmus "package dependency list."); 121604c9d578SStephan Aßmus } 121704c9d578SStephan Aßmus 121804c9d578SStephan Aßmus for (int32 i = 0; const BSolverResultElement* element 121904c9d578SStephan Aßmus = solverResult.ElementAt(i); i++) { 122004c9d578SStephan Aßmus BSolverPackage* package = element->Package(); 122104c9d578SStephan Aßmus if (element->Type() == BSolverResultElement::B_TYPE_INSTALL) { 122204c9d578SStephan Aßmus PackageInfoMap::iterator it = systemInstalledPackages.find( 122304c9d578SStephan Aßmus package->Info().FileName()); 122404c9d578SStephan Aßmus if (it != systemInstalledPackages.end()) 122504c9d578SStephan Aßmus it->second->SetSystemDependency(true); 122604c9d578SStephan Aßmus } 122704c9d578SStephan Aßmus } 122804c9d578SStephan Aßmus } catch (BFatalErrorException ex) { 122904c9d578SStephan Aßmus printf("Fatal exception occurred while resolving system dependencies: " 123004c9d578SStephan Aßmus "%s, details: %s\n", strerror(ex.Error()), ex.Details().String()); 123104c9d578SStephan Aßmus } catch (BNothingToDoException) { 123204c9d578SStephan Aßmus // do nothing 123304c9d578SStephan Aßmus } catch (BException ex) { 123404c9d578SStephan Aßmus printf("Exception occurred while resolving system dependencies: %s\n", 123504c9d578SStephan Aßmus ex.Message().String()); 123604c9d578SStephan Aßmus } catch (...) { 123704c9d578SStephan Aßmus printf("Unknown exception occurred while resolving system " 123804c9d578SStephan Aßmus "dependencies.\n"); 123904c9d578SStephan Aßmus } 12406d18e980SAndrew Lindesay 12416d18e980SAndrew Lindesay if (Logger::IsDebugEnabled()) 12426d18e980SAndrew Lindesay printf("did refresh the package list\n"); 124304c9d578SStephan Aßmus } 124404c9d578SStephan Aßmus 124504c9d578SStephan Aßmus 124604c9d578SStephan Aßmus void 124704c9d578SStephan Aßmus MainWindow::_StartRefreshWorker(bool force) 124804c9d578SStephan Aßmus { 124904c9d578SStephan Aßmus if (fModelWorker != B_BAD_THREAD_ID) 125004c9d578SStephan Aßmus return; 125104c9d578SStephan Aßmus 125204c9d578SStephan Aßmus RefreshWorkerParameters* parameters = new(std::nothrow) 125304c9d578SStephan Aßmus RefreshWorkerParameters(this, force); 125404c9d578SStephan Aßmus if (parameters == NULL) 125504c9d578SStephan Aßmus return; 125604c9d578SStephan Aßmus 1257bc622f6bSHumdinger fWorkStatusView->SetBusy(B_TRANSLATE("Refreshing" B_UTF8_ELLIPSIS)); 1258125d42d9SJulian Harnath 125904c9d578SStephan Aßmus ObjectDeleter<RefreshWorkerParameters> deleter(parameters); 126004c9d578SStephan Aßmus fModelWorker = spawn_thread(&_RefreshModelThreadWorker, "model loader", 126104c9d578SStephan Aßmus B_LOW_PRIORITY, parameters); 126204c9d578SStephan Aßmus 126304c9d578SStephan Aßmus if (fModelWorker > 0) { 126404c9d578SStephan Aßmus deleter.Detach(); 126504c9d578SStephan Aßmus resume_thread(fModelWorker); 126604c9d578SStephan Aßmus } 126704c9d578SStephan Aßmus } 126804c9d578SStephan Aßmus 126904c9d578SStephan Aßmus 127004c9d578SStephan Aßmus status_t 127104c9d578SStephan Aßmus MainWindow::_RefreshModelThreadWorker(void* arg) 127204c9d578SStephan Aßmus { 127304c9d578SStephan Aßmus RefreshWorkerParameters* parameters 127404c9d578SStephan Aßmus = reinterpret_cast<RefreshWorkerParameters*>(arg); 127504c9d578SStephan Aßmus MainWindow* mainWindow = parameters->window; 127604c9d578SStephan Aßmus ObjectDeleter<RefreshWorkerParameters> deleter(parameters); 127704c9d578SStephan Aßmus 127804c9d578SStephan Aßmus BMessenger messenger(mainWindow); 127904c9d578SStephan Aßmus 128004c9d578SStephan Aßmus mainWindow->_RefreshRepositories(parameters->forceRefresh); 128104c9d578SStephan Aßmus 128204c9d578SStephan Aßmus if (mainWindow->fTerminating) 128304c9d578SStephan Aßmus return B_OK; 128404c9d578SStephan Aßmus 12857b2c59b9SStephan Aßmus mainWindow->_RefreshPackageList(parameters->forceRefresh); 128604c9d578SStephan Aßmus 128704c9d578SStephan Aßmus messenger.SendMessage(MSG_MODEL_WORKER_DONE); 128804c9d578SStephan Aßmus 128904c9d578SStephan Aßmus return B_OK; 129004c9d578SStephan Aßmus } 129104c9d578SStephan Aßmus 129204c9d578SStephan Aßmus 129304c9d578SStephan Aßmus status_t 129404c9d578SStephan Aßmus MainWindow::_PackageActionWorker(void* arg) 129504c9d578SStephan Aßmus { 129604c9d578SStephan Aßmus MainWindow* window = reinterpret_cast<MainWindow*>(arg); 129704c9d578SStephan Aßmus 129804c9d578SStephan Aßmus while (acquire_sem(window->fPendingActionsSem) == B_OK) { 129904c9d578SStephan Aßmus PackageActionRef ref; 130004c9d578SStephan Aßmus { 130104c9d578SStephan Aßmus AutoLocker<BLocker> lock(&window->fPendingActionsLock); 130204c9d578SStephan Aßmus ref = window->fPendingActions.ItemAt(0); 130304c9d578SStephan Aßmus if (ref.Get() == NULL) 130404c9d578SStephan Aßmus break; 130504c9d578SStephan Aßmus window->fPendingActions.Remove(0); 130604c9d578SStephan Aßmus } 130704c9d578SStephan Aßmus 1308125d42d9SJulian Harnath BMessenger messenger(window); 1309125d42d9SJulian Harnath BMessage busyMessage(MSG_PACKAGE_WORKER_BUSY); 1310125d42d9SJulian Harnath BString text(ref->Label()); 1311bc622f6bSHumdinger text << B_UTF8_ELLIPSIS; 1312125d42d9SJulian Harnath busyMessage.AddString("reason", text); 1313125d42d9SJulian Harnath 1314125d42d9SJulian Harnath messenger.SendMessage(&busyMessage); 131504c9d578SStephan Aßmus ref->Perform(); 1316125d42d9SJulian Harnath messenger.SendMessage(MSG_PACKAGE_WORKER_IDLE); 131704c9d578SStephan Aßmus } 131804c9d578SStephan Aßmus 131904c9d578SStephan Aßmus return 0; 132004c9d578SStephan Aßmus } 132104c9d578SStephan Aßmus 132204c9d578SStephan Aßmus 1323a9edb9bfSAndrew Lindesay /*! This method will cause the package to have its data refreshed from 1324a9edb9bfSAndrew Lindesay the server application. The refresh happens in the background; this method 1325a9edb9bfSAndrew Lindesay is asynchronous. 1326a9edb9bfSAndrew Lindesay */ 1327a9edb9bfSAndrew Lindesay 1328a9edb9bfSAndrew Lindesay void 1329a9edb9bfSAndrew Lindesay MainWindow::_PopulatePackageAsync(bool forcePopulate) 1330a9edb9bfSAndrew Lindesay { 1331a9edb9bfSAndrew Lindesay // Trigger asynchronous package population from the web-app 1332a9edb9bfSAndrew Lindesay { 1333a9edb9bfSAndrew Lindesay AutoLocker<BLocker> lock(&fPackageToPopulateLock); 1334a9edb9bfSAndrew Lindesay fPackageToPopulate = fPackageInfoView->Package(); 1335a9edb9bfSAndrew Lindesay fForcePopulatePackage = forcePopulate; 1336a9edb9bfSAndrew Lindesay } 1337a9edb9bfSAndrew Lindesay release_sem_etc(fPackageToPopulateSem, 1, 0); 1338a9edb9bfSAndrew Lindesay 1339a9edb9bfSAndrew Lindesay if (Logger::IsDebugEnabled()) { 1340a9edb9bfSAndrew Lindesay printf("pkg [%s] will be updated from the server.\n", 1341a9edb9bfSAndrew Lindesay fPackageToPopulate->Name().String()); 1342a9edb9bfSAndrew Lindesay } 1343a9edb9bfSAndrew Lindesay } 1344a9edb9bfSAndrew Lindesay 1345a9edb9bfSAndrew Lindesay 1346a9edb9bfSAndrew Lindesay /*! This method will run in the background. The thread will block until there 1347a9edb9bfSAndrew Lindesay is a package to be updated. When the thread unblocks, it will update the 1348a9edb9bfSAndrew Lindesay package with information from the server. 1349a9edb9bfSAndrew Lindesay */ 1350a9edb9bfSAndrew Lindesay 135104c9d578SStephan Aßmus status_t 135204c9d578SStephan Aßmus MainWindow::_PopulatePackageWorker(void* arg) 135304c9d578SStephan Aßmus { 135404c9d578SStephan Aßmus MainWindow* window = reinterpret_cast<MainWindow*>(arg); 135504c9d578SStephan Aßmus 135604c9d578SStephan Aßmus while (acquire_sem(window->fPackageToPopulateSem) == B_OK) { 135704c9d578SStephan Aßmus PackageInfoRef package; 1358a9edb9bfSAndrew Lindesay bool force; 135904c9d578SStephan Aßmus { 136004c9d578SStephan Aßmus AutoLocker<BLocker> lock(&window->fPackageToPopulateLock); 136104c9d578SStephan Aßmus package = window->fPackageToPopulate; 1362a9edb9bfSAndrew Lindesay force = window->fForcePopulatePackage; 136304c9d578SStephan Aßmus } 136404c9d578SStephan Aßmus 136504c9d578SStephan Aßmus if (package.Get() != NULL) { 1366a9edb9bfSAndrew Lindesay uint32 populateFlags = Model::POPULATE_USER_RATINGS 1367a9edb9bfSAndrew Lindesay | Model::POPULATE_SCREEN_SHOTS 1368a9edb9bfSAndrew Lindesay | Model::POPULATE_CHANGELOG; 1369a9edb9bfSAndrew Lindesay 1370a9edb9bfSAndrew Lindesay if (force) 1371a9edb9bfSAndrew Lindesay populateFlags |= Model::POPULATE_FORCE; 1372a9edb9bfSAndrew Lindesay 1373a9edb9bfSAndrew Lindesay window->fModel.PopulatePackage(package, populateFlags); 1374a9edb9bfSAndrew Lindesay 1375a9edb9bfSAndrew Lindesay if (Logger::IsDebugEnabled()) { 1376a9edb9bfSAndrew Lindesay printf("populating package [%s]\n", 1377a9edb9bfSAndrew Lindesay package->Name().String()); 1378a9edb9bfSAndrew Lindesay } 137904c9d578SStephan Aßmus } 138004c9d578SStephan Aßmus } 138104c9d578SStephan Aßmus 138204c9d578SStephan Aßmus return 0; 138304c9d578SStephan Aßmus } 138404c9d578SStephan Aßmus 138504c9d578SStephan Aßmus 138672fff6d3SJulian Harnath /* static */ status_t 138772fff6d3SJulian Harnath MainWindow::_PackagesToShowWorker(void* arg) 138872fff6d3SJulian Harnath { 138972fff6d3SJulian Harnath MainWindow* window = reinterpret_cast<MainWindow*>(arg); 139072fff6d3SJulian Harnath 139172fff6d3SJulian Harnath while (acquire_sem(window->fNewPackagesToShowSem) == B_OK) { 139272fff6d3SJulian Harnath PackageList packageList; 139372fff6d3SJulian Harnath int32 listID = 0; 139472fff6d3SJulian Harnath { 139572fff6d3SJulian Harnath AutoLocker<BLocker> lock(&window->fPackagesToShowListLock); 139672fff6d3SJulian Harnath packageList = window->fPackagesToShowList; 139772fff6d3SJulian Harnath listID = atomic_get(&window->fPackagesToShowListID); 139872fff6d3SJulian Harnath window->fPackagesToShowList.Clear(); 139972fff6d3SJulian Harnath } 140072fff6d3SJulian Harnath 140172fff6d3SJulian Harnath // Add packages to list views in batches of kPackagesPerUpdate so we 140272fff6d3SJulian Harnath // don't block the window thread for long with each iteration 140372fff6d3SJulian Harnath enum { 140472fff6d3SJulian Harnath kPackagesPerUpdate = 20 140572fff6d3SJulian Harnath }; 140672fff6d3SJulian Harnath uint32 packagesInMessage = 0; 140772fff6d3SJulian Harnath BMessage message(MSG_ADD_VISIBLE_PACKAGES); 140872fff6d3SJulian Harnath BMessenger messenger(window); 140972fff6d3SJulian Harnath bool listIsOutdated = false; 141072fff6d3SJulian Harnath 141172fff6d3SJulian Harnath for (int i = 0; i < packageList.CountItems(); i++) { 141272fff6d3SJulian Harnath const PackageInfoRef& package = packageList.ItemAtFast(i); 141372fff6d3SJulian Harnath 141472fff6d3SJulian Harnath if (packagesInMessage >= kPackagesPerUpdate) { 141572fff6d3SJulian Harnath if (listID != atomic_get(&window->fPackagesToShowListID)) { 141672fff6d3SJulian Harnath // The model was changed again in the meantime, and thus 141772fff6d3SJulian Harnath // our package list isn't current anymore. Send no further 141872fff6d3SJulian Harnath // messags based on this list and go back to start. 141972fff6d3SJulian Harnath listIsOutdated = true; 142072fff6d3SJulian Harnath break; 142172fff6d3SJulian Harnath } 142272fff6d3SJulian Harnath 142372fff6d3SJulian Harnath message.AddInt32("list_id", listID); 142472fff6d3SJulian Harnath messenger.SendMessage(&message); 142572fff6d3SJulian Harnath message.MakeEmpty(); 142672fff6d3SJulian Harnath packagesInMessage = 0; 142772fff6d3SJulian Harnath 142872fff6d3SJulian Harnath // Don't spam the window's message queue, which would make it 142972fff6d3SJulian Harnath // unresponsive (i.e. allows UI messages to get in between our 143072fff6d3SJulian Harnath // messages). When it has processed the message we just sent, 143172fff6d3SJulian Harnath // it will let us know by releasing the semaphore. 143272fff6d3SJulian Harnath acquire_sem(window->fShowPackagesAcknowledgeSem); 143372fff6d3SJulian Harnath } 143472fff6d3SJulian Harnath package->AcquireReference(); 143572fff6d3SJulian Harnath message.AddPointer("package_ref", package.Get()); 143672fff6d3SJulian Harnath packagesInMessage++; 143772fff6d3SJulian Harnath } 143872fff6d3SJulian Harnath 143972fff6d3SJulian Harnath if (listIsOutdated) 144072fff6d3SJulian Harnath continue; 144172fff6d3SJulian Harnath 144272fff6d3SJulian Harnath // Send remaining package infos, if any, which didn't make it into 144372fff6d3SJulian Harnath // the last message (count < kPackagesPerUpdate) 144472fff6d3SJulian Harnath if (packagesInMessage > 0) { 144572fff6d3SJulian Harnath message.AddInt32("list_id", listID); 144672fff6d3SJulian Harnath messenger.SendMessage(&message); 144772fff6d3SJulian Harnath acquire_sem(window->fShowPackagesAcknowledgeSem); 144872fff6d3SJulian Harnath } 144972fff6d3SJulian Harnath 145072fff6d3SJulian Harnath // Update selected package in list views 145172fff6d3SJulian Harnath messenger.SendMessage(MSG_UPDATE_SELECTED_PACKAGE); 145272fff6d3SJulian Harnath } 145372fff6d3SJulian Harnath 145472fff6d3SJulian Harnath return 0; 145572fff6d3SJulian Harnath } 145672fff6d3SJulian Harnath 145772fff6d3SJulian Harnath 145804c9d578SStephan Aßmus void 145904c9d578SStephan Aßmus MainWindow::_NotifyUser(const char* title, const char* message) 146004c9d578SStephan Aßmus { 146104c9d578SStephan Aßmus BAlert* alert = new(std::nothrow) BAlert(title, message, 146204c9d578SStephan Aßmus B_TRANSLATE("Close")); 146304c9d578SStephan Aßmus 146404c9d578SStephan Aßmus if (alert != NULL) 146504c9d578SStephan Aßmus alert->Go(); 146604c9d578SStephan Aßmus } 146704c9d578SStephan Aßmus 146804c9d578SStephan Aßmus 146904c9d578SStephan Aßmus void 14701bbda92dSStephan Aßmus MainWindow::_OpenLoginWindow(const BMessage& onSuccessMessage) 147104c9d578SStephan Aßmus { 147204c9d578SStephan Aßmus UserLoginWindow* window = new UserLoginWindow(this, 147304c9d578SStephan Aßmus BRect(0, 0, 500, 400), fModel); 14741bbda92dSStephan Aßmus 14751bbda92dSStephan Aßmus if (onSuccessMessage.what != 0) 14761bbda92dSStephan Aßmus window->SetOnSuccessMessage(BMessenger(this), onSuccessMessage); 14771bbda92dSStephan Aßmus 147804c9d578SStephan Aßmus window->Show(); 147904c9d578SStephan Aßmus } 148004c9d578SStephan Aßmus 14818f03a0f9SStephan Aßmus 14828f03a0f9SStephan Aßmus void 14838f03a0f9SStephan Aßmus MainWindow::_UpdateAuthorization() 14848f03a0f9SStephan Aßmus { 14858f03a0f9SStephan Aßmus BString username(fModel.Username()); 1486e0a26dceSStephan Aßmus bool hasUser = !username.IsEmpty(); 1487e0a26dceSStephan Aßmus 14886d519fd1SStephan Aßmus if (fLogOutItem != NULL) 1489e0a26dceSStephan Aßmus fLogOutItem->SetEnabled(hasUser); 1490e0a26dceSStephan Aßmus if (fLogInItem != NULL) { 1491e0a26dceSStephan Aßmus if (hasUser) 1492e0a26dceSStephan Aßmus fLogInItem->SetLabel(B_TRANSLATE("Switch account" B_UTF8_ELLIPSIS)); 1493e0a26dceSStephan Aßmus else 1494e0a26dceSStephan Aßmus fLogInItem->SetLabel(B_TRANSLATE("Log in" B_UTF8_ELLIPSIS)); 1495e0a26dceSStephan Aßmus } 1496e0a26dceSStephan Aßmus 1497e0a26dceSStephan Aßmus if (fUserMenu != NULL) { 1498e0a26dceSStephan Aßmus BString label; 1499e0a26dceSStephan Aßmus if (username.Length() == 0) { 1500e0a26dceSStephan Aßmus label = B_TRANSLATE("Not logged in"); 1501e0a26dceSStephan Aßmus } else { 1502e0a26dceSStephan Aßmus label = B_TRANSLATE("Logged in as %User%"); 1503e0a26dceSStephan Aßmus label.ReplaceAll("%User%", username); 1504e0a26dceSStephan Aßmus } 1505e0a26dceSStephan Aßmus fUserMenu->Superitem()->SetLabel(label); 1506e0a26dceSStephan Aßmus } 15078f03a0f9SStephan Aßmus } 15081bbda92dSStephan Aßmus 15091bbda92dSStephan Aßmus 15101bbda92dSStephan Aßmus void 1511b965ce70SHumdinger MainWindow::_UpdateAvailableRepositories() 1512b965ce70SHumdinger { 1513b965ce70SHumdinger fRepositoryMenu->RemoveItems(0, fRepositoryMenu->CountItems(), true); 1514b965ce70SHumdinger 1515b965ce70SHumdinger fRepositoryMenu->AddItem(new BMenuItem(B_TRANSLATE("All repositories"), 1516b965ce70SHumdinger new BMessage(MSG_DEPOT_SELECTED))); 1517b965ce70SHumdinger 1518b965ce70SHumdinger fRepositoryMenu->AddItem(new BSeparatorItem()); 1519b965ce70SHumdinger 1520b965ce70SHumdinger bool foundSelectedDepot = false; 1521b965ce70SHumdinger const DepotList& depots = fModel.Depots(); 1522b965ce70SHumdinger for (int i = 0; i < depots.CountItems(); i++) { 1523b965ce70SHumdinger const DepotInfo& depot = depots.ItemAtFast(i); 1524d13c3d89SAndrew Lindesay 1525d13c3d89SAndrew Lindesay if (depot.Name().Length() != 0) { 1526b965ce70SHumdinger BMessage* message = new BMessage(MSG_DEPOT_SELECTED); 1527b965ce70SHumdinger message->AddString("name", depot.Name()); 1528b965ce70SHumdinger BMenuItem* item = new BMenuItem(depot.Name(), message); 1529b965ce70SHumdinger fRepositoryMenu->AddItem(item); 1530b965ce70SHumdinger 1531b965ce70SHumdinger if (depot.Name() == fModel.Depot()) { 1532b965ce70SHumdinger item->SetMarked(true); 1533b965ce70SHumdinger foundSelectedDepot = true; 1534b965ce70SHumdinger } 1535b965ce70SHumdinger } 1536d13c3d89SAndrew Lindesay } 1537b965ce70SHumdinger 1538b965ce70SHumdinger if (!foundSelectedDepot) 1539b965ce70SHumdinger fRepositoryMenu->ItemAt(0)->SetMarked(true); 1540b965ce70SHumdinger } 1541b965ce70SHumdinger 1542b965ce70SHumdinger 1543a9edb9bfSAndrew Lindesay bool 1544a9edb9bfSAndrew Lindesay MainWindow::_SelectedPackageHasWebAppRepositoryCode() 1545a9edb9bfSAndrew Lindesay { 1546a9edb9bfSAndrew Lindesay const PackageInfoRef& package = fPackageInfoView->Package(); 15476ab878c0SAndrew Lindesay const BString depotName = package->DepotName(); 1548a9edb9bfSAndrew Lindesay 15496ab878c0SAndrew Lindesay if (depotName.IsEmpty()) { 15506ab878c0SAndrew Lindesay if (Logger::IsDebugEnabled()) { 15516ab878c0SAndrew Lindesay printf("the package [%s] has no depot name\n", 15526ab878c0SAndrew Lindesay package->Name().String()); 15536ab878c0SAndrew Lindesay } 15546ab878c0SAndrew Lindesay } else { 15556ab878c0SAndrew Lindesay const DepotInfo* depot = fModel.DepotForName(depotName); 1556a9edb9bfSAndrew Lindesay 15576ab878c0SAndrew Lindesay if (depot == NULL) { 15586ab878c0SAndrew Lindesay printf("the depot [%s] was not able to be found\n", 15596ab878c0SAndrew Lindesay depotName.String()); 15606ab878c0SAndrew Lindesay } else { 15616ab878c0SAndrew Lindesay BString repositoryCode = depot->WebAppRepositoryCode(); 1562a9edb9bfSAndrew Lindesay 15636ab878c0SAndrew Lindesay if (repositoryCode.IsEmpty()) { 15646ab878c0SAndrew Lindesay printf("the depot [%s] has no web app repository code\n", 15656ab878c0SAndrew Lindesay depotName.String()); 15666ab878c0SAndrew Lindesay } else { 15676ab878c0SAndrew Lindesay return true; 15686ab878c0SAndrew Lindesay } 15696ab878c0SAndrew Lindesay } 15706ab878c0SAndrew Lindesay } 15716ab878c0SAndrew Lindesay 15726ab878c0SAndrew Lindesay return false; 1573a9edb9bfSAndrew Lindesay } 1574a9edb9bfSAndrew Lindesay 1575a9edb9bfSAndrew Lindesay 1576b965ce70SHumdinger void 15771bbda92dSStephan Aßmus MainWindow::_RatePackage() 15781bbda92dSStephan Aßmus { 1579a9edb9bfSAndrew Lindesay if (!_SelectedPackageHasWebAppRepositoryCode()) { 1580a9edb9bfSAndrew Lindesay BAlert* alert = new(std::nothrow) BAlert( 1581cbadcae1SHumdinger B_TRANSLATE("Rating not possible"), 1582cbadcae1SHumdinger B_TRANSLATE("This package doesn't seem to be on the HaikuDepot " 1583cbadcae1SHumdinger "Server, so it's not possible to create a new rating " 1584cbadcae1SHumdinger "or edit an existing rating."), 1585a9edb9bfSAndrew Lindesay B_TRANSLATE("OK")); 1586a9edb9bfSAndrew Lindesay alert->Go(); 1587a9edb9bfSAndrew Lindesay return; 1588a9edb9bfSAndrew Lindesay } 1589a9edb9bfSAndrew Lindesay 15901bbda92dSStephan Aßmus if (fModel.Username().IsEmpty()) { 15911bbda92dSStephan Aßmus BAlert* alert = new(std::nothrow) BAlert( 15921bbda92dSStephan Aßmus B_TRANSLATE("Not logged in"), 15931bbda92dSStephan Aßmus B_TRANSLATE("You need to be logged into an account before you " 15941bbda92dSStephan Aßmus "can rate packages."), 15951bbda92dSStephan Aßmus B_TRANSLATE("Cancel"), 15961bbda92dSStephan Aßmus B_TRANSLATE("Login or Create account")); 15971bbda92dSStephan Aßmus 15981bbda92dSStephan Aßmus if (alert == NULL) 15991bbda92dSStephan Aßmus return; 16001bbda92dSStephan Aßmus 16011bbda92dSStephan Aßmus int32 choice = alert->Go(); 16021bbda92dSStephan Aßmus if (choice == 1) 16031bbda92dSStephan Aßmus _OpenLoginWindow(BMessage(MSG_RATE_PACKAGE)); 16041bbda92dSStephan Aßmus return; 16051bbda92dSStephan Aßmus } 16061bbda92dSStephan Aßmus 16071bbda92dSStephan Aßmus // TODO: Allow only one RatePackageWindow 16081bbda92dSStephan Aßmus // TODO: Mechanism for remembering the window frame 16091bbda92dSStephan Aßmus RatePackageWindow* window = new RatePackageWindow(this, 16101bbda92dSStephan Aßmus BRect(0, 0, 500, 400), fModel); 16111bbda92dSStephan Aßmus window->SetPackage(fPackageInfoView->Package()); 16121bbda92dSStephan Aßmus window->Show(); 16131bbda92dSStephan Aßmus } 1614d5ef985eSStephan Aßmus 1615d5ef985eSStephan Aßmus 1616d5ef985eSStephan Aßmus void 1617d5ef985eSStephan Aßmus MainWindow::_ShowScreenshot() 1618d5ef985eSStephan Aßmus { 1619d5ef985eSStephan Aßmus // TODO: Mechanism for remembering the window frame 1620d5ef985eSStephan Aßmus if (fScreenshotWindow == NULL) 1621d5ef985eSStephan Aßmus fScreenshotWindow = new ScreenshotWindow(this, BRect(0, 0, 500, 400)); 1622d5ef985eSStephan Aßmus 1623d5ef985eSStephan Aßmus if (fScreenshotWindow->LockWithTimeout(1000) != B_OK) 1624d5ef985eSStephan Aßmus return; 1625d5ef985eSStephan Aßmus 1626d5ef985eSStephan Aßmus fScreenshotWindow->SetPackage(fPackageInfoView->Package()); 1627d5ef985eSStephan Aßmus 1628d5ef985eSStephan Aßmus if (fScreenshotWindow->IsHidden()) 1629d5ef985eSStephan Aßmus fScreenshotWindow->Show(); 1630d5ef985eSStephan Aßmus else 1631d5ef985eSStephan Aßmus fScreenshotWindow->Activate(); 1632d5ef985eSStephan Aßmus 1633d5ef985eSStephan Aßmus fScreenshotWindow->Unlock(); 1634d5ef985eSStephan Aßmus } 1635