HaikuDepot: Improve filter UI, fix pkg translations
* The categories and other filter options are orthogonal. Don't force the user to choose between real categories and for example "installed" or "available" in the same drop-down. I've removed (for now) the Options main menu. There are now four small check-marks below the filtering drop-downs: Available, Installed, Development and Source Code. These enable showing the respective packages in the list view. Only "Available" is checked by default. This changes the default behavior to show only not-yet-installed packages. This change puts the filtering options in one place, the showing of development or source code packages is not "hidden somewhere else" anymore. I am not so happy with the additional row, however, I am also thinking about using icons instead of the checkmarks. * Fixed finding the suitable package translation for summary and description. For example, WonderBrush now has a German translation.
This commit is contained in:
parent
8bfb30ceb3
commit
ab172803ff
@ -9,6 +9,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include <Catalog.h>
|
||||
#include <CheckBox.h>
|
||||
#include <LayoutBuilder.h>
|
||||
#include <MenuField.h>
|
||||
#include <MenuItem.h>
|
||||
@ -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());
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <GroupView.h>
|
||||
|
||||
|
||||
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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user