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