104c9d578SStephan Aßmus /* 204c9d578SStephan Aßmus * Copyright 2013-2014, Stephan Aßmus <superstippi@gmx.de>. 304c9d578SStephan Aßmus * Copyright 2013, Rene Gollent, rene@gollent.com. 404c9d578SStephan Aßmus * Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de. 504c9d578SStephan Aßmus * All rights reserved. Distributed under the terms of the MIT License. 604c9d578SStephan Aßmus */ 704c9d578SStephan Aßmus 804c9d578SStephan Aßmus #include "MainWindow.h" 904c9d578SStephan Aßmus 1004c9d578SStephan Aßmus #include <map> 1104c9d578SStephan Aßmus 1204c9d578SStephan Aßmus #include <stdio.h> 1304c9d578SStephan Aßmus 1404c9d578SStephan Aßmus #include <Alert.h> 1504c9d578SStephan Aßmus #include <Autolock.h> 1604c9d578SStephan Aßmus #include <Application.h> 1704c9d578SStephan Aßmus #include <Button.h> 1804c9d578SStephan Aßmus #include <Catalog.h> 1904c9d578SStephan Aßmus #include <LayoutBuilder.h> 2004c9d578SStephan Aßmus #include <MenuBar.h> 2104c9d578SStephan Aßmus #include <MenuItem.h> 2204c9d578SStephan Aßmus #include <Messenger.h> 2304c9d578SStephan Aßmus #include <ScrollView.h> 2404c9d578SStephan Aßmus #include <StringList.h> 2504c9d578SStephan Aßmus #include <TabView.h> 2604c9d578SStephan Aßmus 2704c9d578SStephan Aßmus #include <package/Context.h> 2804c9d578SStephan Aßmus #include <package/manager/Exceptions.h> 2904c9d578SStephan Aßmus #include <package/manager/RepositoryBuilder.h> 3004c9d578SStephan Aßmus #include <package/RefreshRepositoryRequest.h> 3104c9d578SStephan Aßmus #include <package/PackageRoster.h> 3204c9d578SStephan Aßmus #include "package/RepositoryCache.h" 3304c9d578SStephan Aßmus #include <package/solver/SolverPackage.h> 3404c9d578SStephan Aßmus #include <package/solver/SolverProblem.h> 3504c9d578SStephan Aßmus #include <package/solver/SolverProblemSolution.h> 3604c9d578SStephan Aßmus #include <package/solver/SolverRepository.h> 3704c9d578SStephan Aßmus #include <package/solver/SolverResult.h> 3804c9d578SStephan Aßmus 3904c9d578SStephan Aßmus #include "AutoDeleter.h" 4004c9d578SStephan Aßmus #include "AutoLocker.h" 4104c9d578SStephan Aßmus #include "DecisionProvider.h" 4204c9d578SStephan Aßmus #include "FilterView.h" 4304c9d578SStephan Aßmus #include "JobStateListener.h" 4404c9d578SStephan Aßmus #include "PackageInfoView.h" 4504c9d578SStephan Aßmus #include "PackageListView.h" 4604c9d578SStephan Aßmus #include "PackageManager.h" 4704c9d578SStephan Aßmus #include "RatePackageWindow.h" 4804c9d578SStephan Aßmus #include "UserLoginWindow.h" 4904c9d578SStephan Aßmus 5004c9d578SStephan Aßmus 5104c9d578SStephan Aßmus #undef B_TRANSLATION_CONTEXT 5204c9d578SStephan Aßmus #define B_TRANSLATION_CONTEXT "MainWindow" 5304c9d578SStephan Aßmus 5404c9d578SStephan Aßmus 5504c9d578SStephan Aßmus enum { 5604c9d578SStephan Aßmus MSG_MODEL_WORKER_DONE = 'mmwd', 5704c9d578SStephan Aßmus MSG_REFRESH_DEPOTS = 'mrdp', 5804c9d578SStephan Aßmus MSG_LOG_IN = 'lgin', 598f03a0f9SStephan Aßmus MSG_LOG_OUT = 'lgot', 608f03a0f9SStephan Aßmus MSG_AUTHORIZATION_CHANGED = 'athc', 6104c9d578SStephan Aßmus MSG_PACKAGE_STATE_CHANGED = 'mpsc', 6204c9d578SStephan Aßmus MSG_SHOW_SOURCE_PACKAGES = 'ssrc', 6304c9d578SStephan Aßmus MSG_SHOW_DEVELOP_PACKAGES = 'sdvl' 6404c9d578SStephan Aßmus }; 6504c9d578SStephan Aßmus 6604c9d578SStephan Aßmus 6704c9d578SStephan Aßmus using namespace BPackageKit; 6804c9d578SStephan Aßmus using namespace BPackageKit::BManager::BPrivate; 6904c9d578SStephan Aßmus 7004c9d578SStephan Aßmus 7104c9d578SStephan Aßmus typedef std::map<BString, PackageInfoRef> PackageInfoMap; 7204c9d578SStephan Aßmus typedef std::map<BString, DepotInfo> DepotInfoMap; 7304c9d578SStephan Aßmus 7404c9d578SStephan Aßmus 7504c9d578SStephan Aßmus struct RefreshWorkerParameters { 7604c9d578SStephan Aßmus MainWindow* window; 7704c9d578SStephan Aßmus bool forceRefresh; 7804c9d578SStephan Aßmus 7904c9d578SStephan Aßmus RefreshWorkerParameters(MainWindow* window, bool forceRefresh) 8004c9d578SStephan Aßmus : 8104c9d578SStephan Aßmus window(window), 8204c9d578SStephan Aßmus forceRefresh(forceRefresh) 8304c9d578SStephan Aßmus { 8404c9d578SStephan Aßmus } 8504c9d578SStephan Aßmus }; 8604c9d578SStephan Aßmus 8704c9d578SStephan Aßmus 888f03a0f9SStephan Aßmus class MessageModelListener : public ModelListener { 898f03a0f9SStephan Aßmus public: 908f03a0f9SStephan Aßmus MessageModelListener(const BMessenger& messenger) 918f03a0f9SStephan Aßmus : 928f03a0f9SStephan Aßmus fMessenger(messenger) 938f03a0f9SStephan Aßmus { 948f03a0f9SStephan Aßmus } 958f03a0f9SStephan Aßmus 968f03a0f9SStephan Aßmus virtual void AuthorizationChanged() 978f03a0f9SStephan Aßmus { 988f03a0f9SStephan Aßmus if (fMessenger.IsValid()) 998f03a0f9SStephan Aßmus fMessenger.SendMessage(MSG_AUTHORIZATION_CHANGED); 1008f03a0f9SStephan Aßmus } 1018f03a0f9SStephan Aßmus 1028f03a0f9SStephan Aßmus private: 1038f03a0f9SStephan Aßmus BMessenger fMessenger; 1048f03a0f9SStephan Aßmus }; 1058f03a0f9SStephan Aßmus 1068f03a0f9SStephan Aßmus 10704c9d578SStephan Aßmus MainWindow::MainWindow(BRect frame, const BMessage& settings) 10804c9d578SStephan Aßmus : 10904c9d578SStephan Aßmus BWindow(frame, B_TRANSLATE_SYSTEM_NAME("HaikuDepot"), 11004c9d578SStephan Aßmus B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, 11104c9d578SStephan Aßmus B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS), 1128f03a0f9SStephan Aßmus fModelListener(new MessageModelListener(BMessenger(this)), true), 11304c9d578SStephan Aßmus fTerminating(false), 11404c9d578SStephan Aßmus fModelWorker(B_BAD_THREAD_ID) 11504c9d578SStephan Aßmus { 11604c9d578SStephan Aßmus BMenuBar* menuBar = new BMenuBar(B_TRANSLATE("Main Menu")); 11704c9d578SStephan Aßmus _BuildMenu(menuBar); 11804c9d578SStephan Aßmus 11904c9d578SStephan Aßmus fFilterView = new FilterView(); 12004c9d578SStephan Aßmus fPackageListView = new PackageListView(fModel.Lock()); 12104c9d578SStephan Aßmus fPackageInfoView = new PackageInfoView(fModel.Lock(), this); 12204c9d578SStephan Aßmus 12304c9d578SStephan Aßmus fSplitView = new BSplitView(B_VERTICAL, 5.0f); 12404c9d578SStephan Aßmus 12504c9d578SStephan Aßmus BLayoutBuilder::Group<>(this, B_VERTICAL, 0.0f) 12604c9d578SStephan Aßmus .Add(menuBar) 12704c9d578SStephan Aßmus .Add(fFilterView) 12804c9d578SStephan Aßmus .AddSplit(fSplitView) 12904c9d578SStephan Aßmus .AddGroup(B_VERTICAL) 13004c9d578SStephan Aßmus .Add(fPackageListView) 13104c9d578SStephan Aßmus .SetInsets( 13204c9d578SStephan Aßmus B_USE_DEFAULT_SPACING, 0.0f, 13304c9d578SStephan Aßmus B_USE_DEFAULT_SPACING, 0.0f) 13404c9d578SStephan Aßmus .End() 13504c9d578SStephan Aßmus .Add(fPackageInfoView) 13604c9d578SStephan Aßmus .End() 13704c9d578SStephan Aßmus ; 13804c9d578SStephan Aßmus 13904c9d578SStephan Aßmus fSplitView->SetCollapsible(0, false); 14004c9d578SStephan Aßmus fSplitView->SetCollapsible(1, false); 14104c9d578SStephan Aßmus 1428f03a0f9SStephan Aßmus fModel.AddListener(fModelListener); 1438f03a0f9SStephan Aßmus 14404c9d578SStephan Aßmus // Restore settings 14504c9d578SStephan Aßmus BMessage columnSettings; 14604c9d578SStephan Aßmus if (settings.FindMessage("column settings", &columnSettings) == B_OK) 14704c9d578SStephan Aßmus fPackageListView->LoadState(&columnSettings); 14804c9d578SStephan Aßmus 14904c9d578SStephan Aßmus bool showOption; 15004c9d578SStephan Aßmus if (settings.FindBool("show develop packages", &showOption) == B_OK) 15104c9d578SStephan Aßmus fModel.SetShowDevelopPackages(showOption); 15204c9d578SStephan Aßmus if (settings.FindBool("show source packages", &showOption) == B_OK) 15304c9d578SStephan Aßmus fModel.SetShowSourcePackages(showOption); 15404c9d578SStephan Aßmus 1558f03a0f9SStephan Aßmus BString username; 1568f03a0f9SStephan Aßmus if (settings.FindString("username", &username) == B_OK 1578f03a0f9SStephan Aßmus && username.Length() > 0) { 1588f03a0f9SStephan Aßmus fModel.SetUsername(username); 1598f03a0f9SStephan Aßmus } 1608f03a0f9SStephan Aßmus 1618f03a0f9SStephan Aßmus // start worker threads 16204c9d578SStephan Aßmus BPackageRoster().StartWatching(this, 16304c9d578SStephan Aßmus B_WATCH_PACKAGE_INSTALLATION_LOCATIONS); 16404c9d578SStephan Aßmus 16504c9d578SStephan Aßmus _StartRefreshWorker(); 16604c9d578SStephan Aßmus 16704c9d578SStephan Aßmus fPendingActionsSem = create_sem(0, "PendingPackageActions"); 16804c9d578SStephan Aßmus if (fPendingActionsSem >= 0) { 16904c9d578SStephan Aßmus fPendingActionsWorker = spawn_thread(&_PackageActionWorker, 17004c9d578SStephan Aßmus "Planet Express", B_NORMAL_PRIORITY, this); 17104c9d578SStephan Aßmus if (fPendingActionsWorker >= 0) 17204c9d578SStephan Aßmus resume_thread(fPendingActionsWorker); 17304c9d578SStephan Aßmus } 17404c9d578SStephan Aßmus 17504c9d578SStephan Aßmus fPackageToPopulateSem = create_sem(0, "PopulatePackage"); 17604c9d578SStephan Aßmus if (fPackageToPopulateSem >= 0) { 17704c9d578SStephan Aßmus fPopulatePackageWorker = spawn_thread(&_PopulatePackageWorker, 17804c9d578SStephan Aßmus "Package Populator", B_NORMAL_PRIORITY, this); 17904c9d578SStephan Aßmus if (fPopulatePackageWorker >= 0) 18004c9d578SStephan Aßmus resume_thread(fPopulatePackageWorker); 18104c9d578SStephan Aßmus } 18204c9d578SStephan Aßmus } 18304c9d578SStephan Aßmus 18404c9d578SStephan Aßmus 18504c9d578SStephan Aßmus MainWindow::~MainWindow() 18604c9d578SStephan Aßmus { 18704c9d578SStephan Aßmus BPackageRoster().StopWatching(this); 18804c9d578SStephan Aßmus 18904c9d578SStephan Aßmus fTerminating = true; 19004c9d578SStephan Aßmus if (fModelWorker > 0) 19104c9d578SStephan Aßmus wait_for_thread(fModelWorker, NULL); 19204c9d578SStephan Aßmus 19304c9d578SStephan Aßmus delete_sem(fPendingActionsSem); 19404c9d578SStephan Aßmus wait_for_thread(fPendingActionsWorker, NULL); 19504c9d578SStephan Aßmus 19604c9d578SStephan Aßmus delete_sem(fPackageToPopulateSem); 19704c9d578SStephan Aßmus wait_for_thread(fPopulatePackageWorker, NULL); 19804c9d578SStephan Aßmus } 19904c9d578SStephan Aßmus 20004c9d578SStephan Aßmus 20104c9d578SStephan Aßmus bool 20204c9d578SStephan Aßmus MainWindow::QuitRequested() 20304c9d578SStephan Aßmus { 20404c9d578SStephan Aßmus BMessage settings; 20504c9d578SStephan Aßmus StoreSettings(settings); 20604c9d578SStephan Aßmus 20704c9d578SStephan Aßmus BMessage message(MSG_MAIN_WINDOW_CLOSED); 20804c9d578SStephan Aßmus message.AddMessage("window settings", &settings); 20904c9d578SStephan Aßmus 21004c9d578SStephan Aßmus be_app->PostMessage(&message); 21104c9d578SStephan Aßmus 21204c9d578SStephan Aßmus return true; 21304c9d578SStephan Aßmus } 21404c9d578SStephan Aßmus 21504c9d578SStephan Aßmus 21604c9d578SStephan Aßmus void 21704c9d578SStephan Aßmus MainWindow::MessageReceived(BMessage* message) 21804c9d578SStephan Aßmus { 21904c9d578SStephan Aßmus switch (message->what) { 22004c9d578SStephan Aßmus case MSG_MODEL_WORKER_DONE: 22104c9d578SStephan Aßmus { 22204c9d578SStephan Aßmus fModelWorker = B_BAD_THREAD_ID; 22304c9d578SStephan Aßmus _AdoptModel(); 22404c9d578SStephan Aßmus fFilterView->AdoptModel(fModel); 22504c9d578SStephan Aßmus break; 22604c9d578SStephan Aßmus } 22704c9d578SStephan Aßmus case B_SIMPLE_DATA: 22804c9d578SStephan Aßmus case B_REFS_RECEIVED: 22904c9d578SStephan Aßmus // TODO: ? 23004c9d578SStephan Aßmus break; 23104c9d578SStephan Aßmus 23204c9d578SStephan Aßmus case B_PACKAGE_UPDATE: 23304c9d578SStephan Aßmus // TODO: We should do a more selective update depending on the 23404c9d578SStephan Aßmus // "event", "location", and "change count" fields! 23504c9d578SStephan Aßmus _StartRefreshWorker(false); 23604c9d578SStephan Aßmus break; 23704c9d578SStephan Aßmus 23804c9d578SStephan Aßmus case MSG_REFRESH_DEPOTS: 23904c9d578SStephan Aßmus _StartRefreshWorker(true); 24004c9d578SStephan Aßmus break; 24104c9d578SStephan Aßmus 24204c9d578SStephan Aßmus case MSG_LOG_IN: 243*1bbda92dSStephan Aßmus _OpenLoginWindow(BMessage()); 24404c9d578SStephan Aßmus break; 24504c9d578SStephan Aßmus 2468f03a0f9SStephan Aßmus case MSG_LOG_OUT: 2478f03a0f9SStephan Aßmus fModel.SetUsername(""); 2488f03a0f9SStephan Aßmus break; 2498f03a0f9SStephan Aßmus 2508f03a0f9SStephan Aßmus case MSG_AUTHORIZATION_CHANGED: 2518f03a0f9SStephan Aßmus _UpdateAuthorization(); 2528f03a0f9SStephan Aßmus break; 2538f03a0f9SStephan Aßmus 25404c9d578SStephan Aßmus case MSG_SHOW_SOURCE_PACKAGES: 25504c9d578SStephan Aßmus { 25604c9d578SStephan Aßmus BAutolock locker(fModel.Lock()); 25704c9d578SStephan Aßmus fModel.SetShowSourcePackages(!fModel.ShowSourcePackages()); 25804c9d578SStephan Aßmus } 25904c9d578SStephan Aßmus _AdoptModel(); 26004c9d578SStephan Aßmus break; 26104c9d578SStephan Aßmus 26204c9d578SStephan Aßmus case MSG_SHOW_DEVELOP_PACKAGES: 26304c9d578SStephan Aßmus { 26404c9d578SStephan Aßmus BAutolock locker(fModel.Lock()); 26504c9d578SStephan Aßmus fModel.SetShowDevelopPackages(!fModel.ShowDevelopPackages()); 26604c9d578SStephan Aßmus } 26704c9d578SStephan Aßmus _AdoptModel(); 26804c9d578SStephan Aßmus break; 26904c9d578SStephan Aßmus 27004c9d578SStephan Aßmus case MSG_PACKAGE_SELECTED: 27104c9d578SStephan Aßmus { 27204c9d578SStephan Aßmus BString title; 27304c9d578SStephan Aßmus if (message->FindString("title", &title) == B_OK) { 27404c9d578SStephan Aßmus int count = fVisiblePackages.CountItems(); 27504c9d578SStephan Aßmus for (int i = 0; i < count; i++) { 27604c9d578SStephan Aßmus const PackageInfoRef& package 27704c9d578SStephan Aßmus = fVisiblePackages.ItemAtFast(i); 27804c9d578SStephan Aßmus if (package.Get() != NULL && package->Title() == title) { 27904c9d578SStephan Aßmus _AdoptPackage(package); 28004c9d578SStephan Aßmus break; 28104c9d578SStephan Aßmus } 28204c9d578SStephan Aßmus } 28304c9d578SStephan Aßmus } else { 28404c9d578SStephan Aßmus _ClearPackage(); 28504c9d578SStephan Aßmus } 28604c9d578SStephan Aßmus break; 28704c9d578SStephan Aßmus } 28804c9d578SStephan Aßmus 28904c9d578SStephan Aßmus case MSG_CATEGORY_SELECTED: 29004c9d578SStephan Aßmus { 29104c9d578SStephan Aßmus BString name; 29204c9d578SStephan Aßmus if (message->FindString("name", &name) != B_OK) 29304c9d578SStephan Aßmus name = ""; 29404c9d578SStephan Aßmus { 29504c9d578SStephan Aßmus BAutolock locker(fModel.Lock()); 29604c9d578SStephan Aßmus fModel.SetCategory(name); 29704c9d578SStephan Aßmus } 29804c9d578SStephan Aßmus _AdoptModel(); 29904c9d578SStephan Aßmus break; 30004c9d578SStephan Aßmus } 30104c9d578SStephan Aßmus 30204c9d578SStephan Aßmus case MSG_FILTER_SELECTED: 30304c9d578SStephan Aßmus { 30404c9d578SStephan Aßmus BString name; 30504c9d578SStephan Aßmus int32 value; 30604c9d578SStephan Aßmus if (message->FindString("name", &name) != B_OK 30704c9d578SStephan Aßmus || message->FindInt32("be:value", &value) != B_OK) { 30804c9d578SStephan Aßmus break; 30904c9d578SStephan Aßmus } 31004c9d578SStephan Aßmus { 31104c9d578SStephan Aßmus BAutolock locker(fModel.Lock()); 31204c9d578SStephan Aßmus if (name == "available") { 31304c9d578SStephan Aßmus fModel.SetShowAvailablePackages( 31404c9d578SStephan Aßmus value == B_CONTROL_ON); 31504c9d578SStephan Aßmus } else if (name == "installed") { 31604c9d578SStephan Aßmus fModel.SetShowInstalledPackages( 31704c9d578SStephan Aßmus value == B_CONTROL_ON); 31804c9d578SStephan Aßmus } else if (name == "development") { 31904c9d578SStephan Aßmus fModel.SetShowDevelopPackages( 32004c9d578SStephan Aßmus value == B_CONTROL_ON); 32104c9d578SStephan Aßmus } else if (name == "source code") { 32204c9d578SStephan Aßmus fModel.SetShowSourcePackages( 32304c9d578SStephan Aßmus value == B_CONTROL_ON); 32404c9d578SStephan Aßmus } else { 32504c9d578SStephan Aßmus break; 32604c9d578SStephan Aßmus } 32704c9d578SStephan Aßmus } 32804c9d578SStephan Aßmus _AdoptModel(); 32904c9d578SStephan Aßmus break; 33004c9d578SStephan Aßmus } 33104c9d578SStephan Aßmus 33204c9d578SStephan Aßmus case MSG_DEPOT_SELECTED: 33304c9d578SStephan Aßmus { 33404c9d578SStephan Aßmus BString name; 33504c9d578SStephan Aßmus if (message->FindString("name", &name) != B_OK) 33604c9d578SStephan Aßmus name = ""; 33704c9d578SStephan Aßmus { 33804c9d578SStephan Aßmus BAutolock locker(fModel.Lock()); 33904c9d578SStephan Aßmus fModel.SetDepot(name); 34004c9d578SStephan Aßmus } 34104c9d578SStephan Aßmus _AdoptModel(); 34204c9d578SStephan Aßmus break; 34304c9d578SStephan Aßmus } 34404c9d578SStephan Aßmus 34504c9d578SStephan Aßmus case MSG_SEARCH_TERMS_MODIFIED: 34604c9d578SStephan Aßmus { 34704c9d578SStephan Aßmus // TODO: Do this with a delay! 34804c9d578SStephan Aßmus BString searchTerms; 34904c9d578SStephan Aßmus if (message->FindString("search terms", &searchTerms) != B_OK) 35004c9d578SStephan Aßmus searchTerms = ""; 35104c9d578SStephan Aßmus { 35204c9d578SStephan Aßmus BAutolock locker(fModel.Lock()); 35304c9d578SStephan Aßmus fModel.SetSearchTerms(searchTerms); 35404c9d578SStephan Aßmus } 35504c9d578SStephan Aßmus _AdoptModel(); 35604c9d578SStephan Aßmus break; 35704c9d578SStephan Aßmus } 35804c9d578SStephan Aßmus 35904c9d578SStephan Aßmus case MSG_PACKAGE_STATE_CHANGED: 36004c9d578SStephan Aßmus { 36104c9d578SStephan Aßmus PackageInfo* info; 36204c9d578SStephan Aßmus if (message->FindPointer("package", (void**)&info) == B_OK) { 36304c9d578SStephan Aßmus PackageInfoRef ref(info, true); 36404c9d578SStephan Aßmus BAutolock locker(fModel.Lock()); 36504c9d578SStephan Aßmus fModel.SetPackageState(ref, ref->State()); 36604c9d578SStephan Aßmus } 36704c9d578SStephan Aßmus break; 36804c9d578SStephan Aßmus } 36904c9d578SStephan Aßmus 37004c9d578SStephan Aßmus case MSG_RATE_PACKAGE: 371*1bbda92dSStephan Aßmus _RatePackage(); 37204c9d578SStephan Aßmus break; 37304c9d578SStephan Aßmus 37404c9d578SStephan Aßmus default: 37504c9d578SStephan Aßmus BWindow::MessageReceived(message); 37604c9d578SStephan Aßmus break; 37704c9d578SStephan Aßmus } 37804c9d578SStephan Aßmus } 37904c9d578SStephan Aßmus 38004c9d578SStephan Aßmus 38104c9d578SStephan Aßmus void 38204c9d578SStephan Aßmus MainWindow::StoreSettings(BMessage& settings) const 38304c9d578SStephan Aßmus { 38404c9d578SStephan Aßmus settings.AddRect("window frame", Frame()); 38504c9d578SStephan Aßmus 38604c9d578SStephan Aßmus BMessage columnSettings; 38704c9d578SStephan Aßmus fPackageListView->SaveState(&columnSettings); 38804c9d578SStephan Aßmus 38904c9d578SStephan Aßmus settings.AddMessage("column settings", &columnSettings); 39004c9d578SStephan Aßmus 39104c9d578SStephan Aßmus settings.AddBool("show develop packages", fModel.ShowDevelopPackages()); 39204c9d578SStephan Aßmus settings.AddBool("show source packages", fModel.ShowSourcePackages()); 3938f03a0f9SStephan Aßmus 3948f03a0f9SStephan Aßmus settings.AddString("username", fModel.Username()); 39504c9d578SStephan Aßmus } 39604c9d578SStephan Aßmus 39704c9d578SStephan Aßmus 39804c9d578SStephan Aßmus void 39904c9d578SStephan Aßmus MainWindow::PackageChanged(const PackageInfoEvent& event) 40004c9d578SStephan Aßmus { 40104c9d578SStephan Aßmus if ((event.Changes() & PKG_CHANGED_STATE) != 0) { 40204c9d578SStephan Aßmus PackageInfoRef ref(event.Package()); 40304c9d578SStephan Aßmus BMessage message(MSG_PACKAGE_STATE_CHANGED); 40404c9d578SStephan Aßmus message.AddPointer("package", ref.Get()); 40504c9d578SStephan Aßmus ref.Detach(); 40604c9d578SStephan Aßmus // reference needs to be released by MessageReceived(); 40704c9d578SStephan Aßmus PostMessage(&message); 40804c9d578SStephan Aßmus } 40904c9d578SStephan Aßmus } 41004c9d578SStephan Aßmus 41104c9d578SStephan Aßmus 41204c9d578SStephan Aßmus status_t 41304c9d578SStephan Aßmus MainWindow::SchedulePackageActions(PackageActionList& list) 41404c9d578SStephan Aßmus { 41504c9d578SStephan Aßmus AutoLocker<BLocker> lock(&fPendingActionsLock); 41604c9d578SStephan Aßmus for (int32 i = 0; i < list.CountItems(); i++) { 41704c9d578SStephan Aßmus if (!fPendingActions.Add(list.ItemAtFast(i))) 41804c9d578SStephan Aßmus return B_NO_MEMORY; 41904c9d578SStephan Aßmus } 42004c9d578SStephan Aßmus 42104c9d578SStephan Aßmus return release_sem_etc(fPendingActionsSem, list.CountItems(), 0); 42204c9d578SStephan Aßmus } 42304c9d578SStephan Aßmus 42404c9d578SStephan Aßmus 42504c9d578SStephan Aßmus Model* 42604c9d578SStephan Aßmus MainWindow::GetModel() 42704c9d578SStephan Aßmus { 42804c9d578SStephan Aßmus return &fModel; 42904c9d578SStephan Aßmus } 43004c9d578SStephan Aßmus 43104c9d578SStephan Aßmus 43204c9d578SStephan Aßmus void 43304c9d578SStephan Aßmus MainWindow::_BuildMenu(BMenuBar* menuBar) 43404c9d578SStephan Aßmus { 43504c9d578SStephan Aßmus BMenu* menu = new BMenu(B_TRANSLATE("Tools")); 43604c9d578SStephan Aßmus menu->AddItem(new BMenuItem(B_TRANSLATE("Refresh depots"), 43704c9d578SStephan Aßmus new BMessage(MSG_REFRESH_DEPOTS))); 4388f03a0f9SStephan Aßmus menu->AddSeparatorItem(); 4398f03a0f9SStephan Aßmus menu->AddItem(new BMenuItem(B_TRANSLATE("Log in" B_UTF8_ELLIPSIS), 44004c9d578SStephan Aßmus new BMessage(MSG_LOG_IN))); 4418f03a0f9SStephan Aßmus fLogOutItem = new BMenuItem(B_TRANSLATE("Log out"), 4428f03a0f9SStephan Aßmus new BMessage(MSG_LOG_OUT)); 4438f03a0f9SStephan Aßmus menu->AddItem(fLogOutItem); 44404c9d578SStephan Aßmus menuBar->AddItem(menu); 44504c9d578SStephan Aßmus 44604c9d578SStephan Aßmus // menu = new BMenu(B_TRANSLATE("Options")); 44704c9d578SStephan Aßmus // 44804c9d578SStephan Aßmus // fShowDevelopPackagesItem = new BMenuItem( 44904c9d578SStephan Aßmus // B_TRANSLATE("Show develop packages"), 45004c9d578SStephan Aßmus // new BMessage(MSG_SHOW_DEVELOP_PACKAGES)); 45104c9d578SStephan Aßmus // menu->AddItem(fShowDevelopPackagesItem); 45204c9d578SStephan Aßmus // 45304c9d578SStephan Aßmus // fShowSourcePackagesItem = new BMenuItem(B_TRANSLATE("Show source packages"), 45404c9d578SStephan Aßmus // new BMessage(MSG_SHOW_SOURCE_PACKAGES)); 45504c9d578SStephan Aßmus // menu->AddItem(fShowSourcePackagesItem); 45604c9d578SStephan Aßmus // 45704c9d578SStephan Aßmus // menuBar->AddItem(menu); 45804c9d578SStephan Aßmus } 45904c9d578SStephan Aßmus 46004c9d578SStephan Aßmus 46104c9d578SStephan Aßmus void 46204c9d578SStephan Aßmus MainWindow::_AdoptModel() 46304c9d578SStephan Aßmus { 46404c9d578SStephan Aßmus fVisiblePackages = fModel.CreatePackageList(); 46504c9d578SStephan Aßmus 46604c9d578SStephan Aßmus fPackageListView->Clear(); 46704c9d578SStephan Aßmus for (int32 i = 0; i < fVisiblePackages.CountItems(); i++) { 46804c9d578SStephan Aßmus BAutolock locker(fModel.Lock()); 46904c9d578SStephan Aßmus fPackageListView->AddPackage(fVisiblePackages.ItemAtFast(i)); 47004c9d578SStephan Aßmus } 47104c9d578SStephan Aßmus 47204c9d578SStephan Aßmus BAutolock locker(fModel.Lock()); 47304c9d578SStephan Aßmus // fShowSourcePackagesItem->SetMarked(fModel.ShowSourcePackages()); 47404c9d578SStephan Aßmus // fShowDevelopPackagesItem->SetMarked(fModel.ShowDevelopPackages()); 47504c9d578SStephan Aßmus fFilterView->AdoptCheckmarks(fModel); 47604c9d578SStephan Aßmus } 47704c9d578SStephan Aßmus 47804c9d578SStephan Aßmus 47904c9d578SStephan Aßmus void 48004c9d578SStephan Aßmus MainWindow::_AdoptPackage(const PackageInfoRef& package) 48104c9d578SStephan Aßmus { 48204c9d578SStephan Aßmus fPackageInfoView->SetPackage(package); 48304c9d578SStephan Aßmus 48404c9d578SStephan Aßmus // Trigger asynchronous package population from the web-app 48504c9d578SStephan Aßmus { 48604c9d578SStephan Aßmus AutoLocker<BLocker> lock(&fPackageToPopulateLock); 48704c9d578SStephan Aßmus fPackageToPopulate = package; 48804c9d578SStephan Aßmus } 48904c9d578SStephan Aßmus release_sem_etc(fPackageToPopulateSem, 1, 0); 49004c9d578SStephan Aßmus } 49104c9d578SStephan Aßmus 49204c9d578SStephan Aßmus 49304c9d578SStephan Aßmus void 49404c9d578SStephan Aßmus MainWindow::_ClearPackage() 49504c9d578SStephan Aßmus { 49604c9d578SStephan Aßmus fPackageInfoView->Clear(); 49704c9d578SStephan Aßmus } 49804c9d578SStephan Aßmus 49904c9d578SStephan Aßmus 50004c9d578SStephan Aßmus void 50104c9d578SStephan Aßmus MainWindow::_RefreshRepositories(bool force) 50204c9d578SStephan Aßmus { 50304c9d578SStephan Aßmus BPackageRoster roster; 50404c9d578SStephan Aßmus BStringList repositoryNames; 50504c9d578SStephan Aßmus 50604c9d578SStephan Aßmus status_t result = roster.GetRepositoryNames(repositoryNames); 50704c9d578SStephan Aßmus if (result != B_OK) 50804c9d578SStephan Aßmus return; 50904c9d578SStephan Aßmus 51004c9d578SStephan Aßmus DecisionProvider decisionProvider; 51104c9d578SStephan Aßmus JobStateListener listener; 51204c9d578SStephan Aßmus BContext context(decisionProvider, listener); 51304c9d578SStephan Aßmus 51404c9d578SStephan Aßmus BRepositoryCache cache; 51504c9d578SStephan Aßmus for (int32 i = 0; i < repositoryNames.CountStrings(); ++i) { 51604c9d578SStephan Aßmus const BString& repoName = repositoryNames.StringAt(i); 51704c9d578SStephan Aßmus BRepositoryConfig repoConfig; 51804c9d578SStephan Aßmus result = roster.GetRepositoryConfig(repoName, &repoConfig); 51904c9d578SStephan Aßmus if (result != B_OK) { 52004c9d578SStephan Aßmus // TODO: notify user 52104c9d578SStephan Aßmus continue; 52204c9d578SStephan Aßmus } 52304c9d578SStephan Aßmus 52404c9d578SStephan Aßmus if (roster.GetRepositoryCache(repoName, &cache) != B_OK || force) { 52504c9d578SStephan Aßmus try { 52604c9d578SStephan Aßmus BRefreshRepositoryRequest refreshRequest(context, repoConfig); 52704c9d578SStephan Aßmus 52804c9d578SStephan Aßmus result = refreshRequest.Process(); 52904c9d578SStephan Aßmus } catch (BFatalErrorException ex) { 53004c9d578SStephan Aßmus BString message(B_TRANSLATE("An error occurred while " 53104c9d578SStephan Aßmus "refreshing the repository: %error% (%details%)")); 53204c9d578SStephan Aßmus message.ReplaceFirst("%error%", ex.Message()); 53304c9d578SStephan Aßmus message.ReplaceFirst("%details%", ex.Details()); 53404c9d578SStephan Aßmus _NotifyUser("Error", message.String()); 53504c9d578SStephan Aßmus } catch (BException ex) { 53604c9d578SStephan Aßmus BString message(B_TRANSLATE("An error occurred while " 53704c9d578SStephan Aßmus "refreshing the repository: %error%")); 53804c9d578SStephan Aßmus message.ReplaceFirst("%error%", ex.Message()); 53904c9d578SStephan Aßmus _NotifyUser("Error", message.String()); 54004c9d578SStephan Aßmus } 54104c9d578SStephan Aßmus } 54204c9d578SStephan Aßmus } 54304c9d578SStephan Aßmus } 54404c9d578SStephan Aßmus 54504c9d578SStephan Aßmus 54604c9d578SStephan Aßmus void 54704c9d578SStephan Aßmus MainWindow::_RefreshPackageList() 54804c9d578SStephan Aßmus { 54904c9d578SStephan Aßmus BPackageRoster roster; 55004c9d578SStephan Aßmus BStringList repositoryNames; 55104c9d578SStephan Aßmus 55204c9d578SStephan Aßmus status_t result = roster.GetRepositoryNames(repositoryNames); 55304c9d578SStephan Aßmus if (result != B_OK) 55404c9d578SStephan Aßmus return; 55504c9d578SStephan Aßmus 55604c9d578SStephan Aßmus DepotInfoMap depots; 55704c9d578SStephan Aßmus for (int32 i = 0; i < repositoryNames.CountStrings(); i++) { 55804c9d578SStephan Aßmus const BString& repoName = repositoryNames.StringAt(i); 55904c9d578SStephan Aßmus depots[repoName] = DepotInfo(repoName); 56004c9d578SStephan Aßmus } 56104c9d578SStephan Aßmus 56204c9d578SStephan Aßmus PackageManager manager(B_PACKAGE_INSTALLATION_LOCATION_HOME); 56304c9d578SStephan Aßmus try { 56404c9d578SStephan Aßmus manager.Init(PackageManager::B_ADD_INSTALLED_REPOSITORIES 56504c9d578SStephan Aßmus | PackageManager::B_ADD_REMOTE_REPOSITORIES); 56604c9d578SStephan Aßmus } catch (BException ex) { 56704c9d578SStephan Aßmus BString message(B_TRANSLATE("An error occurred while " 56804c9d578SStephan Aßmus "initializing the package manager: %message%")); 56904c9d578SStephan Aßmus message.ReplaceFirst("%message%", ex.Message()); 57004c9d578SStephan Aßmus _NotifyUser("Error", message.String()); 57104c9d578SStephan Aßmus return; 57204c9d578SStephan Aßmus } 57304c9d578SStephan Aßmus 57404c9d578SStephan Aßmus BObjectList<BSolverPackage> packages; 57504c9d578SStephan Aßmus result = manager.Solver()->FindPackages("", 57604c9d578SStephan Aßmus BSolver::B_FIND_CASE_INSENSITIVE | BSolver::B_FIND_IN_NAME 57704c9d578SStephan Aßmus | BSolver::B_FIND_IN_SUMMARY | BSolver::B_FIND_IN_DESCRIPTION 57804c9d578SStephan Aßmus | BSolver::B_FIND_IN_PROVIDES, 57904c9d578SStephan Aßmus packages); 58004c9d578SStephan Aßmus if (result != B_OK) { 58104c9d578SStephan Aßmus BString message(B_TRANSLATE("An error occurred while " 58204c9d578SStephan Aßmus "obtaining the package list: %message%")); 58304c9d578SStephan Aßmus message.ReplaceFirst("%message%", strerror(result)); 58404c9d578SStephan Aßmus _NotifyUser("Error", message.String()); 58504c9d578SStephan Aßmus return; 58604c9d578SStephan Aßmus } 58704c9d578SStephan Aßmus 58804c9d578SStephan Aßmus if (packages.IsEmpty()) 58904c9d578SStephan Aßmus return; 59004c9d578SStephan Aßmus 59104c9d578SStephan Aßmus PackageInfoMap foundPackages; 59204c9d578SStephan Aßmus // if a given package is installed locally, we will potentially 59304c9d578SStephan Aßmus // get back multiple entries, one for each local installation 59404c9d578SStephan Aßmus // location, and one for each remote repository the package 59504c9d578SStephan Aßmus // is available in. The above map is used to ensure that in such 59604c9d578SStephan Aßmus // cases we consolidate the information, rather than displaying 59704c9d578SStephan Aßmus // duplicates 59804c9d578SStephan Aßmus PackageInfoMap remotePackages; 59904c9d578SStephan Aßmus // any package that we find in a remote repository goes in this map. 60004c9d578SStephan Aßmus // this is later used to discern which packages came from a local 60104c9d578SStephan Aßmus // installation only, as those must be handled a bit differently 60204c9d578SStephan Aßmus // upon uninstallation, since we'd no longer be able to pull them 60304c9d578SStephan Aßmus // down remotely. 60404c9d578SStephan Aßmus BStringList systemFlaggedPackages; 60504c9d578SStephan Aßmus // any packages flagged as a system package are added to this list. 60604c9d578SStephan Aßmus // such packages cannot be uninstalled, nor can any of their deps. 60704c9d578SStephan Aßmus PackageInfoMap systemInstalledPackages; 60804c9d578SStephan Aßmus // any packages installed in system are added to this list. 60904c9d578SStephan Aßmus // This is later used for dependency resolution of the actual 61004c9d578SStephan Aßmus // system packages in order to compute the list of protected 61104c9d578SStephan Aßmus // dependencies indicated above. 61204c9d578SStephan Aßmus 61304c9d578SStephan Aßmus BitmapRef defaultIcon(new(std::nothrow) SharedBitmap( 61404c9d578SStephan Aßmus "application/x-vnd.haiku-package"), true); 61504c9d578SStephan Aßmus 61604c9d578SStephan Aßmus for (int32 i = 0; i < packages.CountItems(); i++) { 61704c9d578SStephan Aßmus BSolverPackage* package = packages.ItemAt(i); 61804c9d578SStephan Aßmus const BPackageInfo& repoPackageInfo = package->Info(); 61904c9d578SStephan Aßmus PackageInfoRef modelInfo; 62004c9d578SStephan Aßmus PackageInfoMap::iterator it = foundPackages.find( 62104c9d578SStephan Aßmus repoPackageInfo.Name()); 62204c9d578SStephan Aßmus if (it != foundPackages.end()) 62304c9d578SStephan Aßmus modelInfo.SetTo(it->second); 62404c9d578SStephan Aßmus else { 62504c9d578SStephan Aßmus // Add new package info 62604c9d578SStephan Aßmus BString publisherURL; 62704c9d578SStephan Aßmus if (repoPackageInfo.URLList().CountStrings() > 0) 62804c9d578SStephan Aßmus publisherURL = repoPackageInfo.URLList().StringAt(0); 62904c9d578SStephan Aßmus 63004c9d578SStephan Aßmus BString publisherName = repoPackageInfo.Vendor(); 63104c9d578SStephan Aßmus const BStringList& rightsList = repoPackageInfo.CopyrightList(); 63204c9d578SStephan Aßmus if (rightsList.CountStrings() > 0) 63304c9d578SStephan Aßmus publisherName = rightsList.StringAt(0); 63404c9d578SStephan Aßmus 63504c9d578SStephan Aßmus modelInfo.SetTo(new(std::nothrow) PackageInfo( 63604c9d578SStephan Aßmus repoPackageInfo.Name(), 63746bcb34dSStephan Aßmus repoPackageInfo.Version(), 63804c9d578SStephan Aßmus PublisherInfo(BitmapRef(), publisherName, 63904c9d578SStephan Aßmus "", publisherURL), repoPackageInfo.Summary(), 64004c9d578SStephan Aßmus repoPackageInfo.Description(), 64104c9d578SStephan Aßmus repoPackageInfo.Flags(), 64204c9d578SStephan Aßmus repoPackageInfo.ArchitectureName()), 64304c9d578SStephan Aßmus true); 64404c9d578SStephan Aßmus 64504c9d578SStephan Aßmus if (modelInfo.Get() == NULL) 64604c9d578SStephan Aßmus return; 64704c9d578SStephan Aßmus 64804c9d578SStephan Aßmus foundPackages[repoPackageInfo.Name()] = modelInfo; 64904c9d578SStephan Aßmus } 65004c9d578SStephan Aßmus 65104c9d578SStephan Aßmus modelInfo->SetIcon(defaultIcon); 65204c9d578SStephan Aßmus modelInfo->AddListener(this); 65304c9d578SStephan Aßmus 65404c9d578SStephan Aßmus BSolverRepository* repository = package->Repository(); 65504c9d578SStephan Aßmus if (dynamic_cast<BPackageManager::RemoteRepository*>(repository) 65604c9d578SStephan Aßmus != NULL) { 65704c9d578SStephan Aßmus depots[repository->Name()].AddPackage(modelInfo); 65804c9d578SStephan Aßmus remotePackages[modelInfo->Title()] = modelInfo; 65904c9d578SStephan Aßmus } else { 66004c9d578SStephan Aßmus if (repository == static_cast<const BSolverRepository*>( 66104c9d578SStephan Aßmus manager.SystemRepository())) { 66204c9d578SStephan Aßmus modelInfo->AddInstallationLocation( 66304c9d578SStephan Aßmus B_PACKAGE_INSTALLATION_LOCATION_SYSTEM); 66404c9d578SStephan Aßmus if (!modelInfo->IsSystemPackage()) { 66504c9d578SStephan Aßmus systemInstalledPackages[repoPackageInfo.FileName()] 66604c9d578SStephan Aßmus = modelInfo; 66704c9d578SStephan Aßmus } 66804c9d578SStephan Aßmus } else if (repository == static_cast<const BSolverRepository*>( 66904c9d578SStephan Aßmus manager.HomeRepository())) { 67004c9d578SStephan Aßmus modelInfo->AddInstallationLocation( 67104c9d578SStephan Aßmus B_PACKAGE_INSTALLATION_LOCATION_HOME); 67204c9d578SStephan Aßmus } 67304c9d578SStephan Aßmus } 67404c9d578SStephan Aßmus 67504c9d578SStephan Aßmus if (modelInfo->IsSystemPackage()) 67604c9d578SStephan Aßmus systemFlaggedPackages.Add(repoPackageInfo.FileName()); 67704c9d578SStephan Aßmus } 67804c9d578SStephan Aßmus 67904c9d578SStephan Aßmus BAutolock lock(fModel.Lock()); 68004c9d578SStephan Aßmus 68104c9d578SStephan Aßmus fModel.Clear(); 68204c9d578SStephan Aßmus 68304c9d578SStephan Aßmus // filter remote packages from the found list 68404c9d578SStephan Aßmus // any packages remaining will be locally installed packages 68504c9d578SStephan Aßmus // that weren't acquired from a repository 68604c9d578SStephan Aßmus for (PackageInfoMap::iterator it = remotePackages.begin(); 68704c9d578SStephan Aßmus it != remotePackages.end(); it++) { 68804c9d578SStephan Aßmus foundPackages.erase(it->first); 68904c9d578SStephan Aßmus } 69004c9d578SStephan Aßmus 69104c9d578SStephan Aßmus if (!foundPackages.empty()) { 69204c9d578SStephan Aßmus BString repoName = B_TRANSLATE("Local"); 69304c9d578SStephan Aßmus depots[repoName] = DepotInfo(repoName); 69404c9d578SStephan Aßmus DepotInfoMap::iterator depot = depots.find(repoName); 69504c9d578SStephan Aßmus for (PackageInfoMap::iterator it = foundPackages.begin(); 69604c9d578SStephan Aßmus it != foundPackages.end(); ++it) { 69704c9d578SStephan Aßmus depot->second.AddPackage(it->second); 69804c9d578SStephan Aßmus } 69904c9d578SStephan Aßmus } 70004c9d578SStephan Aßmus 70104c9d578SStephan Aßmus for (DepotInfoMap::iterator it = depots.begin(); it != depots.end(); it++) { 70204c9d578SStephan Aßmus fModel.AddDepot(it->second); 70304c9d578SStephan Aßmus } 70404c9d578SStephan Aßmus 70504c9d578SStephan Aßmus // start retrieving package icons and average ratings 70604c9d578SStephan Aßmus fModel.PopulateAllPackages(); 70704c9d578SStephan Aßmus 70804c9d578SStephan Aßmus // compute the OS package dependencies 70904c9d578SStephan Aßmus try { 71004c9d578SStephan Aßmus // create the solver 71104c9d578SStephan Aßmus BSolver* solver; 71204c9d578SStephan Aßmus status_t error = BSolver::Create(solver); 71304c9d578SStephan Aßmus if (error != B_OK) 71404c9d578SStephan Aßmus throw BFatalErrorException(error, "Failed to create solver."); 71504c9d578SStephan Aßmus 71604c9d578SStephan Aßmus ObjectDeleter<BSolver> solverDeleter(solver); 71704c9d578SStephan Aßmus BPath systemPath; 71804c9d578SStephan Aßmus error = find_directory(B_SYSTEM_PACKAGES_DIRECTORY, &systemPath); 71904c9d578SStephan Aßmus if (error != B_OK) { 72004c9d578SStephan Aßmus throw BFatalErrorException(error, 72104c9d578SStephan Aßmus "Unable to retrieve system packages directory."); 72204c9d578SStephan Aßmus } 72304c9d578SStephan Aßmus 72404c9d578SStephan Aßmus // add the "installed" repository with the given packages 72504c9d578SStephan Aßmus BSolverRepository installedRepository; 72604c9d578SStephan Aßmus { 72704c9d578SStephan Aßmus BRepositoryBuilder installedRepositoryBuilder(installedRepository, 72804c9d578SStephan Aßmus "installed"); 72904c9d578SStephan Aßmus for (int32 i = 0; i < systemFlaggedPackages.CountStrings(); i++) { 73004c9d578SStephan Aßmus BPath packagePath(systemPath); 73104c9d578SStephan Aßmus packagePath.Append(systemFlaggedPackages.StringAt(i)); 73204c9d578SStephan Aßmus installedRepositoryBuilder.AddPackage(packagePath.Path()); 73304c9d578SStephan Aßmus } 73404c9d578SStephan Aßmus installedRepositoryBuilder.AddToSolver(solver, true); 73504c9d578SStephan Aßmus } 73604c9d578SStephan Aßmus 73704c9d578SStephan Aßmus // add system repository 73804c9d578SStephan Aßmus BSolverRepository systemRepository; 73904c9d578SStephan Aßmus { 74004c9d578SStephan Aßmus BRepositoryBuilder systemRepositoryBuilder(systemRepository, 74104c9d578SStephan Aßmus "system"); 74204c9d578SStephan Aßmus for (PackageInfoMap::iterator it = systemInstalledPackages.begin(); 74304c9d578SStephan Aßmus it != systemInstalledPackages.end(); it++) { 74404c9d578SStephan Aßmus BPath packagePath(systemPath); 74504c9d578SStephan Aßmus packagePath.Append(it->first); 74604c9d578SStephan Aßmus systemRepositoryBuilder.AddPackage(packagePath.Path()); 74704c9d578SStephan Aßmus } 74804c9d578SStephan Aßmus systemRepositoryBuilder.AddToSolver(solver, false); 74904c9d578SStephan Aßmus } 75004c9d578SStephan Aßmus 75104c9d578SStephan Aßmus // solve 75204c9d578SStephan Aßmus error = solver->VerifyInstallation(); 75304c9d578SStephan Aßmus if (error != B_OK) { 75404c9d578SStephan Aßmus throw BFatalErrorException(error, "Failed to compute packages to " 75504c9d578SStephan Aßmus "install."); 75604c9d578SStephan Aßmus } 75704c9d578SStephan Aßmus 75804c9d578SStephan Aßmus BSolverResult solverResult; 75904c9d578SStephan Aßmus error = solver->GetResult(solverResult); 76004c9d578SStephan Aßmus if (error != B_OK) { 76104c9d578SStephan Aßmus throw BFatalErrorException(error, "Failed to retrieve system " 76204c9d578SStephan Aßmus "package dependency list."); 76304c9d578SStephan Aßmus } 76404c9d578SStephan Aßmus 76504c9d578SStephan Aßmus for (int32 i = 0; const BSolverResultElement* element 76604c9d578SStephan Aßmus = solverResult.ElementAt(i); i++) { 76704c9d578SStephan Aßmus BSolverPackage* package = element->Package(); 76804c9d578SStephan Aßmus if (element->Type() == BSolverResultElement::B_TYPE_INSTALL) { 76904c9d578SStephan Aßmus PackageInfoMap::iterator it = systemInstalledPackages.find( 77004c9d578SStephan Aßmus package->Info().FileName()); 77104c9d578SStephan Aßmus if (it != systemInstalledPackages.end()) 77204c9d578SStephan Aßmus it->second->SetSystemDependency(true); 77304c9d578SStephan Aßmus } 77404c9d578SStephan Aßmus } 77504c9d578SStephan Aßmus } catch (BFatalErrorException ex) { 77604c9d578SStephan Aßmus printf("Fatal exception occurred while resolving system dependencies: " 77704c9d578SStephan Aßmus "%s, details: %s\n", strerror(ex.Error()), ex.Details().String()); 77804c9d578SStephan Aßmus } catch (BNothingToDoException) { 77904c9d578SStephan Aßmus // do nothing 78004c9d578SStephan Aßmus } catch (BException ex) { 78104c9d578SStephan Aßmus printf("Exception occurred while resolving system dependencies: %s\n", 78204c9d578SStephan Aßmus ex.Message().String()); 78304c9d578SStephan Aßmus } catch (...) { 78404c9d578SStephan Aßmus printf("Unknown exception occurred while resolving system " 78504c9d578SStephan Aßmus "dependencies.\n"); 78604c9d578SStephan Aßmus } 78704c9d578SStephan Aßmus } 78804c9d578SStephan Aßmus 78904c9d578SStephan Aßmus 79004c9d578SStephan Aßmus void 79104c9d578SStephan Aßmus MainWindow::_StartRefreshWorker(bool force) 79204c9d578SStephan Aßmus { 79304c9d578SStephan Aßmus if (fModelWorker != B_BAD_THREAD_ID) 79404c9d578SStephan Aßmus return; 79504c9d578SStephan Aßmus 79604c9d578SStephan Aßmus RefreshWorkerParameters* parameters = new(std::nothrow) 79704c9d578SStephan Aßmus RefreshWorkerParameters(this, force); 79804c9d578SStephan Aßmus if (parameters == NULL) 79904c9d578SStephan Aßmus return; 80004c9d578SStephan Aßmus 80104c9d578SStephan Aßmus ObjectDeleter<RefreshWorkerParameters> deleter(parameters); 80204c9d578SStephan Aßmus fModelWorker = spawn_thread(&_RefreshModelThreadWorker, "model loader", 80304c9d578SStephan Aßmus B_LOW_PRIORITY, parameters); 80404c9d578SStephan Aßmus 80504c9d578SStephan Aßmus if (fModelWorker > 0) { 80604c9d578SStephan Aßmus deleter.Detach(); 80704c9d578SStephan Aßmus resume_thread(fModelWorker); 80804c9d578SStephan Aßmus } 80904c9d578SStephan Aßmus } 81004c9d578SStephan Aßmus 81104c9d578SStephan Aßmus 81204c9d578SStephan Aßmus status_t 81304c9d578SStephan Aßmus MainWindow::_RefreshModelThreadWorker(void* arg) 81404c9d578SStephan Aßmus { 81504c9d578SStephan Aßmus RefreshWorkerParameters* parameters 81604c9d578SStephan Aßmus = reinterpret_cast<RefreshWorkerParameters*>(arg); 81704c9d578SStephan Aßmus MainWindow* mainWindow = parameters->window; 81804c9d578SStephan Aßmus ObjectDeleter<RefreshWorkerParameters> deleter(parameters); 81904c9d578SStephan Aßmus 82004c9d578SStephan Aßmus BMessenger messenger(mainWindow); 82104c9d578SStephan Aßmus 82204c9d578SStephan Aßmus mainWindow->_RefreshRepositories(parameters->forceRefresh); 82304c9d578SStephan Aßmus 82404c9d578SStephan Aßmus if (mainWindow->fTerminating) 82504c9d578SStephan Aßmus return B_OK; 82604c9d578SStephan Aßmus 82704c9d578SStephan Aßmus mainWindow->_RefreshPackageList(); 82804c9d578SStephan Aßmus 82904c9d578SStephan Aßmus messenger.SendMessage(MSG_MODEL_WORKER_DONE); 83004c9d578SStephan Aßmus 83104c9d578SStephan Aßmus return B_OK; 83204c9d578SStephan Aßmus } 83304c9d578SStephan Aßmus 83404c9d578SStephan Aßmus 83504c9d578SStephan Aßmus status_t 83604c9d578SStephan Aßmus MainWindow::_PackageActionWorker(void* arg) 83704c9d578SStephan Aßmus { 83804c9d578SStephan Aßmus MainWindow* window = reinterpret_cast<MainWindow*>(arg); 83904c9d578SStephan Aßmus 84004c9d578SStephan Aßmus while (acquire_sem(window->fPendingActionsSem) == B_OK) { 84104c9d578SStephan Aßmus PackageActionRef ref; 84204c9d578SStephan Aßmus { 84304c9d578SStephan Aßmus AutoLocker<BLocker> lock(&window->fPendingActionsLock); 84404c9d578SStephan Aßmus ref = window->fPendingActions.ItemAt(0); 84504c9d578SStephan Aßmus if (ref.Get() == NULL) 84604c9d578SStephan Aßmus break; 84704c9d578SStephan Aßmus window->fPendingActions.Remove(0); 84804c9d578SStephan Aßmus } 84904c9d578SStephan Aßmus 85004c9d578SStephan Aßmus ref->Perform(); 85104c9d578SStephan Aßmus } 85204c9d578SStephan Aßmus 85304c9d578SStephan Aßmus return 0; 85404c9d578SStephan Aßmus } 85504c9d578SStephan Aßmus 85604c9d578SStephan Aßmus 85704c9d578SStephan Aßmus status_t 85804c9d578SStephan Aßmus MainWindow::_PopulatePackageWorker(void* arg) 85904c9d578SStephan Aßmus { 86004c9d578SStephan Aßmus MainWindow* window = reinterpret_cast<MainWindow*>(arg); 86104c9d578SStephan Aßmus 86204c9d578SStephan Aßmus while (acquire_sem(window->fPackageToPopulateSem) == B_OK) { 86304c9d578SStephan Aßmus PackageInfoRef package; 86404c9d578SStephan Aßmus { 86504c9d578SStephan Aßmus AutoLocker<BLocker> lock(&window->fPackageToPopulateLock); 86604c9d578SStephan Aßmus package = window->fPackageToPopulate; 86704c9d578SStephan Aßmus } 86804c9d578SStephan Aßmus 86904c9d578SStephan Aßmus if (package.Get() != NULL) { 87004c9d578SStephan Aßmus window->fModel.PopulatePackage(package, 87104c9d578SStephan Aßmus Model::POPULATE_USER_RATINGS | Model::POPULATE_SCREEN_SHOTS 87204c9d578SStephan Aßmus | Model::POPULATE_CHANGELOG); 87304c9d578SStephan Aßmus } 87404c9d578SStephan Aßmus } 87504c9d578SStephan Aßmus 87604c9d578SStephan Aßmus return 0; 87704c9d578SStephan Aßmus } 87804c9d578SStephan Aßmus 87904c9d578SStephan Aßmus 88004c9d578SStephan Aßmus void 88104c9d578SStephan Aßmus MainWindow::_NotifyUser(const char* title, const char* message) 88204c9d578SStephan Aßmus { 88304c9d578SStephan Aßmus BAlert *alert = new(std::nothrow) BAlert(title, message, 88404c9d578SStephan Aßmus B_TRANSLATE("Close")); 88504c9d578SStephan Aßmus 88604c9d578SStephan Aßmus if (alert != NULL) 88704c9d578SStephan Aßmus alert->Go(); 88804c9d578SStephan Aßmus } 88904c9d578SStephan Aßmus 89004c9d578SStephan Aßmus 89104c9d578SStephan Aßmus void 892*1bbda92dSStephan Aßmus MainWindow::_OpenLoginWindow(const BMessage& onSuccessMessage) 89304c9d578SStephan Aßmus { 89404c9d578SStephan Aßmus UserLoginWindow* window = new UserLoginWindow(this, 89504c9d578SStephan Aßmus BRect(0, 0, 500, 400), fModel); 896*1bbda92dSStephan Aßmus 897*1bbda92dSStephan Aßmus if (onSuccessMessage.what != 0) 898*1bbda92dSStephan Aßmus window->SetOnSuccessMessage(BMessenger(this), onSuccessMessage); 899*1bbda92dSStephan Aßmus 90004c9d578SStephan Aßmus window->Show(); 90104c9d578SStephan Aßmus } 90204c9d578SStephan Aßmus 9038f03a0f9SStephan Aßmus 9048f03a0f9SStephan Aßmus void 9058f03a0f9SStephan Aßmus MainWindow::_UpdateAuthorization() 9068f03a0f9SStephan Aßmus { 9078f03a0f9SStephan Aßmus BString username(fModel.Username()); 9088f03a0f9SStephan Aßmus fLogOutItem->SetEnabled(username.Length() > 0); 9098f03a0f9SStephan Aßmus fFilterView->SetUsername(username); 9108f03a0f9SStephan Aßmus } 911*1bbda92dSStephan Aßmus 912*1bbda92dSStephan Aßmus 913*1bbda92dSStephan Aßmus void 914*1bbda92dSStephan Aßmus MainWindow::_RatePackage() 915*1bbda92dSStephan Aßmus { 916*1bbda92dSStephan Aßmus if (fModel.Username().IsEmpty()) { 917*1bbda92dSStephan Aßmus BAlert* alert = new(std::nothrow) BAlert( 918*1bbda92dSStephan Aßmus B_TRANSLATE("Not logged in"), 919*1bbda92dSStephan Aßmus B_TRANSLATE("You need to be logged into an account before you " 920*1bbda92dSStephan Aßmus "can rate packages."), 921*1bbda92dSStephan Aßmus B_TRANSLATE("Cancel"), 922*1bbda92dSStephan Aßmus B_TRANSLATE("Login or Create account")); 923*1bbda92dSStephan Aßmus 924*1bbda92dSStephan Aßmus if (alert == NULL) 925*1bbda92dSStephan Aßmus return; 926*1bbda92dSStephan Aßmus 927*1bbda92dSStephan Aßmus int32 choice = alert->Go(); 928*1bbda92dSStephan Aßmus if (choice == 1) 929*1bbda92dSStephan Aßmus _OpenLoginWindow(BMessage(MSG_RATE_PACKAGE)); 930*1bbda92dSStephan Aßmus return; 931*1bbda92dSStephan Aßmus } 932*1bbda92dSStephan Aßmus 933*1bbda92dSStephan Aßmus // TODO: Allow only one RatePackageWindow 934*1bbda92dSStephan Aßmus // TODO: Mechanism for remembering the window frame 935*1bbda92dSStephan Aßmus RatePackageWindow* window = new RatePackageWindow(this, 936*1bbda92dSStephan Aßmus BRect(0, 0, 500, 400), fModel); 937*1bbda92dSStephan Aßmus window->SetPackage(fPackageInfoView->Package()); 938*1bbda92dSStephan Aßmus window->Show(); 939*1bbda92dSStephan Aßmus } 940