[haiku-commits] haiku: hrev53164 - in src/apps/haikudepot: model ui server util

  • From: Andrew Lindesay <apl@xxxxxxxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sat, 25 May 2019 07:10:56 -0400 (EDT)

hrev53164 adds 1 changeset to branch 'master'
old head: f259502c907963f01803a757d60ed55258fe6e4c
new head: 89b16bb4d245c3a6e55e0d8f3502324e6f31bcb4
overview: 
https://git.haiku-os.org/haiku/log/?qt=range&q=89b16bb4d245+%5Ef259502c9079

----------------------------------------------------------------------------

89b16bb4d245: HaikuDepot: Categories from Server
  
  The list of categories for packages is currently
  hard-coded into the HaikuDepot desktop
  application.  This change will change that so that
  the list is obtained from the HaikuDepot Server
  system and is always up to date with the server's
  list of categories.
  
  Change-Id: I757732f4d771e1599d6ad9c85cd65905640de928
  Reviewed-on: https://review.haiku-os.org/c/1478
  Reviewed-by: Adrien Destugues <pulkomandy@xxxxxxxxx>

                                    [ Andrew Lindesay <apl@xxxxxxxxxxxxxx> ]

----------------------------------------------------------------------------

Revision:    hrev53164
Commit:      89b16bb4d245c3a6e55e0d8f3502324e6f31bcb4
URL:         https://git.haiku-os.org/haiku/commit/?id=89b16bb4d245
Author:      Andrew Lindesay <apl@xxxxxxxxxxxxxx>
Date:        Thu May 23 05:10:33 2019 UTC

----------------------------------------------------------------------------

14 files changed, 257 insertions(+), 159 deletions(-)
src/apps/haikudepot/Jamfile                      |   1 +
src/apps/haikudepot/model/LanguageModel.cpp      |  16 ++-
src/apps/haikudepot/model/Model.cpp              | 107 ++++++++++---------
src/apps/haikudepot/model/Model.h                |  41 +------
src/apps/haikudepot/model/PackageInfo.cpp        |  19 ++--
src/apps/haikudepot/model/PackageInfo.h          |  12 +--
.../server/ServerPkgDataUpdateProcess.cpp        |   8 +-
.../server/ServerReferenceDataUpdateProcess.cpp  |  48 +++++++--
.../server/ServerReferenceDataUpdateProcess.h    |   2 +
src/apps/haikudepot/ui/FilterView.cpp            |  61 +++++++----
src/apps/haikudepot/ui/FilterView.h              |  11 +-
src/apps/haikudepot/ui/MainWindow.cpp            |  29 +++--
src/apps/haikudepot/util/LocaleUtils.cpp         |  36 +++++++
src/apps/haikudepot/util/LocaleUtils.h           |  25 +++++

----------------------------------------------------------------------------

diff --git a/src/apps/haikudepot/Jamfile b/src/apps/haikudepot/Jamfile
index 8e69fdfa76..70328c207d 100644
--- a/src/apps/haikudepot/Jamfile
+++ b/src/apps/haikudepot/Jamfile
@@ -173,6 +173,7 @@ local applicationSources =
        AppUtils.cpp
        DataIOUtils.cpp
        LanguageMenuUtils.cpp
+       LocaleUtils.cpp
        RepositoryUrlUtils.cpp
        StorageUtils.cpp
        ToFileUrlProtocolListener.cpp
diff --git a/src/apps/haikudepot/model/LanguageModel.cpp 
b/src/apps/haikudepot/model/LanguageModel.cpp
index 8c602bdc49..c74cea639a 100644
--- a/src/apps/haikudepot/model/LanguageModel.cpp
+++ b/src/apps/haikudepot/model/LanguageModel.cpp
@@ -10,25 +10,23 @@
 
 #include "HaikuDepotConstants.h"
 #include "Logger.h"
+#include "LocaleUtils.h"
 
 
 static int32
 LanguagesCompareFn(const LanguageRef& l1, const LanguageRef& l2)
 {
-       const BLocale* locale = BLocaleRoster::Default()->GetDefaultLocale();
-       BCollator collator;
-
-       if (B_OK != locale->GetCollator(&collator)) {
-               debugger("unable to get the locale's collator");
-       }
-
+       BCollator* collator = LocaleUtils::GetSharedCollator();
        BString name1;
        BString name2;
+       int32 result = 0;
 
        if (l1->GetName(name1) == B_OK && l2->GetName(name2) == B_OK)
-               return collator.Compare(name1.String(), name2.String());
+               result = collator->Compare(name1.String(), name2.String());
+       if (0 == result)
+               result = strcmp(l1->Code(), l2->Code());
 
-       return collator.Compare(l1->Code(), l2->Code());
+       return result;
 }
 
 
