HaikuDepot: Load Languages from HDS
The HaikuDepot application has, thus far had its own hard-coded list of languages that the user is able to choose when (a) creating a new account or (b) creating a user-rating. This change will mean that those languages are loaded from the HDS server dynamically and in this way the user can choose from the full list. There have also been improvements to the way in which the languages are displayed in the menu as well. Change-Id: If7cb7b87f348ca59d503d276a22444e72d0e6168 Reviewed-on: https://review.haiku-os.org/c/1425 Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018, Andrew Lindesay <[email protected]>.
|
||||
* Copyright 2018-2019, Andrew Lindesay <[email protected]>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef HAIKU_DEPOT_CONSTANTS_H
|
||||
@@ -18,7 +18,8 @@ enum {
|
||||
MSG_SERVER_DATA_CHANGED = 'svdc',
|
||||
MSG_ALERT_SIMPLE_ERROR = 'nser',
|
||||
MSG_DID_ADD_USER_RATING = 'adur',
|
||||
MSG_DID_UPDATE_USER_RATING = 'upur'
|
||||
MSG_DID_UPDATE_USER_RATING = 'upur',
|
||||
MSG_LANGUAGE_SELECTED = 'lngs'
|
||||
};
|
||||
|
||||
|
||||
@@ -54,4 +55,9 @@ enum {
|
||||
RSRC_ARROW_RIGHT = 550,
|
||||
};
|
||||
|
||||
|
||||
#define LANGUAGE_DEFAULT_CODE "en"
|
||||
#define LANGUAGE_DEFAULT Language(LANGUAGE_DEFAULT_CODE, "English", true)
|
||||
|
||||
|
||||
#endif // HAIKU_DEPOT_CONSTANTS_H
|
||||
@@ -16,12 +16,19 @@ local dumpExportRepositoryBulkListerTargetDirectory =
|
||||
local dumpExportPkgBulkListenerTargetDirectory =
|
||||
[ FDirName $(HAIKUDEPOT_GENERATED_SOURCES_DIRECTORY)
|
||||
dumpexportpkgbulklistener ] ;
|
||||
local dumpExportReferenceListenerTargetDirectory =
|
||||
[ FDirName $(HAIKUDEPOT_GENERATED_SOURCES_DIRECTORY)
|
||||
dumpexportreferencelistener ] ;
|
||||
|
||||
local dumpExportPkgModelTargetDirectory =
|
||||
[ FDirName $(HAIKUDEPOT_GENERATED_SOURCES_DIRECTORY)
|
||||
dumpexportpkgmodel ] ;
|
||||
local dumpExportRepositoryModelTargetDirectory =
|
||||
[ FDirName $(HAIKUDEPOT_GENERATED_SOURCES_DIRECTORY)
|
||||
dumpexportrepositorymodel ] ;
|
||||
local dumpExportReferenceModelTargetDirectory =
|
||||
[ FDirName $(HAIKUDEPOT_GENERATED_SOURCES_DIRECTORY)
|
||||
dumpexportreferencemodel ] ;
|
||||
|
||||
# During the build process, some sources are generated into a directory. In
|
||||
# order to maintain a timestamp on that generation process, a dummy file is
|
||||
@@ -34,10 +41,15 @@ local dumpExportRepositoryBulkListerTargetFile =
|
||||
[ FDirName $(dumpExportRepositoryBulkListerTargetDirectory) $(dummyFile) ] ;
|
||||
local dumpExportPkgBulkListenerTargetFile =
|
||||
[ FDirName $(dumpExportPkgBulkListenerTargetDirectory) $(dummyFile) ] ;
|
||||
local dumpExportReferenceListenerTargetFile =
|
||||
[ FDirName $(dumpExportReferenceListenerTargetDirectory) $(dummyFile) ] ;
|
||||
|
||||
local dumpExportPkgModelTargetFile =
|
||||
[ FDirName $(dumpExportPkgModelTargetDirectory) $(dummyFile) ] ;
|
||||
local dumpExportRepositoryModelTargetFile =
|
||||
[ FDirName $(dumpExportRepositoryModelTargetDirectory) $(dummyFile) ] ;
|
||||
local dumpExportReferenceModelTargetFile =
|
||||
[ FDirName $(dumpExportReferenceModelTargetDirectory) $(dummyFile) ] ;
|
||||
|
||||
# source directories
|
||||
local sourceDirs =
|
||||
@@ -57,10 +69,14 @@ for sourceDir in $(sourceDirs) {
|
||||
}
|
||||
|
||||
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src servers package ] ;
|
||||
|
||||
SEARCH_SOURCE += $(dumpExportRepositoryBulkListerTargetDirectory) ;
|
||||
SEARCH_SOURCE += $(dumpExportPkgBulkListenerTargetDirectory) ;
|
||||
SEARCH_SOURCE += $(dumpExportReferenceListenerTargetDirectory) ;
|
||||
|
||||
SEARCH_SOURCE += $(dumpExportPkgModelTargetDirectory) ;
|
||||
SEARCH_SOURCE += $(dumpExportRepositoryModelTargetDirectory) ;
|
||||
SEARCH_SOURCE += $(dumpExportReferenceModelTargetDirectory) ;
|
||||
|
||||
local textDocumentSources =
|
||||
# edits_generic
|
||||
@@ -101,6 +117,7 @@ local applicationSources =
|
||||
FilterView.cpp
|
||||
LocalIconStore.cpp
|
||||
JobStateListener.cpp
|
||||
LanguageModel.cpp
|
||||
LinkView.cpp
|
||||
LinkedBitmapView.cpp
|
||||
Logger.cpp
|
||||
@@ -138,6 +155,7 @@ local applicationSources =
|
||||
ServerHelper.cpp
|
||||
ServerSettings.cpp
|
||||
ServerPkgDataUpdateProcess.cpp
|
||||
ServerReferenceDataUpdateProcess.cpp
|
||||
ServerRepositoryDataUpdateProcess.cpp
|
||||
ServerIconExportUpdateProcess.cpp
|
||||
StandardMetaDataJsonEventListener.cpp
|
||||
@@ -151,6 +169,7 @@ local applicationSources =
|
||||
# util
|
||||
AppUtils.cpp
|
||||
DataIOUtils.cpp
|
||||
LanguageMenuUtils.cpp
|
||||
RepositoryUrlUtils.cpp
|
||||
StorageUtils.cpp
|
||||
ToFileUrlProtocolListener.cpp
|
||||
@@ -173,6 +192,14 @@ local generatedRepositoryModelSourceFiles =
|
||||
DumpExportRepositorySourceMirror.cpp
|
||||
;
|
||||
|
||||
local generatedReferenceModelSourceFiles =
|
||||
DumpExportReference.cpp
|
||||
DumpExportReferenceNaturalLanguage.cpp
|
||||
DumpExportReferencePkgCategory.cpp
|
||||
DumpExportReferenceUserRatingStability.cpp
|
||||
DumpExportReferenceCountry.cpp
|
||||
;
|
||||
|
||||
local generatedPkgParserSourceFiles =
|
||||
DumpExportPkgJsonListener.cpp
|
||||
;
|
||||
@@ -181,10 +208,19 @@ local generatedRepositoryParserSourceFiles =
|
||||
DumpExportRepositoryJsonListener.cpp
|
||||
;
|
||||
|
||||
local generatedReferenceParserSourceFiles =
|
||||
DumpExportReferenceJsonListener.cpp
|
||||
;
|
||||
|
||||
Application HaikuDepot
|
||||
: $(applicationSources) $(textDocumentSources)
|
||||
$(generatedPkgModelSourceFiles) $(generatedRepositoryModelSourceFiles)
|
||||
$(generatedPkgParserSourceFiles) $(generatedRepositoryParserSourceFiles)
|
||||
: $(applicationSources)
|
||||
$(textDocumentSources)
|
||||
$(generatedPkgModelSourceFiles)
|
||||
$(generatedRepositoryModelSourceFiles)
|
||||
$(generatedReferenceModelSourceFiles)
|
||||
$(generatedPkgParserSourceFiles)
|
||||
$(generatedRepositoryParserSourceFiles)
|
||||
$(generatedReferenceParserSourceFiles)
|
||||
: be package bnetapi translation libcolumnlistview.a shared
|
||||
[ TargetLibstdc++ ] [ TargetLibsupc++ ] localestub
|
||||
: HaikuDepot.rdef
|
||||
@@ -225,12 +261,18 @@ HdsSchemaGenModel $(dumpExportPkgModelTargetFile)
|
||||
HdsSchemaGenModel $(dumpExportRepositoryModelTargetFile)
|
||||
: dumpexportrepository.json : jsonschema2cppmodel.py ;
|
||||
|
||||
HdsSchemaGenModel $(dumpExportReferenceModelTargetFile)
|
||||
: dumpexportreference.json : jsonschema2cppmodel.py ;
|
||||
|
||||
HdsSchemaGenBulkParser $(dumpExportRepositoryBulkListerTargetFile)
|
||||
: dumpexportrepository.json : jsonschema2cppparser.py ;
|
||||
|
||||
HdsSchemaGenBulkParser $(dumpExportPkgBulkListenerTargetFile)
|
||||
: dumpexportpkg.json : jsonschema2cppparser.py ;
|
||||
|
||||
HdsSchemaGenParser $(dumpExportReferenceListenerTargetFile)
|
||||
: dumpexportreference.json : jsonschema2cppparser.py ;
|
||||
|
||||
HdsSchemaGenAppSrcDependsOnGeneration
|
||||
[ FGristFiles $(generatedPkgParserSourceFiles) ]
|
||||
[ FGristFiles $(generatedPkgParserSourceFiles:S=.h) ]
|
||||
@@ -241,6 +283,11 @@ HdsSchemaGenAppSrcDependsOnGeneration
|
||||
[ FGristFiles $(generatedRepositoryParserSourceFiles:S=.h) ]
|
||||
: $(dumpExportRepositoryBulkListerTargetFile) ;
|
||||
|
||||
HdsSchemaGenAppSrcDependsOnGeneration
|
||||
[ FGristFiles $(generatedReferenceParserSourceFiles) ]
|
||||
[ FGristFiles $(generatedReferenceParserSourceFiles:S=.h) ]
|
||||
: $(dumpExportReferenceListenerTargetFile) ;
|
||||
|
||||
HdsSchemaGenAppSrcDependsOnGeneration
|
||||
[ FGristFiles $(generatedRepositoryModelSourceFiles) ]
|
||||
[ FGristFiles $(generatedRepositoryModelSourceFiles:S=.h) ]
|
||||
@@ -251,13 +298,20 @@ HdsSchemaGenAppSrcDependsOnGeneration
|
||||
[ FGristFiles $(generatedPkgModelSourceFiles:S=.h) ]
|
||||
: $(dumpExportPkgModelTargetFile) ;
|
||||
|
||||
HdsSchemaGenAppSrcDependsOnGeneration
|
||||
[ FGristFiles $(generatedReferenceModelSourceFiles) ]
|
||||
[ FGristFiles $(generatedReferenceModelSourceFiles:S=.h) ]
|
||||
: $(dumpExportReferenceModelTargetFile) ;
|
||||
|
||||
# This will ensure that if any of the generated files' header files change, then
|
||||
# the application should be re-built.
|
||||
|
||||
Depends [ FGristFiles $(applicationSources:S=.o) ]
|
||||
:
|
||||
[ FGristFiles $(generatedPkgParserSourceFiles:S=.h) ]
|
||||
[ FGristFiles $(generatedPkgModelSourceFiles:S=.h) ]
|
||||
[ FGristFiles $(generatedRepositoryParserSourceFiles:S=.h) ]
|
||||
[ FGristFiles $(generatedRepositoryModelSourceFiles:S=.h) ]
|
||||
[ FGristFiles $(generatedPkgModelSourceFiles:S=.h) ]
|
||||
[ FGristFiles $(generatedReferenceParserSourceFiles:S=.h) ]
|
||||
[ FGristFiles $(generatedReferenceModelSourceFiles:S=.h) ]
|
||||
;
|
||||
@@ -72,6 +72,29 @@ actions HdsSchemaGenBulkParser1
|
||||
touch $(1)
|
||||
}
|
||||
|
||||
# pragma mark - Non-Bulk Parsing Class Generation
|
||||
|
||||
# 1 : the dummy file in the class generation directory (target)
|
||||
# 2 : the JSON schema file
|
||||
# 3 : the Python script to use
|
||||
|
||||
rule HdsSchemaGenParser
|
||||
{
|
||||
SEARCH on $(2) = [ FDirName $(SUBDIR) server schema ] ;
|
||||
SEARCH on $(3) = [ FDirName $(SUBDIR) build scripts ] ;
|
||||
|
||||
Clean $(1:D) ;
|
||||
Depends $(1) : $(2) $(3) ;
|
||||
HdsSchemaGenParser1 $(1) : $(2) $(3) $(1:D) ;
|
||||
}
|
||||
|
||||
actions HdsSchemaGenParser1
|
||||
{
|
||||
mkdir -p $(2[3])
|
||||
$(HOST_PYTHON) $(2[2]) -i $(2[1]) --outputdirectory $(2[3])
|
||||
touch $(1)
|
||||
}
|
||||
|
||||
# pragma mark - Registering Generated Classes
|
||||
|
||||
# Because a number of .cpp and .h files will be generated from a single python
|
||||
|
||||
@@ -152,7 +152,27 @@ def writescalaraccessors(outputfile, cppclassname, cppname, cppmembername, cppty
|
||||
string.Template("""
|
||||
${cpptype}
|
||||
${cppclassname}::${cppname}()
|
||||
{
|
||||
{""").substitute(dict))
|
||||
|
||||
if cpptype == jscom.CPP_TYPE_BOOLEAN:
|
||||
outputfile.write(string.Template("""
|
||||
if (${cppname}IsNull())
|
||||
return false;
|
||||
""").substitute(dict))
|
||||
|
||||
if cpptype == jscom.CPP_TYPE_INTEGER:
|
||||
outputfile.write(string.Template("""
|
||||
if (${cppname}IsNull())
|
||||
return 0;
|
||||
""").substitute(dict))
|
||||
|
||||
if cpptype == jscom.CPP_TYPE_NUMBER:
|
||||
outputfile.write(string.Template("""
|
||||
if (${cppname}IsNull())
|
||||
return 0.0;
|
||||
""").substitute(dict))
|
||||
|
||||
outputfile.write(string.Template("""
|
||||
return *${cppmembername};
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright 2019, Andrew Lindesay <[email protected]>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#include "LanguageModel.h"
|
||||
|
||||
#include <Collator.h>
|
||||
#include <Locale.h>
|
||||
#include <LocaleRoster.h>
|
||||
|
||||
#include "HaikuDepotConstants.h"
|
||||
#include "Logger.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");
|
||||
}
|
||||
|
||||
BString name1;
|
||||
BString name2;
|
||||
|
||||
if (l1->GetName(name1) == B_OK && l2->GetName(name2) == B_OK)
|
||||
return collator.Compare(name1.String(), name2.String());
|
||||
|
||||
return collator.Compare(l1->Code(), l2->Code());
|
||||
}
|
||||
|
||||
|
||||
LanguageModel::LanguageModel()
|
||||
:
|
||||
fSupportedLanguages(LanguagesCompareFn, NULL),
|
||||
fPreferredLanguage(LANGUAGE_DEFAULT)
|
||||
{
|
||||
const Language defaultLanguage = _DeriveDefaultLanguage();
|
||||
fSupportedLanguages.Add(LanguageRef(
|
||||
new Language(defaultLanguage)));
|
||||
_SetPreferredLanguage(defaultLanguage);
|
||||
}
|
||||
|
||||
|
||||
LanguageModel::~LanguageModel()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LanguageModel::AddSupportedLanguages(const LanguageList& languages)
|
||||
{
|
||||
for (int32 i = 0; i < languages.CountItems(); i++) {
|
||||
const LanguageRef language = languages.ItemAt(i);
|
||||
int32 index = IndexOfSupportedLanguage(language->Code());
|
||||
|
||||
if (index == -1)
|
||||
fSupportedLanguages.Add(language);
|
||||
else
|
||||
fSupportedLanguages.Replace(index, language);
|
||||
}
|
||||
|
||||
// it could be that the preferred language does not exist in the
|
||||
// list. In this case it is necessary to choose one from the list.
|
||||
_SetPreferredLanguage(_DeriveDefaultLanguage());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LanguageModel::_SetPreferredLanguage(const Language& language)
|
||||
{
|
||||
fPreferredLanguage = language;
|
||||
if(Logger::IsDebugEnabled())
|
||||
printf("set preferred language [%s]\n", language.Code());
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
LanguageModel::IndexOfSupportedLanguage(const BString& languageCode) const
|
||||
{
|
||||
for (int32 i = 0; i < fSupportedLanguages.CountItems(); i++) {
|
||||
if (fSupportedLanguages.ItemAt(i)->Code() == languageCode)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*! This will derive the default language. If there are no other
|
||||
possible languages configured then the default language will be
|
||||
assumed to exist. Otherwise if there is a set of possible languages
|
||||
then this method will ensure that the default language is in that
|
||||
set.
|
||||
*/
|
||||
|
||||
Language
|
||||
LanguageModel::_DeriveDefaultLanguage() const
|
||||
{
|
||||
Language defaultLanguage = _DeriveSystemDefaultLanguage();
|
||||
|
||||
if(Logger::IsDebugEnabled()) {
|
||||
printf("derived system default language [%s]\n",
|
||||
defaultLanguage.Code());
|
||||
}
|
||||
|
||||
// if there are no supported languages; as is the case to start with as the
|
||||
// application starts, the default language from the system is used anyway.
|
||||
// The data queried in HDS will handle the case where the language is not
|
||||
// 'known' at the HDS end so it doesn't matter if it is invalid.
|
||||
|
||||
if (fSupportedLanguages.IsEmpty())
|
||||
return defaultLanguage;
|
||||
|
||||
// if there are supported languages defined then the preferred language
|
||||
// needs to be one of the supported ones.
|
||||
|
||||
Language* foundSupportedLanguage = _FindSupportedLanguage(
|
||||
defaultLanguage.Code());
|
||||
|
||||
if (foundSupportedLanguage == NULL) {
|
||||
printf("unable to find the language [%s] - looking for app default",
|
||||
defaultLanguage.Code());
|
||||
foundSupportedLanguage = _FindSupportedLanguage(
|
||||
LANGUAGE_DEFAULT.Code());
|
||||
}
|
||||
|
||||
if (foundSupportedLanguage == NULL) {
|
||||
printf("unable to find the app default language - using the first "
|
||||
"supported language");
|
||||
foundSupportedLanguage = fSupportedLanguages.ItemAt(0);
|
||||
}
|
||||
|
||||
return Language(*foundSupportedLanguage);
|
||||
}
|
||||
|
||||
|
||||
/*static*/ Language
|
||||
LanguageModel::_DeriveSystemDefaultLanguage()
|
||||
{
|
||||
BLocaleRoster* localeRoster = BLocaleRoster::Default();
|
||||
if (localeRoster != NULL) {
|
||||
BMessage preferredLanguages;
|
||||
if (localeRoster->GetPreferredLanguages(&preferredLanguages) == B_OK) {
|
||||
BString language;
|
||||
BString languageIso;
|
||||
if (preferredLanguages.FindString(
|
||||
"language", 0, &language) == B_OK) {
|
||||
language.CopyInto(languageIso, 0, 2);
|
||||
return Language(languageIso, languageIso, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return LANGUAGE_DEFAULT;
|
||||
}
|
||||
|
||||
|
||||
Language*
|
||||
LanguageModel::_FindSupportedLanguage(const BString& code) const
|
||||
{
|
||||
int32 index = IndexOfSupportedLanguage(code);
|
||||
if (-1 == index)
|
||||
return NULL;
|
||||
return fSupportedLanguages.ItemAt(index);
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2019, Andrew Lindesay <[email protected]>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef LANGUAGE_MODEL_H
|
||||
#define LANGUAGE_MODEL_H
|
||||
|
||||
|
||||
#include <Referenceable.h>
|
||||
|
||||
#include "List.h"
|
||||
#include "PackageInfo.h"
|
||||
|
||||
|
||||
typedef BReference<Language> LanguageRef;
|
||||
typedef List<LanguageRef, false> LanguageList;
|
||||
|
||||
|
||||
class LanguageModel {
|
||||
public:
|
||||
LanguageModel();
|
||||
virtual ~LanguageModel();
|
||||
|
||||
const LanguageList& SupportedLanguages() const
|
||||
{ return fSupportedLanguages; }
|
||||
void AddSupportedLanguages(
|
||||
const LanguageList& languages);
|
||||
int32 IndexOfSupportedLanguage(
|
||||
const BString& languageCode) const;
|
||||
|
||||
const Language& PreferredLanguage() const
|
||||
{ return fPreferredLanguage; }
|
||||
|
||||
private:
|
||||
static Language _DeriveSystemDefaultLanguage();
|
||||
Language _DeriveDefaultLanguage() const;
|
||||
Language* _FindSupportedLanguage(
|
||||
const BString& code) const;
|
||||
void _SetPreferredLanguage(const Language& language);
|
||||
|
||||
private:
|
||||
LanguageList fSupportedLanguages;
|
||||
Language fPreferredLanguage;
|
||||
};
|
||||
|
||||
|
||||
#endif // LANGUAGE_MODEL_H
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
||||
* Copyright 2014, Axel Dörfler <[email protected]>.
|
||||
* Copyright 2016-2018, Andrew Lindesay <[email protected]>.
|
||||
* Copyright 2016-2019, Andrew Lindesay <[email protected]>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@@ -353,7 +353,6 @@ Model::Model()
|
||||
fDepotFilter(""),
|
||||
fSearchTermsFilter(PackageFilterRef(new AnyFilter(), true)),
|
||||
fIsFeaturedFilter(),
|
||||
|
||||
fShowFeaturedPackages(true),
|
||||
fShowAvailablePackages(true),
|
||||
fShowInstalledPackages(true),
|
||||
@@ -378,38 +377,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.
|
||||
|
||||
fPreferredLanguage = "en";
|
||||
BLocaleRoster* localeRoster = BLocaleRoster::Default();
|
||||
if (localeRoster != NULL) {
|
||||
BMessage preferredLanguages;
|
||||
if (localeRoster->GetPreferredLanguages(&preferredLanguages) == B_OK) {
|
||||
BString language;
|
||||
if (preferredLanguages.FindString("language", 0, &language) == B_OK)
|
||||
language.CopyInto(fPreferredLanguage, 0, 2);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Fetch this from the web-app.
|
||||
fSupportedLanguages.Add("en");
|
||||
fSupportedLanguages.Add("es");
|
||||
fSupportedLanguages.Add("de");
|
||||
fSupportedLanguages.Add("fr");
|
||||
fSupportedLanguages.Add("it");
|
||||
fSupportedLanguages.Add("ja");
|
||||
fSupportedLanguages.Add("pt");
|
||||
fSupportedLanguages.Add("ru");
|
||||
fSupportedLanguages.Add("sk");
|
||||
fSupportedLanguages.Add("zh");
|
||||
|
||||
if (!fSupportedLanguages.Contains(fPreferredLanguage)) {
|
||||
// Force the preferred language to one of the currently supported
|
||||
// ones, until the web application supports all ISO language codes.
|
||||
printf("User preferred language '%s' not currently supported, "
|
||||
"defaulting to 'en'.\n", fPreferredLanguage.String());
|
||||
fPreferredLanguage = "en";
|
||||
}
|
||||
fWebAppInterface.SetPreferredLanguage(fPreferredLanguage);
|
||||
}
|
||||
|
||||
|
||||
@@ -418,6 +385,13 @@ Model::~Model()
|
||||
}
|
||||
|
||||
|
||||
LanguageModel&
|
||||
Model::Language()
|
||||
{
|
||||
return fLanguageModel;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Model::AddListener(const ModelListenerRef& listener)
|
||||
{
|
||||
@@ -903,6 +877,30 @@ Model::SetAuthorization(const BString& username, const BString& password,
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Model::_LocalDataPath(const BString leaf, BPath& path) const
|
||||
{
|
||||
BString leafAssembled(leaf);
|
||||
leafAssembled.ReplaceAll("%languageCode%",
|
||||
LanguageModel().PreferredLanguage().Code());
|
||||
|
||||
BPath repoDataPath;
|
||||
|
||||
if (find_directory(B_USER_CACHE_DIRECTORY, &repoDataPath) == B_OK
|
||||
&& repoDataPath.Append("HaikuDepot") == B_OK
|
||||
&& create_directory(repoDataPath.Path(), 0777) == B_OK
|
||||
&& repoDataPath.Append(leafAssembled) == B_OK) {
|
||||
path.SetTo(repoDataPath.Path());
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
path.Unset();
|
||||
fprintf(stdout, "unable to find the user cache file for [%s] data",
|
||||
leaf.String());
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/*! When bulk repository data comes down from the server, it will
|
||||
arrive as a json.gz payload. This is stored locally as a cache
|
||||
and this method will provide the on-disk storage location for
|
||||
@@ -912,20 +910,19 @@ Model::SetAuthorization(const BString& username, const BString& password,
|
||||
status_t
|
||||
Model::DumpExportRepositoryDataPath(BPath& path) const
|
||||
{
|
||||
BPath repoDataPath;
|
||||
return _LocalDataPath("repository-all_%languageCode%.json.gz", path);
|
||||
}
|
||||
|
||||
if (find_directory(B_USER_CACHE_DIRECTORY, &repoDataPath) == B_OK
|
||||
&& repoDataPath.Append("HaikuDepot") == B_OK
|
||||
&& create_directory(repoDataPath.Path(), 0777) == B_OK
|
||||
&& repoDataPath.Append("repository-all_en.json.gz") == B_OK) {
|
||||
path.SetTo(repoDataPath.Path());
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
path.Unset();
|
||||
fprintf(stdout, "unable to find the user cache file for repositories'"
|
||||
" data");
|
||||
return B_ERROR;
|
||||
/*! When the system downloads reference data (eg; categories) from the server
|
||||
then the downloaded data is stored and cached at the path defined by this
|
||||
method.
|
||||
*/
|
||||
|
||||
status_t
|
||||
Model::DumpExportReferenceDataPath(BPath& path) const
|
||||
{
|
||||
return _LocalDataPath("reference-all_%languageCode%.json.gz", path);
|
||||
}
|
||||
|
||||
|
||||
@@ -956,7 +953,7 @@ Model::DumpExportPkgDataPath(BPath& path,
|
||||
BString leafName;
|
||||
|
||||
leafName.SetToFormat("pkg-all-%s-%s.json.gz", repositorySourceCode.String(),
|
||||
fPreferredLanguage.String());
|
||||
LanguageModel().PreferredLanguage().Code());
|
||||
|
||||
if (find_directory(B_USER_CACHE_DIRECTORY, &repoDataPath) == B_OK
|
||||
&& repoDataPath.Append("HaikuDepot") == B_OK
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
||||
* Copyright 2016-2018, Andrew Lindesay <[email protected]>.
|
||||
* Copyright 2016-2019, Andrew Lindesay <[email protected]>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef MODEL_H
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <Locker.h>
|
||||
|
||||
#include "AbstractProcess.h"
|
||||
#include "LanguageModel.h"
|
||||
#include "LocalIconStore.h"
|
||||
#include "PackageInfo.h"
|
||||
#include "WebAppInterface.h"
|
||||
@@ -63,6 +64,8 @@ public:
|
||||
Model();
|
||||
virtual ~Model();
|
||||
|
||||
LanguageModel& Language();
|
||||
|
||||
BLocker* Lock()
|
||||
{ return &fLock; }
|
||||
|
||||
@@ -150,12 +153,6 @@ public:
|
||||
void PopulatePackage(const PackageInfoRef& package,
|
||||
uint32 flags);
|
||||
|
||||
const StringList& SupportedLanguages() const
|
||||
{ return fSupportedLanguages; }
|
||||
|
||||
const BString& PreferredLanguage() const
|
||||
{ return fPreferredLanguage; }
|
||||
|
||||
void SetUsername(BString username);
|
||||
const BString& Username() const;
|
||||
void SetAuthorization(const BString& username,
|
||||
@@ -171,6 +168,7 @@ public:
|
||||
void* context);
|
||||
|
||||
status_t IconStoragePath(BPath& path) const;
|
||||
status_t DumpExportReferenceDataPath(BPath& path) const;
|
||||
status_t DumpExportRepositoryDataPath(BPath& path) const;
|
||||
status_t DumpExportPkgDataPath(BPath& path,
|
||||
const BString& repositorySourceCode) const;
|
||||
@@ -178,6 +176,9 @@ public:
|
||||
void LogDepotsWithNoWebAppRepositoryCode() const;
|
||||
|
||||
private:
|
||||
status_t _LocalDataPath(const BString leaf,
|
||||
BPath& path) const;
|
||||
|
||||
void _MaybeLogJsonRpcError(
|
||||
const BMessage &responsePayload,
|
||||
const char *sourceDescription) const;
|
||||
@@ -245,9 +246,7 @@ private:
|
||||
bool fShowSourcePackages;
|
||||
bool fShowDevelopPackages;
|
||||
|
||||
StringList fSupportedLanguages;
|
||||
BString fPreferredLanguage;
|
||||
|
||||
LanguageModel fLanguageModel;
|
||||
WebAppInterface fWebAppInterface;
|
||||
|
||||
ModelListenerList fListeners;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
||||
* Copyright 2013, Rene Gollent <[email protected]>.
|
||||
* Copyright 2016-2018, Andrew Lindesay <[email protected]>.
|
||||
* Copyright 2016-2019, Andrew Lindesay <[email protected]>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@@ -15,6 +15,41 @@
|
||||
#include <Path.h>
|
||||
|
||||
|
||||
// #pragma mark - Language
|
||||
|
||||
|
||||
Language::Language(const char* language, const BString& serverName,
|
||||
bool isPopular)
|
||||
:
|
||||
BLanguage(language),
|
||||
fServerName(serverName),
|
||||
fIsPopular(isPopular)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Language::Language(const Language& other)
|
||||
:
|
||||
BLanguage(other.Code()),
|
||||
fServerName(other.fServerName),
|
||||
fIsPopular(other.fIsPopular)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Language::GetName(BString& name,
|
||||
const BLanguage* displayLanguage) const
|
||||
{
|
||||
status_t result = BLanguage::GetName(name, displayLanguage);
|
||||
|
||||
if (result == B_OK && (name.IsEmpty() || name == Code()))
|
||||
name.SetTo(fServerName);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - UserInfo
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright 2013-2014, Stephan Aßmus <superstippi@gmx.de>.
|
||||
* Copyright 2016-2018, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||
* Copyright 2016-2019, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef PACKAGE_INFO_H
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <set>
|
||||
|
||||
#include <Language.h>
|
||||
#include <Referenceable.h>
|
||||
#include <package/PackageInfo.h>
|
||||
|
||||
@@ -21,6 +22,30 @@
|
||||
class BPath;
|
||||
|
||||
|
||||
/*! This class represents a language that is supported by the Haiku
|
||||
Depot Server system. This may differ from the set of languages
|
||||
that are supported in the platform itself.
|
||||
*/
|
||||
|
||||
class Language : public BReferenceable, public BLanguage {
|
||||
public:
|
||||
Language(const char* language,
|
||||
const BString& serverName,
|
||||
bool isPopular);
|
||||
Language(const Language& other);
|
||||
|
||||
status_t GetName(BString& name,
|
||||
const BLanguage* displayLanguage = NULL
|
||||
) const;
|
||||
bool IsPopular() const
|
||||
{ return fIsPopular; }
|
||||
|
||||
private:
|
||||
BString fServerName;
|
||||
bool fIsPopular;
|
||||
};
|
||||
|
||||
|
||||
class UserInfo {
|
||||
public:
|
||||
UserInfo();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||
* Copyright 2018-2019, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "ServerHelper.h"
|
||||
#include "ServerIconExportUpdateProcess.h"
|
||||
#include "ServerPkgDataUpdateProcess.h"
|
||||
#include "ServerReferenceDataUpdateProcess.h"
|
||||
#include "ServerRepositoryDataUpdateProcess.h"
|
||||
#include "ServerSettings.h"
|
||||
|
||||
@@ -62,6 +63,11 @@ ProcessCoordinatorFactory::CreateBulkLoadCoordinator(
|
||||
serverRepositoryDataUpdate->AddPredecessor(localPkgDataLoad);
|
||||
processCoordinator->AddNode(serverRepositoryDataUpdate);
|
||||
|
||||
ProcessNode *serverReferenceDataUpdate =
|
||||
new ProcessNode(new ServerReferenceDataUpdateProcess(model,
|
||||
serverProcessOptions));
|
||||
processCoordinator->AddNode(serverReferenceDataUpdate);
|
||||
|
||||
// create a process for each of the repositories that are configured on the
|
||||
// local system. Later, only those that have a web-app repository server
|
||||
// code will be actually processed, but this means that the creation of the
|
||||
@@ -74,9 +80,11 @@ ProcessCoordinatorFactory::CreateBulkLoadCoordinator(
|
||||
if (repoNamesResult == B_OK) {
|
||||
for (int32 i = 0; i < repoNames.CountStrings(); i++) {
|
||||
ProcessNode* processNode = new ProcessNode(
|
||||
new ServerPkgDataUpdateProcess(model->PreferredLanguage(),
|
||||
new ServerPkgDataUpdateProcess(
|
||||
model->Language().PreferredLanguage().Code(),
|
||||
repoNames.StringAt(i), model, serverProcessOptions));
|
||||
processNode->AddPredecessor(serverRepositoryDataUpdate);
|
||||
processNode->AddPredecessor(serverReferenceDataUpdate);
|
||||
processCoordinator->AddNode(processNode);
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright 2019, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "ServerReferenceDataUpdateProcess.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <AutoDeleter.h>
|
||||
#include <Catalog.h>
|
||||
#include <FileIO.h>
|
||||
#include <Url.h>
|
||||
|
||||
#include "ServerSettings.h"
|
||||
#include "StorageUtils.h"
|
||||
#include "Logger.h"
|
||||
#include "DumpExportReference.h"
|
||||
#include "DumpExportReferenceNaturalLanguage.h"
|
||||
#include "DumpExportReferencePkgCategory.h"
|
||||
#include "DumpExportReferenceUserRatingStability.h"
|
||||
#include "DumpExportReferenceCountry.h"
|
||||
#include "DumpExportReferenceJsonListener.h"
|
||||
|
||||
|
||||
#undef B_TRANSLATION_CONTEXT
|
||||
#define B_TRANSLATION_CONTEXT "ServerReferenceDataUpdateProcess"
|
||||
|
||||
|
||||
ServerReferenceDataUpdateProcess::ServerReferenceDataUpdateProcess(
|
||||
Model* model,
|
||||
uint32 serverProcessOptions)
|
||||
:
|
||||
AbstractSingleFileServerProcess(serverProcessOptions),
|
||||
fModel(model)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ServerReferenceDataUpdateProcess::~ServerReferenceDataUpdateProcess()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
const char*
|
||||
ServerReferenceDataUpdateProcess::Name() const
|
||||
{
|
||||
return "ServerReferenceDataUpdateProcess";
|
||||
}
|
||||
|
||||
|
||||
const char*
|
||||
ServerReferenceDataUpdateProcess::Description() const
|
||||
{
|
||||
return B_TRANSLATE("Synchronizing reference data from server");
|
||||
}
|
||||
|
||||
|
||||
BString
|
||||
ServerReferenceDataUpdateProcess::UrlPathComponent()
|
||||
{
|
||||
BString result;
|
||||
result.SetToFormat("/__reference/all-%s.json.gz",
|
||||
fModel->Language().PreferredLanguage().Code());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ServerReferenceDataUpdateProcess::GetLocalPath(BPath& path) const
|
||||
{
|
||||
return fModel->DumpExportReferenceDataPath(path);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ServerReferenceDataUpdateProcess::ProcessLocalData()
|
||||
{
|
||||
SingleDumpExportReferenceJsonListener* listener =
|
||||
new SingleDumpExportReferenceJsonListener();
|
||||
|
||||
BPath localPath;
|
||||
status_t result = GetLocalPath(localPath);
|
||||
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
result = ParseJsonFromFileWithListener(listener, localPath);
|
||||
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
result = listener->ErrorStatus();
|
||||
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
return _ProcessData(listener->Target());
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ServerReferenceDataUpdateProcess::_ProcessData(DumpExportReference* data)
|
||||
{
|
||||
// more to come here later...
|
||||
return _ProcessNaturalLanguages(data);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ServerReferenceDataUpdateProcess::_ProcessNaturalLanguages(
|
||||
DumpExportReference* data)
|
||||
{
|
||||
printf("[%s] will populate %" B_PRId32 " natural languages\n",
|
||||
Name(), data->CountNaturalLanguages());
|
||||
|
||||
LanguageList result;
|
||||
|
||||
for (int32 i = 0; i < data->CountNaturalLanguages(); i++) {
|
||||
DumpExportReferenceNaturalLanguage* naturalLanguage =
|
||||
data->NaturalLanguagesItemAt(i);
|
||||
result.Add(LanguageRef(new Language(
|
||||
*(naturalLanguage->Code()),
|
||||
*(naturalLanguage->Name()),
|
||||
naturalLanguage->IsPopular())));
|
||||
}
|
||||
|
||||
fModel->Language().AddSupportedLanguages(result);
|
||||
|
||||
printf("[%s] did add %" B_PRId32 " supported languages\n",
|
||||
Name(), result.CountItems());
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ServerReferenceDataUpdateProcess::GetStandardMetaDataPath(BPath& path) const
|
||||
{
|
||||
return GetLocalPath(path);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ServerReferenceDataUpdateProcess::GetStandardMetaDataJsonPath(
|
||||
BString& jsonPath) const
|
||||
{
|
||||
jsonPath.SetTo("$.info");
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2019, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef SERVER_REFERENCE_DATA_UPDATE_PROCESS_H
|
||||
#define SERVER_REFERENCE_DATA_UPDATE_PROCESS_H
|
||||
|
||||
|
||||
#include "AbstractSingleFileServerProcess.h"
|
||||
|
||||
#include <File.h>
|
||||
#include <Path.h>
|
||||
#include <String.h>
|
||||
#include <Url.h>
|
||||
|
||||
#include "Model.h"
|
||||
#include "PackageInfo.h"
|
||||
|
||||
|
||||
#undef B_TRANSLATION_CONTEXT
|
||||
#define B_TRANSLATION_CONTEXT "ServerReferenceDataUpdateProcess"
|
||||
|
||||
class DumpExportReference;
|
||||
|
||||
class ServerReferenceDataUpdateProcess : public AbstractSingleFileServerProcess
|
||||
{
|
||||
public:
|
||||
|
||||
ServerReferenceDataUpdateProcess(
|
||||
Model* model, uint32 serverProcessOptions);
|
||||
virtual ~ServerReferenceDataUpdateProcess();
|
||||
|
||||
const char* Name() const;
|
||||
const char* Description() const;
|
||||
|
||||
protected:
|
||||
status_t GetStandardMetaDataPath(BPath& path) const;
|
||||
void GetStandardMetaDataJsonPath(
|
||||
BString& jsonPath) const;
|
||||
|
||||
BString UrlPathComponent();
|
||||
status_t ProcessLocalData();
|
||||
status_t GetLocalPath(BPath& path) const;
|
||||
|
||||
private:
|
||||
status_t _ProcessData(DumpExportReference* data);
|
||||
status_t _ProcessNaturalLanguages(
|
||||
DumpExportReference* data);
|
||||
|
||||
private:
|
||||
Model* fModel;
|
||||
|
||||
};
|
||||
|
||||
#endif // SERVER_REFERENCE_DATA_UPDATE_PROCESS_H
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2018, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||
* Copyright 2017-2019, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@@ -177,7 +177,10 @@ ServerRepositoryDataUpdateProcess::Description() const
|
||||
BString
|
||||
ServerRepositoryDataUpdateProcess::UrlPathComponent()
|
||||
{
|
||||
return BString("/__repository/all-en.json.gz");
|
||||
BString result;
|
||||
result.SetToFormat("/__repository/all-%s.json.gz",
|
||||
fModel->Language().PreferredLanguage().Code());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright 2014, Stephan Aßmus <superstippi@gmx.de>.
|
||||
* Copyright 2016-2018, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||
* Copyright 2016-2019, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@@ -271,8 +271,6 @@ enum {
|
||||
|
||||
|
||||
WebAppInterface::WebAppInterface()
|
||||
:
|
||||
fLanguage("en")
|
||||
{
|
||||
}
|
||||
|
||||
@@ -280,8 +278,7 @@ WebAppInterface::WebAppInterface()
|
||||
WebAppInterface::WebAppInterface(const WebAppInterface& other)
|
||||
:
|
||||
fUsername(other.fUsername),
|
||||
fPassword(other.fPassword),
|
||||
fLanguage(other.fLanguage)
|
||||
fPassword(other.fPassword)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -296,11 +293,8 @@ WebAppInterface::operator=(const WebAppInterface& other)
|
||||
{
|
||||
if (this == &other)
|
||||
return *this;
|
||||
|
||||
fUsername = other.fUsername;
|
||||
fPassword = other.fPassword;
|
||||
fLanguage = other.fLanguage;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -314,13 +308,6 @@ WebAppInterface::SetAuthorization(const BString& username,
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WebAppInterface::SetPreferredLanguage(const BString& language)
|
||||
{
|
||||
fLanguage = language;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
WebAppInterface::GetChangelog(const BString& packageName, BMessage& message)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright 2014, Stephan Aßmus <superstippi@gmx.de>.
|
||||
* Copyright 2016-2018, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||
* Copyright 2016-2019, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef WEB_APP_INTERFACE_H
|
||||
@@ -51,9 +51,6 @@ public:
|
||||
const BString& Username() const
|
||||
{ return fUsername; }
|
||||
|
||||
void SetPreferredLanguage(const BString& language);
|
||||
void SetArchitecture(const BString& architecture);
|
||||
|
||||
status_t GetChangelog(
|
||||
const BString& packageName,
|
||||
BMessage& message);
|
||||
@@ -130,7 +127,6 @@ private:
|
||||
private:
|
||||
BString fUsername;
|
||||
BString fPassword;
|
||||
BString fLanguage;
|
||||
static int fRequestIndex;
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/schema#",
|
||||
"id": "http://depot.haiku-os.org/schema/reference/dumpreference.json",
|
||||
"title": "Reference",
|
||||
"javaType": "org.haiku.haikudepotserver.reference.model.dumpexport.DumpExportReference",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"naturalLanguages": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"javaType": "org.haiku.haikudepotserver.reference.model.dumpexport.DumpExportReferenceNaturalLanguage",
|
||||
"properties": {
|
||||
"code": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"isPopular": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"pkgCategories": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"javaType": "org.haiku.haikudepotserver.reference.model.dumpexport.DumpExportReferencePkgCategory",
|
||||
"properties": {
|
||||
"code": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"userRatingStabilities": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"javaType": "org.haiku.haikudepotserver.reference.model.dumpexport.DumpExportReferenceUserRatingStability",
|
||||
"properties": {
|
||||
"code": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"countries": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"javaType": "org.haiku.haikudepotserver.reference.model.dumpexport.DumpExportReferenceCountry",
|
||||
"properties": {
|
||||
"code": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright 2013-2014, Stephan Aßmus <superstippi@gmx.de>.
|
||||
* Copyright 2018, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||
* Copyright 2018-2019, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@@ -1050,8 +1050,6 @@ public:
|
||||
.Add(scrollView, 1.0f)
|
||||
.SetInsets(B_USE_DEFAULT_SPACING, -1.0f, -1.0f, -1.0f)
|
||||
;
|
||||
|
||||
_InitPreferredLanguages();
|
||||
}
|
||||
|
||||
virtual ~UserRatingsView()
|
||||
@@ -1113,33 +1111,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void _InitPreferredLanguages()
|
||||
{
|
||||
fPreferredLanguages.Clear();
|
||||
|
||||
BLocaleRoster* localeRoster = BLocaleRoster::Default();
|
||||
if (localeRoster == NULL)
|
||||
return;
|
||||
|
||||
BMessage preferredLanguages;
|
||||
if (localeRoster->GetPreferredLanguages(&preferredLanguages) != B_OK)
|
||||
return;
|
||||
|
||||
BString language;
|
||||
int32 index = 0;
|
||||
while (preferredLanguages.FindString("language", index++,
|
||||
&language) == B_OK) {
|
||||
BString languageCode;
|
||||
language.CopyInto(languageCode, 0, 2);
|
||||
fPreferredLanguages.Add(languageCode);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
BGroupLayout* fRatingContainerLayout;
|
||||
RatingSummaryView* fRatingSummaryView;
|
||||
StringList fPreferredLanguages;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright 2014, Stephan Aßmus <superstippi@gmx.de>.
|
||||
* Copyright 2016-2018, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||
* Copyright 2016-2019, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <StringView.h>
|
||||
|
||||
#include "HaikuDepotConstants.h"
|
||||
#include "LanguageMenuUtils.h"
|
||||
#include "MarkupParser.h"
|
||||
#include "RatingView.h"
|
||||
#include "ServerHelper.h"
|
||||
@@ -37,7 +38,6 @@ enum {
|
||||
MSG_SEND = 'send',
|
||||
MSG_PACKAGE_RATED = 'rpkg',
|
||||
MSG_STABILITY_SELECTED = 'stbl',
|
||||
MSG_LANGUAGE_SELECTED = 'lngs',
|
||||
MSG_RATING_ACTIVE_CHANGED = 'rtac',
|
||||
MSG_RATING_DETERMINATE_CHANGED = 'rdch'
|
||||
};
|
||||
@@ -180,19 +180,6 @@ add_stabilities_to_menu(const StabilityRatingList& stabilities, BMenu* menu)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
add_languages_to_menu(const StringList& languages, BMenu* menu)
|
||||
{
|
||||
for (int i = 0; i < languages.CountItems(); i++) {
|
||||
const BString& language = languages.ItemAtFast(i);
|
||||
BMessage* message = new BMessage(MSG_LANGUAGE_SELECTED);
|
||||
message->AddString("code", language);
|
||||
BMenuItem* item = new BMenuItem(language, message);
|
||||
menu->AddItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RatePackageWindow::RatePackageWindow(BWindow* parent, BRect frame,
|
||||
Model& model)
|
||||
:
|
||||
@@ -204,7 +191,7 @@ RatePackageWindow::RatePackageWindow(BWindow* parent, BRect frame,
|
||||
fTextEditor(new TextEditor(), true),
|
||||
fRating(RATING_NONE),
|
||||
fRatingDeterminate(false),
|
||||
fCommentLanguage(fModel.PreferredLanguage()),
|
||||
fCommentLanguageCode(fModel.Language().PreferredLanguage().Code()),
|
||||
fWorkerThread(-1)
|
||||
{
|
||||
AddToSubset(parent);
|
||||
@@ -260,13 +247,12 @@ RatePackageWindow::RatePackageWindow(BWindow* parent, BRect frame,
|
||||
fCommentLanguageField = new BMenuField("language",
|
||||
B_TRANSLATE("Comment language:"), languagesMenu);
|
||||
|
||||
add_languages_to_menu(fModel.SupportedLanguages(), languagesMenu);
|
||||
LanguageMenuUtils::AddLanguagesToMenu(
|
||||
fModel.Language().SupportedLanguages(),
|
||||
languagesMenu);
|
||||
languagesMenu->SetTargetForItems(this);
|
||||
|
||||
BMenuItem* defaultItem = languagesMenu->ItemAt(
|
||||
fModel.SupportedLanguages().IndexOf(fCommentLanguage));
|
||||
if (defaultItem != NULL)
|
||||
defaultItem->SetMarked(true);
|
||||
LanguageMenuUtils::MarkLanguageInMenu(fCommentLanguageCode,
|
||||
languagesMenu);
|
||||
|
||||
fRatingActiveCheckBox = new BCheckBox("rating active",
|
||||
B_TRANSLATE("Other users can see this rating"),
|
||||
@@ -348,7 +334,7 @@ RatePackageWindow::MessageReceived(BMessage* message)
|
||||
break;
|
||||
|
||||
case MSG_LANGUAGE_SELECTED:
|
||||
message->FindString("code", &fCommentLanguage);
|
||||
message->FindString("code", &fCommentLanguageCode);
|
||||
break;
|
||||
|
||||
case MSG_RATING_DETERMINATE_CHANGED:
|
||||
@@ -514,11 +500,9 @@ RatePackageWindow::_RelayServerDataToUI(BMessage& response)
|
||||
item->SetMarked(true);
|
||||
}
|
||||
if (response.FindString("naturalLanguageCode",
|
||||
&fCommentLanguage) == B_OK) {
|
||||
BMenuItem* item = fCommentLanguageField->Menu()->ItemAt(
|
||||
fModel.SupportedLanguages().IndexOf(fCommentLanguage));
|
||||
if (item != NULL)
|
||||
item->SetMarked(true);
|
||||
&fCommentLanguageCode) == B_OK) {
|
||||
LanguageMenuUtils::MarkLanguageInMenu(
|
||||
fCommentLanguageCode, fCommentLanguageField->Menu());
|
||||
}
|
||||
double rating;
|
||||
if (response.FindDouble("rating", &rating) == B_OK) {
|
||||
@@ -649,7 +633,7 @@ RatePackageWindow::_SendRatingThread()
|
||||
int rating = (int)fRating;
|
||||
BString stability = fStability;
|
||||
BString comment = fRatingText->Text();
|
||||
BString languageCode = fCommentLanguage;
|
||||
BString languageCode = fCommentLanguageCode;
|
||||
BString ratingID = fRatingID;
|
||||
bool active = fRatingActive;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright 2014, Stephan Aßmus <superstippi@gmx.de>.
|
||||
* Copyright 2018, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||
* Copyright 2018-2019, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef RATE_PACKAGE_WINDOW_H
|
||||
@@ -56,7 +56,7 @@ private:
|
||||
bool fRatingDeterminate;
|
||||
BString fStability;
|
||||
StabilityRatingList fStabilityCodes;
|
||||
BString fCommentLanguage;
|
||||
BString fCommentLanguageCode;
|
||||
BString fRatingID;
|
||||
bool fRatingActive;
|
||||
PackageInfoRef fPackage;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2014, Stephan Aßmus <superstippi@gmx.de>.
|
||||
* Copyright 2019, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@@ -21,6 +22,8 @@
|
||||
#include <UnicodeChar.h>
|
||||
|
||||
#include "BitmapView.h"
|
||||
#include "HaikuDepotConstants.h"
|
||||
#include "LanguageMenuUtils.h"
|
||||
#include "Model.h"
|
||||
#include "TabView.h"
|
||||
#include "WebAppInterface.h"
|
||||
@@ -34,31 +37,17 @@ enum {
|
||||
MSG_SEND = 'send',
|
||||
MSG_TAB_SELECTED = 'tbsl',
|
||||
MSG_CAPTCHA_OBTAINED = 'cpob',
|
||||
MSG_VALIDATE_FIELDS = 'vldt',
|
||||
MSG_LANGUAGE_SELECTED = 'lngs',
|
||||
MSG_VALIDATE_FIELDS = 'vldt'
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
add_languages_to_menu(const StringList& languages, BMenu* menu)
|
||||
{
|
||||
for (int i = 0; i < languages.CountItems(); i++) {
|
||||
const BString& language = languages.ItemAtFast(i);
|
||||
BMessage* message = new BMessage(MSG_LANGUAGE_SELECTED);
|
||||
message->AddString("code", language);
|
||||
BMenuItem* item = new BMenuItem(language, message);
|
||||
menu->AddItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
UserLoginWindow::UserLoginWindow(BWindow* parent, BRect frame, Model& model)
|
||||
:
|
||||
BWindow(frame, B_TRANSLATE("Log in"),
|
||||
B_FLOATING_WINDOW_LOOK, B_FLOATING_SUBSET_WINDOW_FEEL,
|
||||
B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS
|
||||
| B_NOT_RESIZABLE | B_NOT_ZOOMABLE),
|
||||
fPreferredLanguage(model.PreferredLanguage()),
|
||||
fPreferredLanguageCode(model.Language().PreferredLanguage().Code()),
|
||||
fModel(model),
|
||||
fMode(NONE),
|
||||
fWorkerThread(-1)
|
||||
@@ -83,14 +72,15 @@ UserLoginWindow::UserLoginWindow(BWindow* parent, BRect frame, Model& model)
|
||||
fLanguageCodeField = new BMenuField("language",
|
||||
B_TRANSLATE("Preferred language:"), languagesMenu);
|
||||
|
||||
add_languages_to_menu(fModel.SupportedLanguages(), languagesMenu);
|
||||
LanguageMenuUtils::AddLanguagesToMenu(
|
||||
fModel.Language().SupportedLanguages(),
|
||||
languagesMenu);
|
||||
languagesMenu->SetTargetForItems(this);
|
||||
|
||||
BMenuItem* defaultItem = languagesMenu->ItemAt(
|
||||
fModel.SupportedLanguages().IndexOf(fPreferredLanguage));
|
||||
if (defaultItem != NULL)
|
||||
defaultItem->SetMarked(true);
|
||||
|
||||
printf("using preferred language code [%s]\n",
|
||||
fPreferredLanguageCode.String());
|
||||
LanguageMenuUtils::MarkLanguageInMenu(fPreferredLanguageCode,
|
||||
languagesMenu);
|
||||
|
||||
fEmailField = new BTextControl(B_TRANSLATE("Email address:"), "", NULL);
|
||||
fCaptchaView = new BitmapView("captcha view");
|
||||
@@ -218,7 +208,7 @@ UserLoginWindow::MessageReceived(BMessage* message)
|
||||
break;
|
||||
|
||||
case MSG_LANGUAGE_SELECTED:
|
||||
message->FindString("code", &fPreferredLanguage);
|
||||
message->FindString("code", &fPreferredLanguageCode);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -623,7 +613,7 @@ UserLoginWindow::_CreateAccountThread()
|
||||
BString email(fEmailField->Text());
|
||||
BString captchaToken(fCaptchaToken);
|
||||
BString captchaResponse(fCaptchaResultField->Text());
|
||||
BString languageCode(fPreferredLanguage);
|
||||
BString languageCode(fPreferredLanguageCode);
|
||||
|
||||
Unlock();
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2014, Stephan Aßmus <superstippi@gmx.de>.
|
||||
* Copyright 2019, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef USER_LOGIN_WINDOW_H
|
||||
@@ -84,7 +85,7 @@ private:
|
||||
|
||||
BString fCaptchaToken;
|
||||
BitmapRef fCaptchaImage;
|
||||
BString fPreferredLanguage;
|
||||
BString fPreferredLanguageCode;
|
||||
|
||||
Model& fModel;
|
||||
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <Application.h>
|
||||
#include <Messenger.h>
|
||||
|
||||
#include "HaikuDepotConstants.h"
|
||||
|
||||
|
||||
/*! This method can be called to pop up an error in the user interface;
|
||||
typically in a background thread.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright 2019, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#include "LanguageMenuUtils.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <Application.h>
|
||||
#include <MenuItem.h>
|
||||
#include <Messenger.h>
|
||||
|
||||
#include "HaikuDepotConstants.h"
|
||||
#include "Logger.h"
|
||||
|
||||
|
||||
/*! This method will add the supplied languages to the menu. It will
|
||||
add first the popular languages, followed by a separator and then
|
||||
other less popular languages.
|
||||
*/
|
||||
|
||||
/* static */ void
|
||||
LanguageMenuUtils::AddLanguagesToMenu(
|
||||
const LanguageList& languages, BMenu* menu)
|
||||
{
|
||||
if (languages.IsEmpty())
|
||||
printf("there are no languages defined\n");
|
||||
|
||||
int32 addedPopular = LanguageMenuUtils::_AddLanguagesToMenu(
|
||||
languages, menu, true);
|
||||
|
||||
if (addedPopular > 0)
|
||||
menu->AddSeparatorItem();
|
||||
|
||||
int32 addedNonPopular = LanguageMenuUtils::_AddLanguagesToMenu(
|
||||
languages, menu, false);
|
||||
|
||||
if (Logger::IsDebugEnabled()) {
|
||||
printf("did add %" B_PRId32 " popular languages and %" B_PRId32
|
||||
" non-popular languages to a menu\n", addedPopular,
|
||||
addedNonPopular);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* static */ void
|
||||
LanguageMenuUtils::MarkLanguageInMenu(
|
||||
const BString& languageCode, BMenu* menu) {
|
||||
if (menu->CountItems() == 0) {
|
||||
debugger("menu contains no items; not able to set the "
|
||||
"language");
|
||||
return;
|
||||
}
|
||||
|
||||
int32 index = LanguageMenuUtils::_IndexOfLanguageInMenu(
|
||||
languageCode, menu);
|
||||
|
||||
if (index == -1) {
|
||||
printf("unable to find the language [%s] in the menu\n",
|
||||
languageCode.String());
|
||||
menu->ItemAt(0)->SetMarked(true);
|
||||
}
|
||||
else
|
||||
menu->ItemAt(index)->SetMarked(true);
|
||||
}
|
||||
|
||||
|
||||
/* static */ void
|
||||
LanguageMenuUtils::_AddLanguageToMenu(
|
||||
const BString& code, const BString& name, BMenu* menu)
|
||||
{
|
||||
BMessage* message = new BMessage(MSG_LANGUAGE_SELECTED);
|
||||
message->AddString("code", code);
|
||||
BMenuItem* item = new BMenuItem(name, message);
|
||||
menu->AddItem(item);
|
||||
}
|
||||
|
||||
|
||||
/* static */ void
|
||||
LanguageMenuUtils::_AddLanguageToMenu(
|
||||
const LanguageRef& language, BMenu* menu)
|
||||
{
|
||||
BString name;
|
||||
if (language->GetName(name) != B_OK || name.IsEmpty())
|
||||
name.SetTo("???");
|
||||
LanguageMenuUtils::_AddLanguageToMenu(language->Code(), name, menu);
|
||||
}
|
||||
|
||||
|
||||
/* static */ int32
|
||||
LanguageMenuUtils::_AddLanguagesToMenu(const LanguageList& languages,
|
||||
BMenu* menu, bool isPopular)
|
||||
{
|
||||
int32 count = 0;
|
||||
|
||||
for (int32 i = 0; i < languages.CountItems(); i++) {
|
||||
const LanguageRef language = languages.ItemAtFast(i);
|
||||
|
||||
if (language->IsPopular() == isPopular) {
|
||||
LanguageMenuUtils::_AddLanguageToMenu(language, menu);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
/* static */ status_t
|
||||
LanguageMenuUtils::_GetLanguageAtIndexInMenu(BMenu* menu, int32 index,
|
||||
BString* result)
|
||||
{
|
||||
BMessage *itemMessage = menu->ItemAt(index)->Message();
|
||||
|
||||
if (itemMessage == NULL)
|
||||
return B_ERROR;
|
||||
|
||||
return itemMessage->FindString("code", result);
|
||||
}
|
||||
|
||||
|
||||
/* static */ int32
|
||||
LanguageMenuUtils::_IndexOfLanguageInMenu(
|
||||
const BString& languageCode, BMenu* menu)
|
||||
{
|
||||
BString itemLanguageCode;
|
||||
for (int32 i = 0; i < menu->CountItems(); i++) {
|
||||
if (_GetLanguageAtIndexInMenu(
|
||||
menu, i, &itemLanguageCode) == B_OK) {
|
||||
if (itemLanguageCode == languageCode) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2019, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef LANGUAGE_MENU_UTILS_H
|
||||
#define LANGUAGE_MENU_UTILS_H
|
||||
|
||||
|
||||
#include <Menu.h>
|
||||
|
||||
#include "Model.h"
|
||||
#include "PackageInfo.h"
|
||||
|
||||
|
||||
class LanguageMenuUtils {
|
||||
|
||||
public:
|
||||
static void AddLanguagesToMenu(
|
||||
const LanguageList& languages,
|
||||
BMenu* menu);
|
||||
static void MarkLanguageInMenu(
|
||||
const BString& languageCode,
|
||||
BMenu* menu);
|
||||
|
||||
private:
|
||||
static int32 _IndexOfLanguageInMenu(
|
||||
const BString& languageCode,
|
||||
BMenu* menu);
|
||||
static status_t _GetLanguageAtIndexInMenu(BMenu* menu,
|
||||
int32 index, BString* result);
|
||||
static int32 _AddLanguagesToMenu(
|
||||
const LanguageList& languages,
|
||||
BMenu* menu, bool isPopular);
|
||||
static void _AddLanguageToMenu(
|
||||
const LanguageRef& language,
|
||||
BMenu* menu);
|
||||
static void _AddLanguageToMenu(
|
||||
const BString& code,
|
||||
const BString& name, BMenu* menu);
|
||||
};
|
||||
|
||||
|
||||
#endif // LANGUAGE_MENU_UTILS_H
|
||||
Reference in New Issue
Block a user