From e550d7b8c563b9276ba9d8bd86b7ab41ec729836 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Sat, 21 Sep 2013 14:27:12 -0400 Subject: [PATCH] HaikuDepot: Miscellanous improvements to package state tracking. - MainWindow now listens for package installation state changes so it can keep Model's package location lists in sync. - PackageListView now updates its status column on package state changes. - PackageInfoView now updates the available action list when package installation state changes. - PackageManager populates the expected user-specified install/uninstall package sets for ProblemWindow so that one can properly filter those out. There still remain some issues with the installed locations for ResultWindow not being entirely correct though, which causes issues for package uninstallation. --- src/apps/haiku-depot/MainWindow.cpp | 29 ++++- src/apps/haiku-depot/MainWindow.h | 9 +- src/apps/haiku-depot/PackageInfoView.cpp | 10 +- src/apps/haiku-depot/PackageListView.cpp | 28 ++-- src/apps/haiku-depot/PackageManager.cpp | 157 ++++++++++++++++------- src/apps/haiku-depot/PackageManager.h | 26 +++- 6 files changed, 193 insertions(+), 66 deletions(-) diff --git a/src/apps/haiku-depot/MainWindow.cpp b/src/apps/haiku-depot/MainWindow.cpp index 82ee4a95ac..24a131f64c 100644 --- a/src/apps/haiku-depot/MainWindow.cpp +++ b/src/apps/haiku-depot/MainWindow.cpp @@ -43,7 +43,8 @@ enum { MSG_MODEL_WORKER_DONE = 'mmwd', - MSG_REFRESH_DEPOTS = 'mrdp' + MSG_REFRESH_DEPOTS = 'mrdp', + MSG_PACKAGE_STATE_CHANGED = 'mpsc' }; @@ -197,6 +198,16 @@ MainWindow::MessageReceived(BMessage* message) searchTerms = ""; fModel.SetSearchTerms(searchTerms); _AdoptModel(); + break; + } + + case MSG_PACKAGE_STATE_CHANGED: + { + PackageInfo* info; + if (message->FindPointer("package", (void **)&info) == B_OK) { + PackageInfoRef ref(info, true); + fModel.SetPackageState(ref, ref->State()); + } } default: @@ -206,6 +217,20 @@ MainWindow::MessageReceived(BMessage* message) } +void +MainWindow::PackageChanged(const PackageInfoEvent& event) +{ + if ((event.Changes() & PKG_CHANGED_STATE) != 0) { + PackageInfoRef ref(event.Package()); + BMessage message(MSG_PACKAGE_STATE_CHANGED); + message.AddPointer("package", ref.Get()); + ref.Detach(); + // reference needs to be released by MessageReceived(); + PostMessage(&message); + } +} + + void MainWindow::_BuildMenu(BMenuBar* menuBar) { @@ -367,6 +392,8 @@ MainWindow::_RefreshPackageList() foundPackages[repoPackageInfo.Name()] = modelInfo; } + modelInfo->AddListener(this); + BSolverRepository* repository = package->Repository(); if (dynamic_cast(repository) != NULL) { diff --git a/src/apps/haiku-depot/MainWindow.h b/src/apps/haiku-depot/MainWindow.h index da6aedfcec..8ceb0641b6 100644 --- a/src/apps/haiku-depot/MainWindow.h +++ b/src/apps/haiku-depot/MainWindow.h @@ -1,5 +1,6 @@ /* * Copyright 2013, Stephan Aßmus . + * Copyright 2013, Rene Gollent . * All rights reserved. Distributed under the terms of the MIT License. */ #ifndef MAIN_WINDOW_H @@ -8,6 +9,7 @@ #include #include "Model.h" +#include "PackageInfoListener.h" #include "PackageManager.h" @@ -22,7 +24,7 @@ enum { }; -class MainWindow : public BWindow { +class MainWindow : public BWindow, private PackageInfoListener { public: MainWindow(BRect frame); virtual ~MainWindow(); @@ -31,6 +33,11 @@ public: virtual bool QuitRequested(); virtual void MessageReceived(BMessage* message); +private: + // PackageInfoListener + virtual void PackageChanged( + const PackageInfoEvent& event); + private: void _BuildMenu(BMenuBar* menuBar); void _AdoptModel(); diff --git a/src/apps/haiku-depot/PackageInfoView.cpp b/src/apps/haiku-depot/PackageInfoView.cpp index 0244894cf4..12451c52bb 100644 --- a/src/apps/haiku-depot/PackageInfoView.cpp +++ b/src/apps/haiku-depot/PackageInfoView.cpp @@ -521,7 +521,7 @@ public: if (result != B_OK) { fprintf(stderr, "Failed to schedule action: " "%s '%s'\n", action->Label(), - action->Package().Title().String()); + action->Package()->Title().String()); } } } @@ -538,7 +538,8 @@ public: { Clear(); - fPackageActions = fPackageManager->GetPackageActions(package); + fPackageActions = fPackageManager->GetPackageActions( + const_cast(&package)); // Add Buttons in reverse action order for (int32 i = fPackageActions.CountItems() - 1; i >= 0; i--) { @@ -1280,8 +1281,11 @@ PackageInfoView::MessageReceived(BMessage* message) fTitleView->SetPackage(package); } - if ((changes & PKG_CHANGED_RATINGS) != 0) { + if ((changes & PKG_CHANGED_RATINGS) != 0) fPagesView->SetPackage(package); + + if ((changes & PKG_CHANGED_STATE) != 0) { + fPackageActionView->SetPackage(package); } break; diff --git a/src/apps/haiku-depot/PackageListView.cpp b/src/apps/haiku-depot/PackageListView.cpp index 348b50191a..cfbb40931b 100644 --- a/src/apps/haiku-depot/PackageListView.cpp +++ b/src/apps/haiku-depot/PackageListView.cpp @@ -112,6 +112,7 @@ public: const PackageInfoRef& Package() const { return fPackage; } + void UpdateState(); void UpdateRating(); private: @@ -139,9 +140,6 @@ public: virtual void PackageChanged(const PackageInfoEvent& event) { - if ((event.Changes() & PKG_CHANGED_RATINGS) == 0) - return; - BMessenger messenger(fView); if (!messenger.IsValid()) return; @@ -489,6 +487,17 @@ PackageRow::~PackageRow() } +void +PackageRow::UpdateState() +{ + if (fPackage.Get() == NULL) + return; + + BStringField* field = (BStringField*)GetField(kStatusColumn); + field->SetString(package_state_to_string(fPackage->State())); +} + + void PackageRow::UpdateRating() { @@ -634,15 +643,14 @@ PackageListView::MessageReceived(BMessage* message) break; } - if ((changes & PKG_CHANGED_RATINGS) == 0) - break; - BAutolock _(fModelLock); - PackageRow* row = _FindRow(title); - if (row != NULL) - row->UpdateRating(); - + if (row != NULL) { + if ((changes & PKG_CHANGED_RATINGS) != 0) + row->UpdateRating(); + if ((changes & PKG_CHANGED_STATE) != 0) + row->UpdateState(); + } break; } diff --git a/src/apps/haiku-depot/PackageManager.cpp b/src/apps/haiku-depot/PackageManager.cpp index 5ed1474ca9..c3bc229a35 100644 --- a/src/apps/haiku-depot/PackageManager.cpp +++ b/src/apps/haiku-depot/PackageManager.cpp @@ -24,6 +24,7 @@ #include "AutoDeleter.h" #include "AutoLocker.h" +#include "PackageInfo.h" #include "ProblemWindow.h" #include "ResultWindow.h" @@ -44,7 +45,7 @@ using BPackageKit::BSolverRepository; // #pragma mark - PackageAction -PackageAction::PackageAction(const PackageInfo& package, +PackageAction::PackageAction(PackageInfoRef package, PackageManager* manager) : fPackageManager(manager), @@ -63,7 +64,7 @@ PackageAction::~PackageAction() class InstallPackageAction : public PackageAction { public: - InstallPackageAction(const PackageInfo& package, PackageManager* manager) + InstallPackageAction(PackageInfoRef package, PackageManager* manager) : PackageAction(package, manager) { @@ -76,7 +77,9 @@ public: virtual status_t Perform() { - const char* packageName = Package().Title().String(); + PackageInfoRef ref(Package()); + fPackageManager->SetCurrentActionPackage(ref, true); + const char* packageName = ref->Title().String(); try { fPackageManager->Install(&packageName, 1); } catch (BFatalErrorException ex) { @@ -84,11 +87,17 @@ public: "%s: %s (%s)\n", packageName, ex.Message().String(), ex.Details().String()); return ex.Error(); + } catch (BAbortedByUserException ex) { + return B_OK; + } catch (BNothingToDoException ex) { } catch (BException ex) { fprintf(stderr, "Exception occurred while installing package " "%s: %s\n", packageName, ex.Message().String()); + return B_ERROR;; } + ref->SetState(ACTIVATED); + return B_OK; } }; @@ -99,7 +108,7 @@ public: class UninstallPackageAction : public PackageAction { public: - UninstallPackageAction(const PackageInfo& package, PackageManager* manager) + UninstallPackageAction(PackageInfoRef package, PackageManager* manager) : PackageAction(package, manager) { @@ -112,7 +121,9 @@ public: virtual status_t Perform() { - const char* packageName = Package().Title().String(); + PackageInfoRef ref(Package()); + fPackageManager->SetCurrentActionPackage(ref, false); + const char* packageName = ref->Title().String(); try { fPackageManager->Uninstall(&packageName, 1); } catch (BFatalErrorException ex) { @@ -120,11 +131,15 @@ public: "%s: %s (%s)\n", packageName, ex.Message().String(), ex.Details().String()); return ex.Error(); - } catch (BException ex) { + } catch (BAbortedByUserException ex) { + } catch (BNothingToDoException ex) { fprintf(stderr, "Exception occurred while uninstalling package " "%s: %s\n", packageName, ex.Message().String()); + return B_ERROR; } + ref->SetState(NONE); + return B_OK; } }; @@ -141,7 +156,9 @@ PackageManager::PackageManager(BPackageInstallationLocation location) fJobStateListener(), fContext(fDecisionProvider, fJobStateListener), fClientInstallationInterface(), - fProblemWindow(NULL) + fProblemWindow(NULL), + fCurrentInstallPackage(NULL), + fCurrentUninstallPackage(NULL) { fInstallationInterface = &fClientInstallationInterface; fRequestHandler = this; @@ -178,47 +195,40 @@ PackageManager::GetPackageState(const PackageInfo& package) PackageActionList -PackageManager::GetPackageActions(const PackageInfo& package) +PackageManager::GetPackageActions(PackageInfoRef package) { PackageActionList actionList; - BObjectList packages; - status_t result = Solver()->FindPackages(package.Title(), - BSolver::B_FIND_IN_NAME, packages); - if (result == B_OK) { - bool installed = false; - bool systemPackage = false; - for (int32 i = 0; i < packages.CountItems(); i++) { - const BSolverPackage* solverPackage = packages.ItemAt(i); - if (solverPackage->Name() != package.Title()) - continue; + bool installed = false; + bool systemPackage = false; + BSolverPackage* solverPackage = _GetSolverPackage(package); + if (solverPackage == NULL) + return actionList; - const BSolverRepository* repository = solverPackage->Repository(); - if (repository == static_cast( - SystemRepository())) { - installed = true; - systemPackage = true; - } else if (repository == static_cast( - CommonRepository())) { - installed = true; - } else if (repository == static_cast( - HomeRepository())) { - installed = true; - } - } - - if (installed) { - if (!systemPackage) { - actionList.Add(PackageActionRef(new UninstallPackageAction( - package, this), true)); - } - } else { - actionList.Add(PackageActionRef(new InstallPackageAction(package, - this), true)); - } - // TODO: activation status + const BSolverRepository* repository = solverPackage->Repository(); + if (repository == static_cast( + SystemRepository())) { + installed = true; + systemPackage = true; + } else if (repository == static_cast( + CommonRepository())) { + installed = true; + } else if (repository == static_cast( + HomeRepository())) { + installed = true; } + if (installed) { + if (!systemPackage) { + actionList.Add(PackageActionRef(new UninstallPackageAction( + package, this), true)); + } + } else { + actionList.Add(PackageActionRef(new InstallPackageAction(package, + this), true)); + } + // TODO: activation status + return actionList; } @@ -237,6 +247,27 @@ PackageManager::SchedulePackageActions(PackageActionList& list) } +void +PackageManager::SetCurrentActionPackage(PackageInfoRef package, bool install) +{ + BSolverPackage* solverPackage = _GetSolverPackage(package); + if (solverPackage == NULL) + ClearCurrentActionPackage(); + else { + fCurrentInstallPackage = install ? solverPackage : NULL; + fCurrentUninstallPackage = install ? NULL : solverPackage; + } +} + + +void +PackageManager::ClearCurrentActionPackage() +{ + fCurrentInstallPackage = NULL; + fCurrentUninstallPackage = NULL; +} + + status_t PackageManager::RefreshRepository(const BRepositoryConfig& repoConfig) { @@ -286,8 +317,15 @@ PackageManager::HandleProblems() if (fProblemWindow == NULL) fProblemWindow = new ProblemWindow; - ProblemWindow::SolverPackageSet dummy; - if (!fProblemWindow->Go(fSolver,dummy, dummy)) + ProblemWindow::SolverPackageSet installPackages; + ProblemWindow::SolverPackageSet uninstallPackages; + if (fCurrentInstallPackage != NULL) + installPackages.insert(fCurrentInstallPackage); + + if (fCurrentUninstallPackage != NULL) + uninstallPackages.insert(fCurrentInstallPackage); + + if (!fProblemWindow->Go(fSolver,installPackages, uninstallPackages)) throw BAbortedByUserException(); } @@ -364,6 +402,7 @@ PackageManager::_PackageActionWorker(void* arg) } ref->Perform(); + manager->ClearCurrentActionPackage(); } return 0; @@ -377,10 +416,34 @@ PackageManager::_AddResults(InstalledRepository& repository, if (!repository.HasChanges()) return false; - ProblemWindow::SolverPackageSet dummy; + ProblemWindow::SolverPackageSet installPackages; + ProblemWindow::SolverPackageSet uninstallPackages; + if (fCurrentInstallPackage != NULL) + installPackages.insert(fCurrentInstallPackage); + + if (fCurrentUninstallPackage != NULL) + uninstallPackages.insert(fCurrentInstallPackage); + return window->AddLocationChanges(repository.Name(), - repository.PackagesToActivate(), dummy, - repository.PackagesToDeactivate(), dummy); + repository.PackagesToActivate(), installPackages, + repository.PackagesToDeactivate(), uninstallPackages); } +BSolverPackage* +PackageManager::_GetSolverPackage(PackageInfoRef package) +{ + BObjectList packages; + status_t result = Solver()->FindPackages(package->Title(), + BSolver::B_FIND_IN_NAME, packages); + if (result == B_OK) { + for (int32 i = 0; i < packages.CountItems(); i++) { + BSolverPackage* solverPackage = packages.ItemAt(i); + if (solverPackage->Name() != package->Title()) + continue; + return solverPackage; + } + } + + return NULL; +} diff --git a/src/apps/haiku-depot/PackageManager.h b/src/apps/haiku-depot/PackageManager.h index 141fbf7c89..01e55f3c79 100644 --- a/src/apps/haiku-depot/PackageManager.h +++ b/src/apps/haiku-depot/PackageManager.h @@ -18,6 +18,11 @@ #include "PackageInfo.h" +namespace BPackageKit { + class BSolverPackage; +} + + class PackageManager; class ProblemWindow; class ResultWindow; @@ -25,7 +30,7 @@ class ResultWindow; class PackageAction : public BReferenceable { public: - PackageAction(const PackageInfo& package, + PackageAction(PackageInfoRef package, PackageManager* manager); virtual ~PackageAction(); @@ -36,14 +41,14 @@ public: // Package Kit supports this stuff already. virtual status_t Perform() = 0; - const PackageInfo& Package() const + PackageInfoRef Package() const { return fPackage; } protected: PackageManager* fPackageManager; private: - PackageInfo fPackage; + PackageInfoRef fPackage; }; @@ -66,11 +71,17 @@ public: virtual ~PackageManager(); virtual PackageState GetPackageState(const PackageInfo& package); - virtual PackageActionList GetPackageActions(const PackageInfo& package); + virtual PackageActionList GetPackageActions(PackageInfoRef package); status_t SchedulePackageActions( PackageActionList& list); + void SetCurrentActionPackage( + PackageInfoRef package, + bool install); + + void ClearCurrentActionPackage(); + private: // RequestHandler virtual status_t RefreshRepository( @@ -101,6 +112,9 @@ private: repository, ResultWindow* window); + BPackageKit::BSolverPackage* + _GetSolverPackage(PackageInfoRef package); + private: DecisionProvider fDecisionProvider; JobStateListener fJobStateListener; @@ -113,6 +127,10 @@ private: BLocker fPendingActionsLock; sem_id fPendingActionsSem; ProblemWindow* fProblemWindow; + BPackageKit::BSolverPackage* + fCurrentInstallPackage; + BPackageKit::BSolverPackage* + fCurrentUninstallPackage; }; #endif // PACKAGE_MANAGER_H