diff --git a/src/apps/haikudepot/model/Model.cpp 
b/src/apps/haikudepot/model/Model.cpp
index 7f583f6348..d9758ee0cf 100644
--- a/src/apps/haikudepot/model/Model.cpp
+++ b/src/apps/haikudepot/model/Model.cpp
@@ -14,15 +14,18 @@
 
 #include <Autolock.h>
 #include <Catalog.h>
+#include <Collator.h>
 #include <Directory.h>
 #include <Entry.h>
 #include <File.h>
 #include <KeyStore.h>
+#include <Locale.h>
 #include <LocaleRoster.h>
 #include <Message.h>
 #include <Path.h>
 
 #include "Logger.h"
+#include "LocaleUtils.h"
 #include "StorageUtils.h"
 #include "RepositoryUrlUtils.h"
 
@@ -103,7 +106,7 @@ public:
                        const CategoryRef& category = categories.ItemAtFast(i);
                        if (category.Get() == NULL)
                                continue;
-                       if (category->Name() == fCategory)
+                       if (category->Code() == fCategory)
                                return true;
                }
                return false;
@@ -311,44 +314,22 @@ is_develop_package(const PackageInfoRef& package)
 // #pragma mark - Model
 
 
+static int32
+PackageCategoryCompareFn(const CategoryRef& c1, const CategoryRef& c2)
+{
+       BCollator* collator = LocaleUtils::GetSharedCollator();
+       int32 result = collator->Compare(c1->Name().String(),
+               c2->Name().String());
+       if (result == 0)
+               result = c1->Code().Compare(c2->Code());
+       return result;
+}
+
+
 Model::Model()
        :
        fDepots(),
-
-       fCategoryAudio(new PackageCategory(
-               BitmapRef(),
-               B_TRANSLATE("Audio"), "audio"), true),
-       fCategoryBusiness(new PackageCategory(
-               BitmapRef(),
-               B_TRANSLATE("Business"), "business"), true),
-       fCategoryDevelopment(new PackageCategory(
-               BitmapRef(),
-               B_TRANSLATE("Development"), "development"), true),
-       fCategoryEducation(new PackageCategory(
-               BitmapRef(),
-               B_TRANSLATE("Education"), "education"), true),
-       fCategoryGames(new PackageCategory(
-               BitmapRef(),
-               B_TRANSLATE("Games"), "games"), true),
-       fCategoryGraphics(new PackageCategory(
-               BitmapRef(),
-               B_TRANSLATE("Graphics"), "graphics"), true),
-       fCategoryInternetAndNetwork(new PackageCategory(
-               BitmapRef(),
-               B_TRANSLATE("Internet & Network"), "internetandnetwork"), true),
-       fCategoryProductivity(new PackageCategory(
-               BitmapRef(),
-               B_TRANSLATE("Productivity"), "productivity"), true),
-       fCategoryScienceAndMathematics(new PackageCategory(
-               BitmapRef(),
-               B_TRANSLATE("Science & Mathematics"), "scienceandmathematics"), 
true),
-       fCategorySystemAndUtilities(new PackageCategory(
-               BitmapRef(),
-               B_TRANSLATE("System & Utilities"), "systemandutilities"), true),
-       fCategoryVideo(new PackageCategory(
-               BitmapRef(),
-               B_TRANSLATE("Video"), "video"), true),
-
+       fCategories(&PackageCategoryCompareFn, NULL),
        fCategoryFilter(PackageFilterRef(new AnyFilter(), true)),
        fDepotFilter(""),
        fSearchTermsFilter(PackageFilterRef(new AnyFilter(), true)),
