diff --git a/src/apps/haikudepot/FilterView.cpp b/src/apps/haikudepot/FilterView.cpp index d85d0ddccf..b57264b131 100644 --- a/src/apps/haikudepot/FilterView.cpp +++ b/src/apps/haikudepot/FilterView.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -36,15 +37,27 @@ add_categories_to_menu(const CategoryList& categories, BMenu* menu) } +static BCheckBox* +create_check_box(const char* label, const char* name) +{ + BMessage* message = new BMessage(MSG_FILTER_SELECTED); + message->AddString("name", name); + BCheckBox* checkBox = new BCheckBox(label, message); + BFont font; + checkBox->GetFont(&font); + font.SetSize(ceilf(font.Size() * 0.75)); + checkBox->SetFont(&font); + return checkBox; +} + + FilterView::FilterView() : - BGroupView("filter view") + BGroupView("filter view", B_VERTICAL) { // Contruct category popup - BPopUpMenu* categoryMenu = new BPopUpMenu(B_TRANSLATE("Show")); - - fShowField = new BMenuField("category", B_TRANSLATE("Show:"), - categoryMenu); + BPopUpMenu* showMenu = new BPopUpMenu(B_TRANSLATE("Category")); + fShowField = new BMenuField("category", B_TRANSLATE("Category:"), showMenu); // Construct repository popup BPopUpMenu* repositoryMenu = new BPopUpMenu(B_TRANSLATE("Depot")); @@ -67,15 +80,34 @@ FilterView::FilterView() float maxSearchWidth = minSearchWidth * 2; fSearchTermsText->SetExplicitMaxSize(BSize(maxSearchWidth, B_SIZE_UNSET)); + // Construct check boxen + fAvailableCheckBox = create_check_box( + B_TRANSLATE("Available"), "available"); + fInstalledCheckBox = create_check_box( + B_TRANSLATE("Installed"), "installed"); + fDevelopmentCheckBox = create_check_box( + B_TRANSLATE("Development"), "development"); + fSourceCodeCheckBox = create_check_box( + B_TRANSLATE("Source code"), "source code"); + // Build layout BLayoutBuilder::Group<>(this) - .AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING, 1.2f) - .Add(fShowField, 0.0f) - .Add(fRepositoryField, 0.0f) - .SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)) + .AddGroup(B_HORIZONTAL) + .AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING, 1.2f) + .Add(fShowField, 0.0f) + .Add(fRepositoryField, 0.0f) + .SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)) + .End() + .AddGlue(0.5f) + .Add(fSearchTermsText, 1.0f) + .End() + .AddGroup(B_HORIZONTAL) + .Add(fAvailableCheckBox) + .Add(fInstalledCheckBox) + .Add(fDevelopmentCheckBox) + .Add(fSourceCodeCheckBox) + .AddGlue(0.5f) .End() - .AddGlue(0.5f) - .Add(fSearchTermsText, 1.0f) .SetInsets(B_USE_DEFAULT_SPACING) ; @@ -95,6 +127,11 @@ FilterView::AttachedToWindow() fSearchTermsText->SetTarget(this); fSearchTermsText->MakeFocus(); + + fAvailableCheckBox->SetTarget(Window()); + fInstalledCheckBox->SetTarget(Window()); + fDevelopmentCheckBox->SetTarget(Window()); + fSourceCodeCheckBox->SetTarget(Window()); } @@ -138,17 +175,28 @@ FilterView::AdoptModel(const Model& model) repositoryMenu->AddItem(item); } - BMenu* categoryMenu = fShowField->Menu(); - categoryMenu->RemoveItems(0, categoryMenu->CountItems(), true); + BMenu* showMenu = fShowField->Menu(); + showMenu->RemoveItems(0, showMenu->CountItems(), true); - categoryMenu->AddItem(new BMenuItem(B_TRANSLATE("All packages"), + showMenu->AddItem(new BMenuItem(B_TRANSLATE("All categories"), new BMessage(MSG_CATEGORY_SELECTED))); - categoryMenu->AddItem(new BSeparatorItem()); - add_categories_to_menu(model.Categories(), categoryMenu); - categoryMenu->AddItem(new BSeparatorItem()); - add_categories_to_menu(model.UserCategories(), categoryMenu); - categoryMenu->AddItem(new BSeparatorItem()); - add_categories_to_menu(model.ProgressCategories(), categoryMenu); - categoryMenu->ItemAt(0)->SetMarked(true); + showMenu->AddItem(new BSeparatorItem()); + + add_categories_to_menu(model.Categories(), showMenu); + + showMenu->ItemAt(0)->SetMarked(true); + + AdoptCheckmarks(model); } + + +void +FilterView::AdoptCheckmarks(const Model& model) +{ + fAvailableCheckBox->SetValue(model.ShowAvailablePackages()); + fInstalledCheckBox->SetValue(model.ShowInstalledPackages()); + fDevelopmentCheckBox->SetValue(model.ShowDevelopPackages()); + fSourceCodeCheckBox->SetValue(model.ShowSourcePackages()); +} + diff --git a/src/apps/haikudepot/FilterView.h b/src/apps/haikudepot/FilterView.h index d6baf4eec6..78ae76a55a 100644 --- a/src/apps/haikudepot/FilterView.h +++ b/src/apps/haikudepot/FilterView.h @@ -8,6 +8,7 @@ #include +class BCheckBox; class BMenuField; class BTextControl; class Model; @@ -15,6 +16,7 @@ class Model; enum { MSG_CATEGORY_SELECTED = 'ctsl', + MSG_FILTER_SELECTED = 'ftsl', MSG_DEPOT_SELECTED = 'dpsl', MSG_SEARCH_TERMS_MODIFIED = 'stmd', }; @@ -29,11 +31,17 @@ public: virtual void MessageReceived(BMessage* message); virtual void AdoptModel(const Model& model); + virtual void AdoptCheckmarks(const Model& model); private: BMenuField* fShowField; BMenuField* fRepositoryField; BTextControl* fSearchTermsText; + + BCheckBox* fAvailableCheckBox; + BCheckBox* fInstalledCheckBox; + BCheckBox* fDevelopmentCheckBox; + BCheckBox* fSourceCodeCheckBox; }; #endif // FILTER_VIEW_H diff --git a/src/apps/haikudepot/MainWindow.cpp b/src/apps/haikudepot/MainWindow.cpp index a2b9051787..7f2ab16d74 100644 --- a/src/apps/haikudepot/MainWindow.cpp +++ b/src/apps/haikudepot/MainWindow.cpp @@ -246,7 +246,40 @@ MainWindow::MessageReceived(BMessage* message) BString name; if (message->FindString("name", &name) != B_OK) name = ""; - fModel.SetCategory(name); + { + BAutolock locker(fModel.Lock()); + fModel.SetCategory(name); + } + _AdoptModel(); + break; + } + + case MSG_FILTER_SELECTED: + { + BString name; + int32 value; + if (message->FindString("name", &name) != B_OK + || message->FindInt32("be:value", &value) != B_OK) { + break; + } + { + BAutolock locker(fModel.Lock()); + if (name == "available") { + fModel.SetShowAvailablePackages( + value == B_CONTROL_ON); + } else if (name == "installed") { + fModel.SetShowInstalledPackages( + value == B_CONTROL_ON); + } else if (name == "development") { + fModel.SetShowDevelopPackages( + value == B_CONTROL_ON); + } else if (name == "source code") { + fModel.SetShowSourcePackages( + value == B_CONTROL_ON); + } else { + break; + } + } _AdoptModel(); break; } @@ -256,7 +289,10 @@ MainWindow::MessageReceived(BMessage* message) BString name; if (message->FindString("name", &name) != B_OK) name = ""; - fModel.SetDepot(name); + { + BAutolock locker(fModel.Lock()); + fModel.SetDepot(name); + } _AdoptModel(); break; } @@ -267,7 +303,10 @@ MainWindow::MessageReceived(BMessage* message) BString searchTerms; if (message->FindString("search terms", &searchTerms) != B_OK) searchTerms = ""; - fModel.SetSearchTerms(searchTerms); + { + BAutolock locker(fModel.Lock()); + fModel.SetSearchTerms(searchTerms); + } _AdoptModel(); break; } @@ -277,6 +316,7 @@ MainWindow::MessageReceived(BMessage* message) PackageInfo* info; if (message->FindPointer("package", (void**)&info) == B_OK) { PackageInfoRef ref(info, true); + BAutolock locker(fModel.Lock()); fModel.SetPackageState(ref, ref->State()); } break; @@ -356,18 +396,18 @@ MainWindow::_BuildMenu(BMenuBar* menuBar) new BMessage(MSG_REFRESH_DEPOTS))); menuBar->AddItem(menu); - menu = new BMenu(B_TRANSLATE("Options")); - - fShowDevelopPackagesItem = new BMenuItem( - B_TRANSLATE("Show develop packages"), - new BMessage(MSG_SHOW_DEVELOP_PACKAGES)); - menu->AddItem(fShowDevelopPackagesItem); - - fShowSourcePackagesItem = new BMenuItem(B_TRANSLATE("Show source packages"), - new BMessage(MSG_SHOW_SOURCE_PACKAGES)); - menu->AddItem(fShowSourcePackagesItem); - - menuBar->AddItem(menu); +// menu = new BMenu(B_TRANSLATE("Options")); +// +// fShowDevelopPackagesItem = new BMenuItem( +// B_TRANSLATE("Show develop packages"), +// new BMessage(MSG_SHOW_DEVELOP_PACKAGES)); +// menu->AddItem(fShowDevelopPackagesItem); +// +// fShowSourcePackagesItem = new BMenuItem(B_TRANSLATE("Show source packages"), +// new BMessage(MSG_SHOW_SOURCE_PACKAGES)); +// menu->AddItem(fShowSourcePackagesItem); +// +// menuBar->AddItem(menu); } @@ -383,8 +423,9 @@ MainWindow::_AdoptModel() } BAutolock locker(fModel.Lock()); - fShowSourcePackagesItem->SetMarked(fModel.ShowSourcePackages()); - fShowDevelopPackagesItem->SetMarked(fModel.ShowDevelopPackages()); +// fShowSourcePackagesItem->SetMarked(fModel.ShowSourcePackages()); +// fShowDevelopPackagesItem->SetMarked(fModel.ShowDevelopPackages()); + fFilterView->AdoptCheckmarks(fModel); } diff --git a/src/apps/haikudepot/Model.cpp b/src/apps/haikudepot/Model.cpp index 9462c93ffa..8307f6c8cd 100644 --- a/src/apps/haikudepot/Model.cpp +++ b/src/apps/haikudepot/Model.cpp @@ -303,6 +303,8 @@ Model::Model() fDepotFilter(""), fSearchTermsFilter(PackageFilterRef(new AnyFilter(), true)), + fShowAvailablePackages(true), + fShowInstalledPackages(false), fShowSourcePackages(false), fShowDevelopPackages(false), @@ -325,39 +327,6 @@ Model::Model() // get the defined categories and their translated names. // This should then be used instead of hard-coded // categories and translations in the app. - - // A category for packages that the user installed. - fUserCategories.Add(CategoryRef(new PackageCategory( - BitmapRef(), - B_TRANSLATE("Installed packages"), "installed"), true)); - - // A category for packages that not yet installed. - fUserCategories.Add(CategoryRef(new PackageCategory( - BitmapRef(), - B_TRANSLATE("Available packages"), "available"), true)); - - // A category for packages that the user specifically uninstalled. - // For example, a user may have removed packages from a default - // Haiku installation - fUserCategories.Add(CategoryRef(new PackageCategory( - BitmapRef(), - B_TRANSLATE("Uninstalled packages"), "uninstalled"), true)); - - // A category for all packages that the user has installed or uninstalled. - // Those packages resemble what makes their system different from a - // fresh Haiku installation. - fUserCategories.Add(CategoryRef(new PackageCategory( - BitmapRef(), - B_TRANSLATE("User modified packages"), "modified"), true)); - - // Two categories to see just the packages which are downloading or - // have updates available - fProgressCategories.Add(CategoryRef(new PackageCategory( - BitmapRef(), - B_TRANSLATE("Downloading"), "downloading"), true)); - fProgressCategories.Add(CategoryRef(new PackageCategory( - BitmapRef(), - B_TRANSLATE("Update available"), "updates"), true)); } @@ -370,9 +339,8 @@ Model::~Model() PackageList Model::CreatePackageList() const { - // TODO: Allow to restrict depot, filter by search terms, ... - - // Return all packages from all depots. + // Iterate all packages from all depots. + // If configured, restrict depot, filter by search terms, status, name ... PackageList resultList; for (int32 i = 0; i < fDepots.CountItems(); i++) { @@ -387,6 +355,8 @@ Model::CreatePackageList() const const PackageInfoRef& package = packages.ItemAtFast(j); if (fCategoryFilter->AcceptsPackage(package) && fSearchTermsFilter->AcceptsPackage(package) + && (fShowAvailablePackages || package->State() != NONE) + && (fShowInstalledPackages || package->State() != ACTIVATED) && (fShowSourcePackages || !is_source_package(package)) && (fShowDevelopPackages || !is_develop_package(package))) { resultList.Add(package); @@ -439,7 +409,8 @@ Model::SetPackageState(const PackageInfoRef& package, PackageState state) case UNINSTALLED: fInstalledPackages.Remove(package); fActivatedPackages.Remove(package); - fUninstalledPackages.Add(package); + if (!fUninstalledPackages.Contains(package)) + fUninstalledPackages.Add(package); break; } @@ -457,22 +428,6 @@ Model::SetCategory(const BString& category) if (category.Length() == 0) filter = new AnyFilter(); - else if (category == "installed") - filter = new ContainedInFilter(fInstalledPackages); - else if (category == "uninstalled") - filter = new ContainedInFilter(fUninstalledPackages); - else if (category == "available") { - filter = new StateFilter(NONE); -// filter = new NotContainedInFilter(&fInstalledPackages, -// &fUninstalledPackages, &fDownloadingPackages, &fUpdateablePackages, -// NULL); - } else if (category == "modified") { - filter = new ContainedInEitherFilter(fInstalledPackages, - fUninstalledPackages); - } else if (category == "downloading") - filter = new ContainedInFilter(fDownloadingPackages); - else if (category == "updates") - filter = new ContainedInFilter(fUpdateablePackages); else filter = new CategoryFilter(category); @@ -501,6 +456,20 @@ Model::SetSearchTerms(const BString& searchTerms) } +void +Model::SetShowAvailablePackages(bool show) +{ + fShowAvailablePackages = show; +} + + +void +Model::SetShowInstalledPackages(bool show) +{ + fShowInstalledPackages = show; +} + + void Model::SetShowSourcePackages(bool show) { @@ -883,23 +852,33 @@ Model::_PopulatePackageInfo(const PackageInfoRef& package, const BMessage& data) BString foundInfo; BMessage versions; - BMessage version; - if (data.FindMessage("versions", &versions) == B_OK - && versions.FindMessage("0", &version)) { - BString languageCode; - if (version.FindString("naturalLanguageCode", &languageCode) == B_OK) { - if (languageCode == fPreferredLanguage) { - BString summary; - if (version.FindString("summary", &summary) == B_OK) { - package->SetShortDescription(summary); - append_word_list(foundInfo, "summary"); - } - BString description; - if (version.FindString("description", &description) == B_OK) { - package->SetFullDescription(description); - append_word_list(foundInfo, "description"); - } + if (data.FindMessage("versions", &versions) == B_OK) { + // Search a summary and description in the preferred language + int32 index = 0; + while (true) { + BString name; + name << index++; + BMessage version; + if (versions.FindMessage(name, &version) != B_OK) + break; + BString languageCode; + if (version.FindString("naturalLanguageCode", + &languageCode) != B_OK + || languageCode != fPreferredLanguage) { + continue; } + + BString summary; + if (version.FindString("summary", &summary) == B_OK) { + package->SetShortDescription(summary); + append_word_list(foundInfo, "summary"); + } + BString description; + if (version.FindString("description", &description) == B_OK) { + package->SetFullDescription(description); + append_word_list(foundInfo, "description"); + } + break; } } diff --git a/src/apps/haikudepot/Model.h b/src/apps/haikudepot/Model.h index 09b94cd2aa..543492c040 100644 --- a/src/apps/haikudepot/Model.h +++ b/src/apps/haikudepot/Model.h @@ -66,10 +66,6 @@ public: const CategoryList& Categories() const { return fCategories; } - const CategoryList& UserCategories() const - { return fUserCategories; } - const CategoryList& ProgressCategories() const - { return fProgressCategories; } void SetPackageState( const PackageInfoRef& package, @@ -79,6 +75,13 @@ public: void SetCategory(const BString& category); void SetDepot(const BString& depot); void SetSearchTerms(const BString& searchTerms); + + void SetShowAvailablePackages(bool show); + bool ShowAvailablePackages() const + { return fShowAvailablePackages; } + void SetShowInstalledPackages(bool show); + bool ShowInstalledPackages() const + { return fShowInstalledPackages; } void SetShowSourcePackages(bool show); bool ShowSourcePackages() const { return fShowSourcePackages; } @@ -142,8 +145,6 @@ private: // TODO: Dynamic categories retrieved from web-app CategoryList fCategories; - CategoryList fUserCategories; - CategoryList fProgressCategories; PackageList fInstalledPackages; PackageList fActivatedPackages; @@ -156,6 +157,8 @@ private: BString fDepotFilter; PackageFilterRef fSearchTermsFilter; + bool fShowAvailablePackages; + bool fShowInstalledPackages; bool fShowSourcePackages; bool fShowDevelopPackages;