@@ -360,23 +341,6 @@ Model::Model()
        fShowDevelopPackages(false)
 {
        _UpdateIsFeaturedFilter();
-
-       // Don't forget to add new categories to this list:
-       fCategories.Add(fCategoryGames);
-       fCategories.Add(fCategoryBusiness);
-       fCategories.Add(fCategoryAudio);
-       fCategories.Add(fCategoryVideo);
-       fCategories.Add(fCategoryGraphics);
-       fCategories.Add(fCategoryEducation);
-       fCategories.Add(fCategoryProductivity);
-       fCategories.Add(fCategorySystemAndUtilities);
-       fCategories.Add(fCategoryInternetAndNetwork);
-       fCategories.Add(fCategoryDevelopment);
-       fCategories.Add(fCategoryScienceAndMathematics);
-       // TODO: The server will eventually support an API to
-       // get the defined categories and their translated names.
-       // This should then be used instead of hard-coded
-       // categories and translations in the app.
 }
 
 
@@ -1057,6 +1021,18 @@ Model::_NotifyAuthorizationChanged()
 }
 
 
+void
+Model::_NotifyCategoryListChanged()
+{
+       for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) {
+               const ModelListenerRef& listener = fListeners.ItemAtFast(i);
+               if (listener.Get() != NULL)
+                       listener->CategoryListChanged();
+       }
+}
+
+
+
 /*! This method will find the stored 'DepotInfo' that correlates to the
     supplied 'url' and will invoke the mapper function in order to get a
     replacement for the 'DepotInfo'.  The 'url' is a unique identifier
@@ -1117,3 +1093,28 @@ Model::_MaybeLogJsonRpcError(const BMessage 
&responsePayload,
                printf("[%s] --> an undefined error has occurred\n", 
sourceDescription);
        }
 }
+
+
+void
+Model::AddCategories(const CategoryList& categories)
+{
+       int32 i;
+       for (i = 0; i < categories.CountItems(); i++)
+               _AddCategory(categories.ItemAt(i));
+       _NotifyCategoryListChanged();
+}
+
+
+void
+Model::_AddCategory(const CategoryRef& category)
+{
+       int32 i;
+       for (i = 0; i < fCategories.CountItems(); i++) {
+               if (fCategories.ItemAt(i)->Code() == category->Code()) {
+                       fCategories.Replace(i, category);
+                       return;
+               }
+       }
+
+       fCategories.Add(category);
+}
diff --git a/src/apps/haikudepot/model/Model.h 
b/src/apps/haikudepot/model/Model.h
index 553f48614a..0e23af33bb 100644
--- a/src/apps/haikudepot/model/Model.h
+++ b/src/apps/haikudepot/model/Model.h
@@ -37,6 +37,7 @@ public:
        virtual                                         ~ModelListener();
 
        virtual void                            AuthorizationChanged() = 0;
+       virtual void                            CategoryListChanged() = 0;
 };
 
 
@@ -86,30 +87,7 @@ public:
 
                        void                            Clear();
 
-                       // Access to global categories
-                       const CategoryRef&      CategoryAudio() const
-                                                                       { 
return fCategoryAudio; }
-                       const CategoryRef&      CategoryBusiness() const
-                                                                       { 
return fCategoryBusiness; }
-                       const CategoryRef&      CategoryDevelopment() const
-                                                                       { 
return fCategoryDevelopment; }
-                       const CategoryRef&      CategoryEducation() const
-                                                                       { 
return fCategoryEducation; }
-                       const CategoryRef&      CategoryInternetAndNetwork() 
const
-                                                                       { 
return fCategoryInternetAndNetwork; }
-                       const CategoryRef&      CategoryGames() const
-                                                                       { 
return fCategoryGames; }
-                       const CategoryRef&      CategoryGraphics() const
-                                                                       { 
return fCategoryGraphics; }
-                       const CategoryRef&      CategoryProductivity() const
-                                                                       { 
return fCategoryProductivity; }
-                       const CategoryRef&      CategoryScienceAndMathematics() 
const
-                                                                       { 
return fCategoryScienceAndMathematics; }
-                       const CategoryRef&      CategorySystemAndUtilities() 
const
-                                                                       { 
return fCategorySystemAndUtilities; }
-                       const CategoryRef&      CategoryVideo() const
-                                                                       { 
return fCategoryVideo; }
-
+                       void                            AddCategories(const 
CategoryList& categories);
                        const CategoryList&     Categories() const
                                                                        { 
return fCategories; }
 
@@ -176,6 +154,7 @@ public:
                        void                            
LogDepotsWithNoWebAppRepositoryCode() const;
 
 private:
+                       void                            _AddCategory(const 
CategoryRef& category);
                        status_t                        _LocalDataPath(const 
BString leaf,
                                                                        BPath& 
path) const;
 
@@ -207,25 +186,13 @@ private:
                                                                        bool 
ignoreAge, time_t maxAge) const;
 
                        void                            
_NotifyAuthorizationChanged();
+                       void                            
_NotifyCategoryListChanged();
 
 private:
                        BLocker                         fLock;
 
                        DepotList                       fDepots;
 
-                       CategoryRef                     fCategoryAudio;
-                       CategoryRef                     fCategoryBusiness;
-                       CategoryRef                     fCategoryDevelopment;
-                       CategoryRef                     fCategoryEducation;
-                       CategoryRef                     fCategoryGames;
-                       CategoryRef                     fCategoryGraphics;
-                       CategoryRef                     
fCategoryInternetAndNetwork;
-                       CategoryRef                     fCategoryProductivity;
-                       CategoryRef                     
fCategoryScienceAndMathematics;
-                       CategoryRef                     
fCategorySystemAndUtilities;
-                       CategoryRef                     fCategoryVideo;
-                       // TODO: Dynamic categories retrieved from web-app
-
                        CategoryList            fCategories;
 
                        PackageList                     fInstalledPackages;
diff --git a/src/apps/haikudepot/model/PackageInfo.cpp 
b/src/apps/haikudepot/model/PackageInfo.cpp
index e1cade50db..4006bbf27f 100644
--- a/src/apps/haikudepot/model/PackageInfo.cpp
+++ b/src/apps/haikudepot/model/PackageInfo.cpp
@@ -371,19 +371,16 @@ PublisherInfo::operator!=(const PublisherInfo& other) 
const
 PackageCategory::PackageCategory()
        :
        BReferenceable(),
-       fIcon(),
-       fLabel(),
+       fCode(),
        fName()
 {
 }
 
 
-PackageCategory::PackageCategory(const BitmapRef& icon, const BString& label,
-               const BString& name)
+PackageCategory::PackageCategory(const BString& code, const BString& name)
        :
        BReferenceable(),
-       fIcon(icon),
-       fLabel(label),
+       fCode(code),
        fName(name)
 {
 }
@@ -392,8 +389,7 @@ PackageCategory::PackageCategory(const BitmapRef& icon, 
const BString& label,
 PackageCategory::PackageCategory(const PackageCategory& other)
        :
        BReferenceable(),
-       fIcon(other.fIcon),
-       fLabel(other.fLabel),
+       fCode(other.fCode),
        fName(other.fName)
 {
 }
@@ -402,8 +398,7 @@ PackageCategory::PackageCategory(const PackageCategory& 
other)
 PackageCategory&
 PackageCategory::operator=(const PackageCategory& other)
 {
-       fIcon = other.fIcon;
-       fLabel = other.fLabel;
+       fCode = other.fCode;
        fName = other.fName;
        return *this;
 }
@@ -412,9 +407,7 @@ PackageCategory::operator=(const PackageCategory& other)
 bool
 PackageCategory::operator==(const PackageCategory& other) const
 {
-       return fIcon == other.fIcon
-               && fLabel == other.fLabel
-               && fName == other.fName;
+       return fCode == other.fCode && fName == other.fName;
 }
 
 
diff --git a/src/apps/haikudepot/model/PackageInfo.h 
b/src/apps/haikudepot/model/PackageInfo.h
index c2c8ddb35b..09aabd5a19 100644
--- a/src/apps/haikudepot/model/PackageInfo.h
+++ b/src/apps/haikudepot/model/PackageInfo.h
@@ -192,8 +192,7 @@ private:
 class PackageCategory : public BReferenceable {
 public:
                                                                
PackageCategory();
-                                                               
PackageCategory(const BitmapRef& icon,
-                                                                       const 
BString& label,
+                                                               
PackageCategory(const BString& code,
                                                                        const 
BString& name);
                                                                
PackageCategory(const PackageCategory& other);
 
@@ -201,15 +200,12 @@ public:
                        bool                            operator==(const 
PackageCategory& other) const;
                        bool                            operator!=(const 
PackageCategory& other) const;
 
-                       const BitmapRef&        Icon() const
-                                                                       { 
return fIcon; }
-                       const BString&          Label() const
-                                                                       { 
return fLabel; }
+                       const BString&          Code() const
+                                                                       { 
return fCode; }
                        const BString&          Name() const
                                                                        { 
return fName; }
 private:
-                       BitmapRef                       fIcon;
-                       BString                         fLabel;
+                       BString                         fCode;
                        BString                         fName;
 };
 
diff --git a/src/apps/haikudepot/server/ServerPkgDataUpdateProcess.cpp 
b/src/apps/haikudepot/server/ServerPkgDataUpdateProcess.cpp
index 596a2a2a5c..10bdfe2f9b 100644
--- a/src/apps/haikudepot/server/ServerPkgDataUpdateProcess.cpp
+++ b/src/apps/haikudepot/server/ServerPkgDataUpdateProcess.cpp
@@ -86,8 +86,8 @@ PackageFillingPkgListener::~PackageFillingPkgListener()
        // TODO; performance could be improved by not needing the linear search
 
 inline int32
-PackageFillingPkgListener::IndexOfCategoryByName(
-       const BString& name) const
+PackageFillingPkgListener::IndexOfCategoryByCode(
+       const BString& code) const
 {
        int32 i;
        int32 categoryCount = fCategories.CountItems();
@@ -95,7 +95,7 @@ PackageFillingPkgListener::IndexOfCategoryByName(
        for (i = 0; i < categoryCount; i++) {
                const CategoryRef categoryRef = fCategories.ItemAtFast(i);
 
-               if (categoryRef->Name() == name)
+               if (categoryRef->Code() == code)
                        return i;
        }
 
@@ -140,7 +140,7 @@ PackageFillingPkgListener::ConsumePackage(const 
PackageInfoRef& package,
 
        for (i = 0; i < countPkgCategories; i++) {
                BString* categoryCode = pkg->PkgCategoriesItemAt(i)->Code();
-               int categoryIndex = IndexOfCategoryByName(*(categoryCode));
+               int categoryIndex = IndexOfCategoryByCode(*(categoryCode));
 
                if (categoryIndex == -1) {
                        printf("unable to find the category for [%s]\n",
diff --git a/src/apps/haikudepot/server/ServerReferenceDataUpdateProcess.cpp 
b/src/apps/haikudepot/server/ServerReferenceDataUpdateProcess.cpp
index 622fcfb2a5..97acc8928a 100644
--- a/src/apps/haikudepot/server/ServerReferenceDataUpdateProcess.cpp
+++ b/src/apps/haikudepot/server/ServerReferenceDataUpdateProcess.cpp
@@ -107,8 +107,12 @@ ServerReferenceDataUpdateProcess::ProcessLocalData()
 status_t
 ServerReferenceDataUpdateProcess::_ProcessData(DumpExportReference* data)
 {
-       // more to come here later...
-       return _ProcessNaturalLanguages(data);
+       status_t result = B_OK;
+       if (result == B_OK)
+               result = _ProcessNaturalLanguages(data);
+       if (result == B_OK)
+               result = _ProcessPkgCategories(data);
+       return result;
 }
 
 
@@ -124,10 +128,13 @@ 
ServerReferenceDataUpdateProcess::_ProcessNaturalLanguages(
        for (int32 i = 0; i < data->CountNaturalLanguages(); i++) {
                DumpExportReferenceNaturalLanguage* naturalLanguage =
                        data->NaturalLanguagesItemAt(i);
-               result.Add(LanguageRef(new Language(
-                       *(naturalLanguage->Code()),
-                       *(naturalLanguage->Name()),
-                       naturalLanguage->IsPopular())));
+               result.Add(LanguageRef(
+                       new Language(
+                               *(naturalLanguage->Code()),
+                               *(naturalLanguage->Name()),
+                               naturalLanguage->IsPopular()
+                       ),
+                       true));
        }
 
        {
@@ -142,6 +149,35 @@ ServerReferenceDataUpdateProcess::_ProcessNaturalLanguages(
 }
 
 
+status_t
+ServerReferenceDataUpdateProcess::_ProcessPkgCategories(
+       DumpExportReference* data)
+{
+       printf("[%s] will populate %" B_PRId32 " pkg categories\n",
+               Name(), data->CountPkgCategories());
+
+       CategoryList result;
+
+       for (int32 i = 0; i < data->CountPkgCategories(); i++) {
+               DumpExportReferencePkgCategory* pkgCategory =
+                       data->PkgCategoriesItemAt(i);
+               result.Add(CategoryRef(
+                       new PackageCategory(
+                               *(pkgCategory->Code()),
+                               *(pkgCategory->Name())
+                       ),
+                       true));
+       }
+
+       {
+               AutoLocker<BLocker> locker(fModel->Lock());
+               fModel->AddCategories(result);
+       }
+
+       return B_OK;
+}
+
+
 status_t
 ServerReferenceDataUpdateProcess::GetStandardMetaDataPath(BPath& path) const
 {
diff --git a/src/apps/haikudepot/server/ServerReferenceDataUpdateProcess.h 
b/src/apps/haikudepot/server/ServerReferenceDataUpdateProcess.h
index fe051b6efa..25ff2c1101 100644
--- a/src/apps/haikudepot/server/ServerReferenceDataUpdateProcess.h
+++ b/src/apps/haikudepot/server/ServerReferenceDataUpdateProcess.h
@@ -46,6 +46,8 @@ private:
                        status_t                        
_ProcessData(DumpExportReference* data);
                        status_t                        
_ProcessNaturalLanguages(
                                                                        
DumpExportReference* data);
+                       status_t                        _ProcessPkgCategories(
+                                                                       
DumpExportReference* data);
 
 private:
                        Model*                          fModel;
diff --git a/src/apps/haikudepot/ui/FilterView.cpp 
b/src/apps/haikudepot/ui/FilterView.cpp
index 807b030a84..cccf70185d 100644
--- a/src/apps/haikudepot/ui/FilterView.cpp
+++ b/src/apps/haikudepot/ui/FilterView.cpp
@@ -1,5 +1,6 @@
 /*
  * Copyright 2013, Stephan Aßmus <superstippi@xxxxxx>.
+ * Copyright 2019, Andrew Lindesay <apl@xxxxxxxxxxxxxx>.
  * All rights reserved. Distributed under the terms of the MIT License.
  */
 
@@ -8,6 +9,7 @@
 #include <algorithm>
 #include <stdio.h>
 
+#include <AutoLocker.h>
 #include <Catalog.h>
 #include <CheckBox.h>
 #include <LayoutBuilder.h>
@@ -31,8 +33,8 @@ add_categories_to_menu(const CategoryList& categories, BMenu* 
menu)
        for (int i = 0; i < categories.CountItems(); i++) {
                const CategoryRef& category = categories.ItemAtFast(i);
                BMessage* message = new BMessage(MSG_CATEGORY_SELECTED);
-               message->AddString("name", category->Name());
-               BMenuItem* item = new BMenuItem(category->Label(), message);
+               message->AddString("code", category->Code());
+               BMenuItem* item = new BMenuItem(category->Name(), message);
                menu->AddItem(item);
        }
 }
@@ -88,7 +90,6 @@ FilterView::AttachedToWindow()
 {
        fShowField->Menu()->SetTargetForItems(Window());
        fSearchTermsText->SetTarget(this);
-
        fSearchTermsText->MakeFocus();
 }
 
@@ -113,7 +114,7 @@ FilterView::MessageReceived(BMessage* message)
 
 
 void
-FilterView::AdoptModel(const Model& model)
+FilterView::AdoptModel(Model& model)
 {
        // Adopt categories
        BMenu* showMenu = fShowField->Menu();
@@ -122,25 +123,47 @@ FilterView::AdoptModel(const Model& model)
        showMenu->AddItem(new BMenuItem(B_TRANSLATE("All categories"),
                new BMessage(MSG_CATEGORY_SELECTED)));
 
-       showMenu->AddItem(new BSeparatorItem());
+       AutoLocker<BLocker> locker(model.Lock());
+       CategoryList categories = model.Categories();
+
+       if (!categories.IsEmpty()) {
+               showMenu->AddItem(new BSeparatorItem());
+               add_categories_to_menu(categories, showMenu);
+       }
+
+       showMenu->SetEnabled(!categories.IsEmpty());
+
+       if (!_SelectCategoryCode(showMenu, model.Category()))
+               showMenu->ItemAt(0)->SetMarked(true);
+}
 
-       add_categories_to_menu(model.Categories(), showMenu);
 
-       bool foundSelectedCategory = false;
-       for (int32 i = 0; i < showMenu->CountItems(); i++) {
-               BMenuItem* item = showMenu->ItemAt(i);
-               BMessage* message = item->Message();
-               if (message == NULL)
-                       continue;
-               BString category;
-               if (message->FindString("name", &category) == B_OK
-                       && model.Category() == category) {
+/*! Tries to mark the menu item that corresponds to the supplied
+    category code.  If the supplied code was found and the item marked
+    then the method will return true.
+*/
+
+/*static*/ bool
+FilterView::_SelectCategoryCode(BMenu* menu, const BString& code)
+{
+       for (int32 i = 0; i < menu->CountItems(); i++) {
+               BMenuItem* item = menu->ItemAt(i);
+               if (_MatchesCategoryCode(item, code)) {
                        item->SetMarked(true);
-                       foundSelectedCategory = true;
-                       break;
+                       return true;
                }
        }
-       if (!foundSelectedCategory)
-               showMenu->ItemAt(0)->SetMarked(true);
+       return false;
 }
 
+
+/*static*/ bool
+FilterView::_MatchesCategoryCode(BMenuItem* item, const BString& code)
+{
+       BMessage* message = item->Message();
+       if (message == NULL)
+               return false;
+       BString itemCode;
+       message->FindString("code", &itemCode);
+       return itemCode == code;
+}
\ No newline at end of file
diff --git a/src/apps/haikudepot/ui/FilterView.h 
b/src/apps/haikudepot/ui/FilterView.h
index 6740766785..795c095a60 100644
--- a/src/apps/haikudepot/ui/FilterView.h
+++ b/src/apps/haikudepot/ui/FilterView.h
@@ -1,5 +1,6 @@
 /*
  * Copyright 2013, Stephan Aßmus <superstippi@xxxxxx>.
+ * Copyright 2019, Andrew Lindesay <apl@xxxxxxxxxxxxxx>.
  * All rights reserved. Distributed under the terms of the MIT License.
  */
 #ifndef FILTER_VIEW_H
@@ -9,7 +10,9 @@
 
 
 class BCheckBox;
+class BMenu;
 class BMenuField;
+class BMenuItem;
 class BTextControl;
 class Model;
 
@@ -29,7 +32,13 @@ public:
        virtual void                            AttachedToWindow();
        virtual void                            MessageReceived(BMessage* 
message);
 
-                       void                            AdoptModel(const Model& 
model);
+                       void                            AdoptModel(Model& 
model);
+
+private:
+       static  bool                            _SelectCategoryCode(BMenu* menu,
+                                                                       const 
BString& code);
+       static  bool                            _MatchesCategoryCode(BMenuItem* 
item,
+                                                                       const 
BString& code);
 
 private:
                        BMenuField*                     fShowField;
diff --git a/src/apps/haikudepot/ui/MainWindow.cpp 
b/src/apps/haikudepot/ui/MainWindow.cpp
index fb26b69ba0..e0a32ec567 100644
--- a/src/apps/haikudepot/ui/MainWindow.cpp
+++ b/src/apps/haikudepot/ui/MainWindow.cpp
@@ -3,7 +3,7 @@
  * Copyright 2013-2014, Stephan Aßmus <superstippi@xxxxxx>.
  * Copyright 2013, Rene Gollent, rene@xxxxxxxxxxx.
  * Copyright 2013, Ingo Weinhold, ingo_weinhold@xxxxxx.
- * Copyright 2016-2018, Andrew Lindesay <apl@xxxxxxxxxxxxxx>.
+ * Copyright 2016-2019, Andrew Lindesay <apl@xxxxxxxxxxxxxx>.
  * Copyright 2017, Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>.
  * All rights reserved. Distributed under the terms of the MIT License.
  */
@@ -63,6 +63,7 @@ enum {
        MSG_LOG_IN                                      = 'lgin',
        MSG_LOG_OUT                                     = 'lgot',
        MSG_AUTHORIZATION_CHANGED       = 'athc',
+       MSG_CATEGORIES_LIST_CHANGED     = 'clic',
        MSG_PACKAGE_CHANGED                     = 'pchd',
        MSG_WORK_STATUS_CHANGE          = 'wsch',
        MSG_WORK_STATUS_CLEAR           = 'wscl',
@@ -95,9 +96,9 @@ struct RefreshWorkerParameters {
 };
 
 
-class MessageModelListener : public ModelListener {
+class MainWindowModelListener : public ModelListener {
 public:
-       MessageModelListener(const BMessenger& messenger)
+       MainWindowModelListener(const BMessenger& messenger)
                :
                fMessenger(messenger)
        {
@@ -109,6 +110,12 @@ public:
                        fMessenger.SendMessage(MSG_AUTHORIZATION_CHANGED);
        }
 
+       virtual void CategoryListChanged()
+       {
+               if (fMessenger.IsValid())
+                       fMessenger.SendMessage(MSG_CATEGORIES_LIST_CHANGED);
+       }
+
 private:
        BMessenger      fMessenger;
 };
@@ -123,7 +130,7 @@ MainWindow::MainWindow(const BMessage& settings)
        fUserMenu(NULL),
        fLogInItem(NULL),
        fLogOutItem(NULL),
-       fModelListener(new MessageModelListener(BMessenger(this)), true),
+       fModelListener(new MainWindowModelListener(BMessenger(this)), true),
        fBulkLoadProcessCoordinator(NULL),
        fSinglePackageMode(false)
 {
@@ -221,7 +228,7 @@ MainWindow::MainWindow(const BMessage& settings, const 
PackageInfoRef& package)
        fUserMenu(NULL),
        fLogInItem(NULL),
        fLogOutItem(NULL),
-       fModelListener(new MessageModelListener(BMessenger(this)), true),
+       fModelListener(new MainWindowModelListener(BMessenger(this)), true),
        fBulkLoadProcessCoordinator(NULL),
        fSinglePackageMode(true)
 {
@@ -331,6 +338,10 @@ MainWindow::MessageReceived(BMessage* message)
                        _UpdateAuthorization();
                        break;
 
+               case MSG_CATEGORIES_LIST_CHANGED:
+                       fFilterView->AdoptModel(fModel);
+                       break;
+
                case MSG_SHOW_FEATURED_PACKAGES:
                        // check to see if we aren't already on the current tab
                        if (fListTabs->Selection() ==
@@ -421,12 +432,12 @@ MainWindow::MessageReceived(BMessage* message)
 
                case MSG_CATEGORY_SELECTED:
                {
-                       BString name;
-                       if (message->FindString("name", &name) != B_OK)
-                               name = "";
+                       BString code;
+                       if (message->FindString("code", &code) != B_OK)
+                               code = "";
                        {
                                BAutolock locker(fModel.Lock());
-                               fModel.SetCategory(name);
+                               fModel.SetCategory(code);
                        }
                        _AdoptModel();
                        break;
diff --git a/src/apps/haikudepot/util/LocaleUtils.cpp 
b/src/apps/haikudepot/util/LocaleUtils.cpp
new file mode 100644
index 0000000000..d354aa7929
--- /dev/null
+++ b/src/apps/haikudepot/util/LocaleUtils.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2019, Andrew Lindesay <apl@xxxxxxxxxxxxxx>.
+ * All rights reserved. Distributed under the terms of the MIT License.
+ */
+#include "LocaleUtils.h"
+
+
+#include <Collator.h>
+#include <Locale.h>
+#include <LocaleRoster.h>
+
+
+BCollator* LocaleUtils::sSharedCollator = NULL;
+
+
+/*static*/ BCollator*
+LocaleUtils::GetSharedCollator()
+{
+       if (sSharedCollator == NULL) {
+               GetCollator(sSharedCollator);
+       }
+
+       return sSharedCollator;
+}
+
+
+/*static*/ void
+LocaleUtils::GetCollator(BCollator* collator)
+{
+       const BLocale* locale = BLocaleRoster::Default()->GetDefaultLocale();
+
+       if (B_OK != locale->GetCollator(collator)) {
+               debugger("unable to get the locale's collator");
+               exit(EXIT_FAILURE);
+       }
+}
\ No newline at end of file
diff --git a/src/apps/haikudepot/util/LocaleUtils.h 
b/src/apps/haikudepot/util/LocaleUtils.h
new file mode 100644
index 0000000000..9887012239
--- /dev/null
+++ b/src/apps/haikudepot/util/LocaleUtils.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2019, Andrew Lindesay <apl@xxxxxxxxxxxxxx>.
+ * All rights reserved. Distributed under the terms of the MIT License.
+ */
+#ifndef LOCALE_UTILS_H
+#define LOCALE_UTILS_H
+
+
+class BCollator;
+
+
+class LocaleUtils {
+
+public:
+       static  BCollator*              GetSharedCollator();
+
+private:
+       static  void                    GetCollator(BCollator* collator);
+
+private:
+       static  BCollator*              sSharedCollator;
+};
+
+
+#endif // LOCALE_UTILS_H


Other related posts:

  • » [haiku-commits] haiku: hrev53164 - in src/apps/haikudepot: model ui server util - Andrew Lindesay