Added languages module
This commit is contained in:
parent
c350dcb9c4
commit
4433ce2e6f
25 changed files with 1519 additions and 10 deletions
|
@ -58,6 +58,9 @@ public:
|
|||
MidiFirst = 600,
|
||||
MidiLast = 699,
|
||||
|
||||
LanguagesFirst = 700,
|
||||
LanguagesLast = 799,
|
||||
|
||||
NotationFirst = 1000,
|
||||
NotationLast = 1299
|
||||
};
|
||||
|
|
|
@ -91,6 +91,7 @@ if (BUILD_UI_MU4)
|
|||
mu4_midi
|
||||
userscores
|
||||
extensions
|
||||
languages
|
||||
importexport
|
||||
notation
|
||||
notation_scene
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "mu4/context/contextmodule.h"
|
||||
#include "mu4/userscores/userscoresmodule.h"
|
||||
#include "mu4/extensions/extensionsmodule.h"
|
||||
#include "mu4/languages/languagesmodule.h"
|
||||
#include "mu4/domain/notation/notationdomainmodule.h"
|
||||
#include "mu4/domain/importexport/importexportmodule.h"
|
||||
#include "mu4/scenes/common/commonscenemodule.h"
|
||||
|
@ -71,6 +72,7 @@ ModulesSetup::ModulesSetup()
|
|||
<< new mu::midi::MidiModule()
|
||||
<< new mu::userscores::UserScoresModule()
|
||||
<< new mu::extensions::ExtensionsModule()
|
||||
<< new mu::languages::LanguagesModule()
|
||||
<< new mu::domain::notation::NotationDomainModule()
|
||||
<< new mu::scene::common::CommonSceneModule()
|
||||
<< new mu::scene::notation::NotationSceneModule()
|
||||
|
|
|
@ -11,6 +11,7 @@ add_subdirectory(domain/importexport)
|
|||
# Home
|
||||
add_subdirectory(userscores)
|
||||
add_subdirectory(extensions)
|
||||
add_subdirectory(languages)
|
||||
|
||||
# Scenes common
|
||||
add_subdirectory(scenes/common)
|
||||
|
|
|
@ -4,6 +4,7 @@ import QtQuick.Layouts 1.3
|
|||
|
||||
import MuseScore.UiComponents 1.0
|
||||
import MuseScore.Extensions 1.0
|
||||
import MuseScore.Languages 1.0
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
|
@ -105,17 +106,17 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
|
||||
LanguagesModule {
|
||||
id: languagesComp
|
||||
color: ui.theme.backgroundColor
|
||||
StyledTextLabel {
|
||||
anchors.fill: parent
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: "Languages Module"
|
||||
|
||||
Connections {
|
||||
target: search
|
||||
|
||||
function onCurrentTextEdited(newTextValue) {
|
||||
languagesComp.search = newTextValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -180,7 +180,7 @@ Ret ExtensionsController::uninstall(const QString& extensionCode)
|
|||
}
|
||||
|
||||
m_extensionChanged.send(extensionHash[extensionCode]);
|
||||
|
||||
|
||||
return make_ret(Err::NoError);
|
||||
}
|
||||
|
||||
|
|
45
mu4/languages/CMakeLists.txt
Normal file
45
mu4/languages/CMakeLists.txt
Normal file
|
@ -0,0 +1,45 @@
|
|||
#=============================================================================
|
||||
# MuseScore
|
||||
# Music Composition & Notation
|
||||
#
|
||||
# Copyright (C) 2020 MuseScore BVBA and others
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
#=============================================================================
|
||||
|
||||
set(MODULE languages)
|
||||
|
||||
set(MODULE_QRC languages.qrc)
|
||||
|
||||
set(MODULE_QML_IMPORT ${CMAKE_CURRENT_LIST_DIR}/qml )
|
||||
|
||||
set(MODULE_SRC
|
||||
${CMAKE_CURRENT_LIST_DIR}/languagesmodule.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/languagesmodule.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/languagestypes.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/languageserrors.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/ilanguagesconfiguration.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/ilanguagescontroller.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/ilanguageunpacker.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/internal/languagesconfiguration.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/internal/languagesconfiguration.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/internal/languagescontroller.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/internal/languagescontroller.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/internal/languageunpacker.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/internal/languageunpacker.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/view/languagelistmodel.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/view/languagelistmodel.h
|
||||
)
|
||||
|
||||
include(${PROJECT_SOURCE_DIR}/build/module.cmake)
|
||||
|
51
mu4/languages/ilanguagesconfiguration.h
Normal file
51
mu4/languages/ilanguagesconfiguration.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
//=============================================================================
|
||||
// MuseScore
|
||||
// Music Composition & Notation
|
||||
//
|
||||
// Copyright (C) 2020 MuseScore BVBA and others
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//=============================================================================
|
||||
#ifndef MU_LANGUAGES_ILANGUAGESCONFIGURATION_H
|
||||
#define MU_LANGUAGES_ILANGUAGESCONFIGURATION_H
|
||||
|
||||
#include "retval.h"
|
||||
#include "modularity/imoduleexport.h"
|
||||
|
||||
#include "languagestypes.h"
|
||||
|
||||
namespace mu {
|
||||
namespace languages {
|
||||
class ILanguagesConfiguration : MODULE_EXPORT_INTERFACE
|
||||
{
|
||||
INTERFACE_ID(ILanguagesConfiguration)
|
||||
|
||||
public:
|
||||
virtual ~ILanguagesConfiguration() = default;
|
||||
|
||||
virtual QString currentLanguageCode() const = 0;
|
||||
virtual Ret setCurrentLanguageCode(const QString& languageCode) const = 0;
|
||||
|
||||
virtual QUrl languagesUpdateUrl() const = 0;
|
||||
virtual QUrl languagesFileServerUrl() const = 0;
|
||||
|
||||
virtual ValCh<LanguagesHash> languages() const = 0;
|
||||
virtual Ret setLanguages(const LanguagesHash& languages) const = 0;
|
||||
|
||||
virtual QString languagesSharePath() const = 0;
|
||||
virtual QString languagesDataPath() const = 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MU_LANGUAGES_ILANGUAGESCONFIGURATION_H
|
49
mu4/languages/ilanguagescontroller.h
Normal file
49
mu4/languages/ilanguagescontroller.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
//=============================================================================
|
||||
// MuseScore
|
||||
// Music Composition & Notation
|
||||
//
|
||||
// Copyright (C) 2020 MuseScore BVBA and others
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//=============================================================================
|
||||
#ifndef MU_LANGUAGES_ILANGUAGESCONTROLLER_H
|
||||
#define MU_LANGUAGES_ILANGUAGESCONTROLLER_H
|
||||
|
||||
#include "modularity/imoduleexport.h"
|
||||
#include "retval.h"
|
||||
|
||||
#include "languagestypes.h"
|
||||
|
||||
namespace mu {
|
||||
namespace languages {
|
||||
class ILanguagesController : MODULE_EXPORT_INTERFACE
|
||||
{
|
||||
INTERFACE_ID(ILanguagesController)
|
||||
|
||||
public:
|
||||
virtual ~ILanguagesController() = default;
|
||||
|
||||
virtual Ret refreshLanguages() = 0;
|
||||
|
||||
virtual ValCh<LanguagesHash> languages() = 0;
|
||||
virtual Ret install(const QString& languageCode) = 0;
|
||||
virtual Ret uninstall(const QString& languageCode) = 0;
|
||||
|
||||
virtual Ret setLanguage(const QString& languageCode) = 0;
|
||||
|
||||
virtual RetCh<Language> languageChanged() = 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MU_LANGUAGES_ILANGUAGESCONTROLLER_H
|
41
mu4/languages/ilanguageunpacker.h
Normal file
41
mu4/languages/ilanguageunpacker.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
//=============================================================================
|
||||
// MuseScore
|
||||
// Music Composition & Notation
|
||||
//
|
||||
// Copyright (C) 2020 MuseScore BVBA and others
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//=============================================================================
|
||||
#ifndef MU_LANGUAGES_ILANGUAGEUNPACKER_H
|
||||
#define MU_LANGUAGES_ILANGUAGEUNPACKER_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include "modularity/imoduleexport.h"
|
||||
#include "ret.h"
|
||||
|
||||
namespace mu {
|
||||
namespace languages {
|
||||
class ILanguageUnpacker : MODULE_EXPORT_INTERFACE
|
||||
{
|
||||
INTERFACE_ID(ILanguageUnpacker)
|
||||
|
||||
public:
|
||||
virtual ~ILanguageUnpacker() = default;
|
||||
|
||||
virtual Ret unpack(const QString& languageCode, const QString& source, const QString& destination) const = 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MU_LANGUAGES_ILANGUAGEUNPACKER_H
|
131
mu4/languages/internal/languagesconfiguration.cpp
Normal file
131
mu4/languages/internal/languagesconfiguration.cpp
Normal file
|
@ -0,0 +1,131 @@
|
|||
//=============================================================================
|
||||
// MuseScore
|
||||
// Music Composition & Notation
|
||||
//
|
||||
// Copyright (C) 2020 MuseScore BVBA and others
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//=============================================================================
|
||||
#include "languagesconfiguration.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QVariant>
|
||||
|
||||
#include "log.h"
|
||||
#include "settings.h"
|
||||
#include "languagestypes.h"
|
||||
#include "languageserrors.h"
|
||||
|
||||
using namespace mu;
|
||||
using namespace mu::framework;
|
||||
using namespace mu::languages;
|
||||
|
||||
static std::string module_name("languages");
|
||||
static const Settings::Key LANGUAGES_JSON(module_name, "languages/languagesJson");
|
||||
static const Settings::Key LANGUAGE("ui", "ui/application/language");
|
||||
|
||||
void LanguagesConfiguration::init()
|
||||
{
|
||||
settings()->addItem(LANGUAGE, Val("system"));
|
||||
settings()->valueChanged(LANGUAGES_JSON).onReceive(nullptr, [this](const Val& val) {
|
||||
LanguagesHash languagesHash = parseLanguagesConfig(io::pathToQString(val.toString()).toLocal8Bit());
|
||||
m_languagesHashChanged.send(languagesHash);
|
||||
});
|
||||
}
|
||||
|
||||
QString LanguagesConfiguration::currentLanguageCode() const
|
||||
{
|
||||
return io::pathToQString(settings()->value(LANGUAGE).toString());
|
||||
}
|
||||
|
||||
Ret LanguagesConfiguration::setCurrentLanguageCode(const QString& languageCode) const
|
||||
{
|
||||
Val value(languageCode.toStdString());
|
||||
settings()->setValue(LANGUAGE, value);
|
||||
return make_ret(Err::NoError);
|
||||
}
|
||||
|
||||
QUrl LanguagesConfiguration::languagesUpdateUrl() const
|
||||
{
|
||||
return QUrl("http://extensions.musescore.org/4.0/languages/details.json");
|
||||
}
|
||||
|
||||
QUrl LanguagesConfiguration::languagesFileServerUrl() const
|
||||
{
|
||||
return QUrl("http://extensions.musescore.org/4.0/languages/");
|
||||
}
|
||||
|
||||
ValCh<LanguagesHash> LanguagesConfiguration::languages() const
|
||||
{
|
||||
ValCh<LanguagesHash> result;
|
||||
result.val = parseLanguagesConfig(io::pathToQString(settings()->value(LANGUAGES_JSON).toString()).toLocal8Bit());
|
||||
result.ch = m_languagesHashChanged;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Ret LanguagesConfiguration::setLanguages(const LanguagesHash& languages) const
|
||||
{
|
||||
QJsonArray jsonArray;
|
||||
for (const Language& language: languages) {
|
||||
QJsonObject obj;
|
||||
obj[language.code] = language.toJson();
|
||||
|
||||
jsonArray << obj;
|
||||
}
|
||||
|
||||
QJsonDocument jsonDoc(jsonArray);
|
||||
|
||||
Val value(jsonDoc.toJson(QJsonDocument::Compact).constData());
|
||||
settings()->setValue(LANGUAGES_JSON, value);
|
||||
|
||||
return make_ret(Err::NoError);
|
||||
}
|
||||
|
||||
LanguagesHash LanguagesConfiguration::parseLanguagesConfig(const QByteArray& json) const
|
||||
{
|
||||
LanguagesHash result;
|
||||
|
||||
QJsonParseError err;
|
||||
QJsonDocument jsodDoc = QJsonDocument::fromJson(json, &err);
|
||||
if (err.error != QJsonParseError::NoError || !jsodDoc.isArray()) {
|
||||
return LanguagesHash();
|
||||
}
|
||||
|
||||
QVariantList languages = jsodDoc.array().toVariantList();
|
||||
for (const QVariant& languagesObj: languages) {
|
||||
QMap<QString, QVariant> value = languagesObj.toMap();
|
||||
QVariantMap lngMap = value.first().toMap();
|
||||
|
||||
Language language;
|
||||
language.code = value.keys().first();
|
||||
language.name = lngMap.value("name").toString();
|
||||
language.fileName = lngMap.value("fileName").toString();
|
||||
language.fileSize = lngMap.value("fileSize").toDouble();
|
||||
language.status = static_cast<LanguageStatus::Status>(lngMap.value("status").toInt());
|
||||
|
||||
result.insert(language.code, language);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QString LanguagesConfiguration::languagesSharePath() const
|
||||
{
|
||||
return io::pathToQString(globalConfiguration()->sharePath() + "/locale");
|
||||
}
|
||||
|
||||
QString LanguagesConfiguration::languagesDataPath() const
|
||||
{
|
||||
return io::pathToQString(globalConfiguration()->dataPath() + "/locale");
|
||||
}
|
57
mu4/languages/internal/languagesconfiguration.h
Normal file
57
mu4/languages/internal/languagesconfiguration.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
//=============================================================================
|
||||
// MuseScore
|
||||
// Music Composition & Notation
|
||||
//
|
||||
// Copyright (C) 2020 MuseScore BVBA and others
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//=============================================================================
|
||||
#ifndef MU_LANGUAGES_LANGUAGESCONFIGURATION_H
|
||||
#define MU_LANGUAGES_LANGUAGESCONFIGURATION_H
|
||||
|
||||
#include "modularity/ioc.h"
|
||||
#include "../ilanguagesconfiguration.h"
|
||||
#include "iglobalconfiguration.h"
|
||||
|
||||
namespace mu {
|
||||
namespace languages {
|
||||
class LanguagesConfiguration : public ILanguagesConfiguration
|
||||
{
|
||||
INJECT(languages, framework::IGlobalConfiguration, globalConfiguration)
|
||||
|
||||
public:
|
||||
LanguagesConfiguration() = default;
|
||||
|
||||
void init();
|
||||
|
||||
QString currentLanguageCode() const override;
|
||||
Ret setCurrentLanguageCode(const QString& languageCode) const override;
|
||||
|
||||
QUrl languagesUpdateUrl() const override;
|
||||
QUrl languagesFileServerUrl() const override;
|
||||
|
||||
ValCh<LanguagesHash> languages() const override;
|
||||
Ret setLanguages(const LanguagesHash& languages) const override;
|
||||
|
||||
QString languagesSharePath() const override;
|
||||
QString languagesDataPath() const override;
|
||||
|
||||
private:
|
||||
LanguagesHash parseLanguagesConfig(const QByteArray& json) const;
|
||||
|
||||
async::Channel<LanguagesHash> m_languagesHashChanged;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MU_LANGUAGES_LANGUAGESCONFIGURATION_H
|
343
mu4/languages/internal/languagescontroller.cpp
Normal file
343
mu4/languages/internal/languagescontroller.cpp
Normal file
|
@ -0,0 +1,343 @@
|
|||
//=============================================================================
|
||||
// MuseScore
|
||||
// Music Composition & Notation
|
||||
//
|
||||
// Copyright (C) 2020 MuseScore BVBA and others
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//=============================================================================
|
||||
#include "languagescontroller.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QTranslator>
|
||||
#include <QCoreApplication>
|
||||
|
||||
#include "log.h"
|
||||
#include "mscore/downloadUtils.h"
|
||||
#include "languageserrors.h"
|
||||
|
||||
using namespace mu;
|
||||
using namespace mu::languages;
|
||||
|
||||
static const QString DEFAULT_LANGUAGE("system");
|
||||
|
||||
void LanguagesController::init()
|
||||
{
|
||||
QString code = configuration()->currentLanguageCode();
|
||||
LOGD() << "==========" << code;
|
||||
loadLanguage(code);
|
||||
}
|
||||
|
||||
Ret LanguagesController::refreshLanguages()
|
||||
{
|
||||
Ms::DownloadUtils* js = new Ms::DownloadUtils();
|
||||
js->setTarget(configuration()->languagesUpdateUrl().toString());
|
||||
js->download();
|
||||
|
||||
QByteArray json = js->returnData();
|
||||
RetVal<LanguagesHash> actualLanguages = parseLanguagesConfig(json);
|
||||
|
||||
if (!actualLanguages.ret) {
|
||||
return actualLanguages.ret;
|
||||
}
|
||||
|
||||
LanguagesHash savedLanguages = configuration()->languages().val;
|
||||
|
||||
LanguagesHash resultLanguages = savedLanguages;
|
||||
|
||||
for (Language& language : actualLanguages.val) {
|
||||
if (resultLanguages.contains(language.code)) {
|
||||
Language& savedLanguage = resultLanguages[language.code];
|
||||
|
||||
if (!isLanguageExists(language.code)) {
|
||||
savedLanguage.status = LanguageStatus::Status::NoInstalled;
|
||||
continue;
|
||||
}
|
||||
|
||||
savedLanguage.status = LanguageStatus::Status::Installed;
|
||||
} else {
|
||||
language.status = LanguageStatus::Status::NoInstalled;
|
||||
resultLanguages.insert(language.code, language);
|
||||
}
|
||||
}
|
||||
|
||||
Ret ret = configuration()->setLanguages(resultLanguages);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ValCh<LanguagesHash> LanguagesController::languages()
|
||||
{
|
||||
ValCh<LanguagesHash> languagesHash = configuration()->languages();
|
||||
languagesHash.val = correctLanguagesStates(languagesHash.val).val;
|
||||
|
||||
return languagesHash;
|
||||
}
|
||||
|
||||
Ret LanguagesController::install(const QString& languageCode)
|
||||
{
|
||||
RetVal<QString> download = downloadLanguage(languageCode);
|
||||
if (!download.ret) {
|
||||
return download.ret;
|
||||
}
|
||||
|
||||
QString languageArchivePath = download.val;
|
||||
|
||||
QDir languagesShareDir(configuration()->languagesSharePath());
|
||||
if (!languagesShareDir.exists()) {
|
||||
languagesShareDir.mkpath(languagesShareDir.absolutePath());
|
||||
}
|
||||
|
||||
Ret unpack = languageUnpacker()->unpack(languageCode, languageArchivePath, languagesShareDir.absolutePath());
|
||||
if (!unpack) {
|
||||
LOGE() << "Error unpack" << unpack.code();
|
||||
return unpack;
|
||||
}
|
||||
|
||||
QFile languageArchive(languageArchivePath);
|
||||
languageArchive.remove();
|
||||
|
||||
LanguagesHash languageHash = this->languages().val;
|
||||
|
||||
languageHash[languageCode].status = LanguageStatus::Status::Installed;
|
||||
|
||||
Ret ret = configuration()->setLanguages(languageHash);
|
||||
if (!ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
m_languageChanged.send(languageHash[languageCode]);
|
||||
|
||||
return make_ret(Err::NoError);
|
||||
}
|
||||
|
||||
Ret LanguagesController::uninstall(const QString& languageCode)
|
||||
{
|
||||
LanguagesHash languagesHash = languages().val;
|
||||
|
||||
if (!languagesHash.contains(languageCode)) {
|
||||
return make_ret(Err::ErrorLanguageNotFound);
|
||||
}
|
||||
|
||||
Ret remove = removeLanguage(languageCode);
|
||||
if (!remove) {
|
||||
return remove;
|
||||
}
|
||||
|
||||
if (languagesHash[languageCode].isCurrent) {
|
||||
resetLanguageByDefault();
|
||||
}
|
||||
|
||||
languagesHash[languageCode].status = LanguageStatus::Status::NoInstalled;
|
||||
Ret ret = configuration()->setLanguages(languagesHash);
|
||||
if (!ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
m_languageChanged.send(languagesHash[languageCode]);
|
||||
|
||||
return make_ret(Err::NoError);
|
||||
}
|
||||
|
||||
Ret LanguagesController::setLanguage(const QString& languageCode)
|
||||
{
|
||||
LanguagesHash languageHash = this->languages().val;
|
||||
if (!languageHash.contains(languageCode)) {
|
||||
return make_ret(Err::ErrorLanguageNotFound);
|
||||
}
|
||||
|
||||
for (QTranslator* t: m_translatorList) {
|
||||
qApp->removeTranslator(t);
|
||||
delete t;
|
||||
}
|
||||
m_translatorList.clear();
|
||||
|
||||
Ret load = loadLanguage(languageCode);
|
||||
if (!load) {
|
||||
return load;
|
||||
}
|
||||
|
||||
QString previousLanguage = configuration()->currentLanguageCode();
|
||||
|
||||
Ret save = configuration()->setCurrentLanguageCode(languageCode);
|
||||
if (!save) {
|
||||
return save;
|
||||
}
|
||||
|
||||
languageHash[previousLanguage].isCurrent = false;
|
||||
m_languageChanged.send(languageHash[previousLanguage]);
|
||||
|
||||
languageHash[languageCode].isCurrent = true;
|
||||
m_languageChanged.send(languageHash[languageCode]);
|
||||
|
||||
return save;
|
||||
}
|
||||
|
||||
RetCh<Language> LanguagesController::languageChanged()
|
||||
{
|
||||
RetCh<Language> result;
|
||||
result.ret = make_ret(Err::NoError);
|
||||
result.ch = m_languageChanged;
|
||||
return result;
|
||||
}
|
||||
|
||||
RetVal<LanguagesHash> LanguagesController::parseLanguagesConfig(const QByteArray& json) const
|
||||
{
|
||||
RetVal<LanguagesHash> result;
|
||||
|
||||
QJsonParseError err;
|
||||
QJsonDocument jsodDoc = QJsonDocument::fromJson(json, &err);
|
||||
if (err.error != QJsonParseError::NoError || !jsodDoc.isObject()) {
|
||||
result.ret = make_ret(Err::ErrorParseConfig);
|
||||
return result;
|
||||
}
|
||||
|
||||
result.ret = make_ret(Err::NoError);
|
||||
QStringList languages = jsodDoc.object().keys();
|
||||
for (const QString& key : languages) {
|
||||
if (!jsodDoc.object().value(key).isObject()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QJsonObject value = jsodDoc.object().value(key).toObject();
|
||||
|
||||
Language language;
|
||||
language.code = key;
|
||||
language.name = value.value("name").toString();
|
||||
language.fileName = value.value("file_name").toString();
|
||||
language.fileSize = value.value("file_size").toDouble();
|
||||
language.status = LanguageStatus::Status::Undefined;
|
||||
|
||||
result.val.insert(key, language);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool LanguagesController::isLanguageExists(const QString& languageCode) const
|
||||
{
|
||||
QDir languagesDir(configuration()->languagesSharePath());
|
||||
QStringList files = languagesDir.entryList({ QString("*%1.qm").arg(languageCode) }, QDir::Files);
|
||||
return !files.empty();
|
||||
}
|
||||
|
||||
RetVal<LanguagesHash> LanguagesController::correctLanguagesStates(LanguagesHash& languages) const
|
||||
{
|
||||
RetVal<LanguagesHash> result;
|
||||
bool isNeedUpdate = false;
|
||||
|
||||
QString currentLanguage = configuration()->currentLanguageCode();
|
||||
|
||||
for (Language& language: languages) {
|
||||
if (language.status == LanguageStatus::Status::Installed && !isLanguageExists(language.code)) {
|
||||
language.status = LanguageStatus::Status::NoInstalled;
|
||||
isNeedUpdate = true;
|
||||
}
|
||||
|
||||
language.isCurrent = (language.code == currentLanguage);
|
||||
}
|
||||
|
||||
if (isNeedUpdate) {
|
||||
Ret update = configuration()->setLanguages(languages);
|
||||
if (!update) {
|
||||
result.ret = update;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
result.ret = make_ret(Err::NoError);
|
||||
result.val = languages;
|
||||
return result;
|
||||
}
|
||||
|
||||
RetVal<QString> LanguagesController::downloadLanguage(const QString& languageCode) const
|
||||
{
|
||||
RetVal<QString> result;
|
||||
|
||||
ValCh<LanguagesHash> languages = configuration()->languages();
|
||||
QString fileName = languages.val.value(languageCode).fileName;
|
||||
|
||||
QDir languagesDir(configuration()->languagesDataPath());
|
||||
if (!languagesDir.exists()) {
|
||||
languagesDir.mkpath(languagesDir.absolutePath());
|
||||
}
|
||||
|
||||
QString languageArchivePath = languagesDir.absolutePath() + "/" + fileName;
|
||||
|
||||
Ms::DownloadUtils* js = new Ms::DownloadUtils();
|
||||
js->setTarget(configuration()->languagesFileServerUrl().toString() + fileName);
|
||||
js->setLocalFile(languageArchivePath);
|
||||
js->download(true);
|
||||
|
||||
if (!js->saveFile()) {
|
||||
LOGE() << "Error save file";
|
||||
result.ret = make_ret(Err::ErrorDownloadLanguage);
|
||||
return result;
|
||||
}
|
||||
|
||||
result.ret = make_ret(Err::NoError);
|
||||
result.val = languageArchivePath;
|
||||
return result;
|
||||
}
|
||||
|
||||
Ret LanguagesController::removeLanguage(const QString& languageCode) const
|
||||
{
|
||||
QDir languageDir(configuration()->languagesSharePath());
|
||||
QStringList files = languageDir.entryList({ QString("*%1.qm").arg(languageCode) }, QDir::Files);
|
||||
for (const QString& fileName: files) {
|
||||
QString filePath(languageDir.absolutePath() + "/" + fileName);
|
||||
QFile file(filePath);
|
||||
if (!file.remove()) {
|
||||
LOGE() << "Error remove file" << filePath << file.errorString();
|
||||
return make_ret(Err::ErrorRemoveLanguageDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
return make_ret(Err::NoError);
|
||||
}
|
||||
|
||||
Ret LanguagesController::loadLanguage(const QString &languageCode)
|
||||
{
|
||||
QDir languageDir(configuration()->languagesSharePath());
|
||||
QStringList files = languageDir.entryList({ QString("*%1.qm").arg(languageCode) }, QDir::Files);
|
||||
|
||||
for (const QString& fileName: files) {
|
||||
QFileInfo file(fileName);
|
||||
QString filePath(languageDir.absolutePath() + "/" + file.baseName());
|
||||
|
||||
QTranslator* translator = new QTranslator;
|
||||
bool ok = translator->load(filePath);
|
||||
if (ok) {
|
||||
qApp->installTranslator(translator);
|
||||
m_translatorList.append(translator);
|
||||
} else {
|
||||
LOGE() << "Error load translate" << filePath;
|
||||
delete translator;
|
||||
}
|
||||
}
|
||||
|
||||
QLocale locale(languageCode);
|
||||
QLocale::setDefault(locale);
|
||||
qApp->setLayoutDirection(locale.textDirection());
|
||||
|
||||
return make_ret(Err::NoError);
|
||||
}
|
||||
|
||||
void LanguagesController::resetLanguageByDefault()
|
||||
{
|
||||
Ret load = loadLanguage(DEFAULT_LANGUAGE);
|
||||
if (!load) {
|
||||
return;
|
||||
}
|
||||
|
||||
configuration()->setCurrentLanguageCode(DEFAULT_LANGUAGE);
|
||||
}
|
72
mu4/languages/internal/languagescontroller.h
Normal file
72
mu4/languages/internal/languagescontroller.h
Normal file
|
@ -0,0 +1,72 @@
|
|||
//=============================================================================
|
||||
// MuseScore
|
||||
// Music Composition & Notation
|
||||
//
|
||||
// Copyright (C) 2020 MuseScore BVBA and others
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//=============================================================================
|
||||
#ifndef MU_LANGUAGES_LANGUAGESCONTROLLER_H
|
||||
#define MU_LANGUAGES_LANGUAGESCONTROLLER_H
|
||||
|
||||
#include "modularity/ioc.h"
|
||||
#include "../ilanguagescontroller.h"
|
||||
#include "../ilanguagesconfiguration.h"
|
||||
#include "../ilanguageunpacker.h"
|
||||
#include "iglobalconfiguration.h"
|
||||
|
||||
class QTranslator;
|
||||
|
||||
namespace mu {
|
||||
namespace languages {
|
||||
class LanguagesController : public ILanguagesController
|
||||
{
|
||||
INJECT(languages, ILanguagesConfiguration, configuration)
|
||||
INJECT(languages, ILanguageUnpacker, languageUnpacker)
|
||||
INJECT(languages, framework::IGlobalConfiguration, globalConfiguration)
|
||||
|
||||
public:
|
||||
LanguagesController() = default;
|
||||
|
||||
void init();
|
||||
|
||||
Ret refreshLanguages() override;
|
||||
ValCh<LanguagesHash> languages() override;
|
||||
Ret install(const QString& languageCode) override;
|
||||
Ret uninstall(const QString& languageCode) override;
|
||||
|
||||
Ret setLanguage(const QString &languageCode) override;
|
||||
|
||||
RetCh<Language> languageChanged() override;
|
||||
|
||||
private:
|
||||
RetVal<LanguagesHash> parseLanguagesConfig(const QByteArray& json) const;
|
||||
bool isLanguageExists(const QString& languageCode) const;
|
||||
|
||||
RetVal<LanguagesHash> correctLanguagesStates(LanguagesHash& languages) const;
|
||||
|
||||
RetVal<QString> downloadLanguage(const QString& languageCode) const;
|
||||
Ret removeLanguage(const QString& languageCode) const;
|
||||
|
||||
Ret loadLanguage(const QString& languageCode);
|
||||
|
||||
void resetLanguageByDefault();
|
||||
|
||||
private:
|
||||
async::Channel<Language> m_languageChanged;
|
||||
QList<QTranslator*> m_translatorList;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MU_LANGUAGES_LANGUAGESCONTROLLER_H
|
109
mu4/languages/internal/languageunpacker.cpp
Normal file
109
mu4/languages/internal/languageunpacker.cpp
Normal file
|
@ -0,0 +1,109 @@
|
|||
//=============================================================================
|
||||
// MuseScore
|
||||
// Music Composition & Notation
|
||||
//
|
||||
// Copyright (C) 2020 MuseScore BVBA and others
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//=============================================================================
|
||||
#include "languageunpacker.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QStorageInfo>
|
||||
|
||||
#include "thirdparty/qzip/qzipreader_p.h"
|
||||
#include "log.h"
|
||||
#include "../ilanguageunpacker.h"
|
||||
#include "languageserrors.h"
|
||||
|
||||
using namespace mu;
|
||||
using namespace mu::languages;
|
||||
|
||||
Ret LanguageUnpacker::unpack(const QString& languageCode, const QString& source, const QString& destination) const
|
||||
{
|
||||
Ret destinationWritable = checkDirectoryIsWritable(destination);
|
||||
if (!destinationWritable) {
|
||||
return destinationWritable;
|
||||
}
|
||||
|
||||
MQZipReader zipFile(source);
|
||||
|
||||
qint64 totalZipSize = 0;
|
||||
for (const MQZipReader::FileInfo& fileInfo : zipFile.fileInfoList()) {
|
||||
totalZipSize += fileInfo.size;
|
||||
}
|
||||
|
||||
Ret freeSpace = checkFreeSpace(destination, totalZipSize);
|
||||
if (!freeSpace) {
|
||||
return freeSpace;
|
||||
}
|
||||
|
||||
Ret remove = removePreviousVersion(destination, languageCode);
|
||||
if (!remove) {
|
||||
return remove;
|
||||
}
|
||||
|
||||
Ret unzipLanguage = unzip(&zipFile, destination);
|
||||
return unzipLanguage;
|
||||
}
|
||||
|
||||
Ret LanguageUnpacker::checkDirectoryIsWritable(const QString& directoryPath) const
|
||||
{
|
||||
QFileInfo destinationDirInfo(directoryPath);
|
||||
if (!destinationDirInfo.isWritable()) {
|
||||
return make_ret(Err::UnpackDestinationReadOnly);
|
||||
}
|
||||
|
||||
return make_ret(Err::NoError);
|
||||
}
|
||||
|
||||
Ret LanguageUnpacker::checkFreeSpace(const QString& directoryPath, quint64 neededSpace) const
|
||||
{
|
||||
QStorageInfo destinationStorageInfo(directoryPath);
|
||||
if (neededSpace > destinationStorageInfo.bytesAvailable()) {
|
||||
return make_ret(Err::UnpackNoFreeSpace);
|
||||
}
|
||||
|
||||
return make_ret(Err::NoError);
|
||||
}
|
||||
|
||||
Ret LanguageUnpacker::removePreviousVersion(const QString& path, const QString& languageCode) const
|
||||
{
|
||||
QDir languageDir(path);
|
||||
QStringList files = languageDir.entryList({ QString("*%1.qm").arg(languageCode) }, QDir::Files);
|
||||
for (const QString& fileName: files) {
|
||||
QString filePath(languageDir.absolutePath() + "/" + fileName);
|
||||
QFile file(filePath);
|
||||
if (!file.remove()) {
|
||||
LOGE() << "Error remove file" << filePath << file.errorString();
|
||||
return make_ret(Err::UnpackErrorRemovePreviousVersion);
|
||||
}
|
||||
}
|
||||
|
||||
return make_ret(Err::NoError);
|
||||
}
|
||||
|
||||
Ret LanguageUnpacker::unzip(const MQZipReader* zip, const QString& destination) const
|
||||
{
|
||||
QDir destinationDir(destination);
|
||||
if (!destinationDir.exists()) {
|
||||
destinationDir.mkpath(destinationDir.absolutePath());
|
||||
}
|
||||
|
||||
if (!zip->extractAll(destination)) {
|
||||
return make_ret(Err::UnpackError);
|
||||
}
|
||||
|
||||
return make_ret(Err::NoError);
|
||||
}
|
47
mu4/languages/internal/languageunpacker.h
Normal file
47
mu4/languages/internal/languageunpacker.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
//=============================================================================
|
||||
// MuseScore
|
||||
// Music Composition & Notation
|
||||
//
|
||||
// Copyright (C) 2020 MuseScore BVBA and others
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//=============================================================================
|
||||
#ifndef MU_LANGUAGES_LANGUAGEUNPACKER_H
|
||||
#define MU_LANGUAGES_LANGUAGEUNPACKER_H
|
||||
|
||||
#include "retval.h"
|
||||
|
||||
#include "../ilanguageunpacker.h"
|
||||
|
||||
class MQZipReader;
|
||||
|
||||
namespace mu {
|
||||
namespace languages {
|
||||
class LanguageUnpacker : public ILanguageUnpacker
|
||||
{
|
||||
public:
|
||||
LanguageUnpacker() = default;
|
||||
|
||||
Ret unpack(const QString& languageCode, const QString& source, const QString& destination) const override;
|
||||
|
||||
private:
|
||||
Ret checkDirectoryIsWritable(const QString& directoryPath) const;
|
||||
Ret checkFreeSpace(const QString& directoryPath, quint64 neededSpace) const;
|
||||
|
||||
Ret removePreviousVersion(const QString& path, const QString& languageCode) const;
|
||||
Ret unzip(const MQZipReader* zip, const QString& destination) const;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MU_LANGUAGES_LANGUAGEUNPACKER_H
|
6
mu4/languages/languages.qrc
Normal file
6
mu4/languages/languages.qrc
Normal file
|
@ -0,0 +1,6 @@
|
|||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>qml/MuseScore/Languages/qmldir</file>
|
||||
<file>qml/MuseScore/Languages/LanguagesModule.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
72
mu4/languages/languageserrors.h
Normal file
72
mu4/languages/languageserrors.h
Normal file
|
@ -0,0 +1,72 @@
|
|||
//=============================================================================
|
||||
// MuseScore
|
||||
// Music Composition & Notation
|
||||
//
|
||||
// Copyright (C) 2020 MuseScore BVBA and others
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//=============================================================================
|
||||
#ifndef MU_LANGUAGES_LANGUAGESERRORS_H
|
||||
#define MU_LANGUAGES_LANGUAGESERRORS_H
|
||||
|
||||
#include "ret.h"
|
||||
#include "translation.h"
|
||||
|
||||
namespace mu {
|
||||
namespace languages {
|
||||
enum class Err {
|
||||
Undefined = int(Ret::Code::Undefined),
|
||||
NoError = int(Ret::Code::Ok),
|
||||
UnknownError = int(Ret::Code::LanguagesFirst),
|
||||
|
||||
ErrorParseConfig,
|
||||
ErrorDownloadLanguage,
|
||||
ErrorLanguageNotFound,
|
||||
ErrorRemoveLanguageDirectory,
|
||||
|
||||
UnpackDestinationReadOnly,
|
||||
UnpackNoFreeSpace,
|
||||
UnpackErrorRemovePreviousVersion,
|
||||
UnpackError
|
||||
};
|
||||
|
||||
inline Ret make_ret(Err e)
|
||||
{
|
||||
switch (e) {
|
||||
case Err::Undefined: return Ret(static_cast<int>(Ret::Code::Undefined));
|
||||
case Err::NoError: return Ret(static_cast<int>(Ret::Code::Ok));
|
||||
case Err::UnknownError: return Ret(static_cast<int>(Ret::Code::UnknownError));
|
||||
case Err::ErrorParseConfig: return Ret(static_cast<int>(Err::ErrorParseConfig),
|
||||
trc("languages", "Error parsing response from server"));
|
||||
case Err::ErrorDownloadLanguage: return Ret(static_cast<int>(Err::ErrorDownloadLanguage),
|
||||
trc("languages", "Error download language"));
|
||||
case Err::ErrorLanguageNotFound: return Ret(static_cast<int>(Err::ErrorLanguageNotFound),
|
||||
trc("languages", "Language not found"));
|
||||
case Err::ErrorRemoveLanguageDirectory: return Ret(static_cast<int>(Err::ErrorRemoveLanguageDirectory),
|
||||
trc("languages", "Error remove language directory"));
|
||||
case Err::UnpackDestinationReadOnly: return Ret(static_cast<int>(Err::UnpackDestinationReadOnly),
|
||||
trc("languages", "Cannot import extension on read-only storage"));
|
||||
case Err::UnpackNoFreeSpace: return Ret(static_cast<int>(Err::UnpackNoFreeSpace),
|
||||
trc("languages", "Cannot import extension on full storage"));
|
||||
case Err::UnpackErrorRemovePreviousVersion: return Ret(static_cast<int>(Err::UnpackErrorRemovePreviousVersion),
|
||||
trc("languages", "Error removing previous version"));
|
||||
case Err::UnpackError: return Ret(static_cast<int>(Err::UnpackError),
|
||||
trc("languages", "Error unpacking extension"));
|
||||
}
|
||||
|
||||
return Ret(static_cast<int>(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MU_LANGUAGES_LANGUAGESERRORS_H
|
65
mu4/languages/languagesmodule.cpp
Normal file
65
mu4/languages/languagesmodule.cpp
Normal file
|
@ -0,0 +1,65 @@
|
|||
//=============================================================================
|
||||
// MuseScore
|
||||
// Music Composition & Notation
|
||||
//
|
||||
// Copyright (C) 2020 MuseScore BVBA and others
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//=============================================================================
|
||||
#include "languagesmodule.h"
|
||||
|
||||
#include <QQmlEngine>
|
||||
|
||||
#include "internal/languagesconfiguration.h"
|
||||
#include "internal/languagescontroller.h"
|
||||
#include "internal/languageunpacker.h"
|
||||
#include "view/languagelistmodel.h"
|
||||
|
||||
using namespace mu::languages;
|
||||
|
||||
static LanguagesConfiguration* m_languagesConfiguration = new LanguagesConfiguration();
|
||||
static LanguagesController* m_languagesController = new LanguagesController();
|
||||
|
||||
static void languages_init_qrc()
|
||||
{
|
||||
Q_INIT_RESOURCE(languages);
|
||||
}
|
||||
|
||||
std::string LanguagesModule::moduleName() const
|
||||
{
|
||||
return "languages";
|
||||
}
|
||||
|
||||
void LanguagesModule::registerExports()
|
||||
{
|
||||
framework::ioc()->registerExport<ILanguagesConfiguration>(moduleName(), m_languagesConfiguration);
|
||||
framework::ioc()->registerExport<ILanguagesController>(moduleName(), m_languagesController);
|
||||
framework::ioc()->registerExport<ILanguageUnpacker>(moduleName(), new LanguageUnpacker());
|
||||
}
|
||||
|
||||
void LanguagesModule::registerResources()
|
||||
{
|
||||
languages_init_qrc();
|
||||
}
|
||||
|
||||
void LanguagesModule::registerUiTypes()
|
||||
{
|
||||
qmlRegisterType<LanguageListModel>("MuseScore.Languages", 1, 0, "LanguageListModel");
|
||||
qmlRegisterUncreatableType<LanguageStatus>("MuseScore.Languages", 1, 0, "LanguageStatus", "Cannot create an LanguageStatus");
|
||||
}
|
||||
|
||||
void LanguagesModule::onInit()
|
||||
{
|
||||
m_languagesController->init();
|
||||
m_languagesConfiguration->init();
|
||||
}
|
39
mu4/languages/languagesmodule.h
Normal file
39
mu4/languages/languagesmodule.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
//=============================================================================
|
||||
// MuseScore
|
||||
// Music Composition & Notation
|
||||
//
|
||||
// Copyright (C) 2020 MuseScore BVBA and others
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//=============================================================================
|
||||
#ifndef MU_LANGUAGES_LANGUAGESMODULE_H
|
||||
#define MU_LANGUAGES_LANGUAGESMODULE_H
|
||||
|
||||
#include "modularity/imodulesetup.h"
|
||||
|
||||
namespace mu {
|
||||
namespace languages {
|
||||
class LanguagesModule : public framework::IModuleSetup
|
||||
{
|
||||
public:
|
||||
std::string moduleName() const override;
|
||||
|
||||
void registerExports() override;
|
||||
void registerResources() override;
|
||||
void registerUiTypes() override;
|
||||
void onInit() override;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MU_LANGUAGES_LANGUAGESMODULE_H
|
66
mu4/languages/languagestypes.h
Normal file
66
mu4/languages/languagestypes.h
Normal file
|
@ -0,0 +1,66 @@
|
|||
//=============================================================================
|
||||
// MuseScore
|
||||
// Music Composition & Notation
|
||||
//
|
||||
// Copyright (C) 2020 MuseScore BVBA and others
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//=============================================================================
|
||||
#ifndef MU_LANGUAGES_LANGUAGESTYPES_H
|
||||
#define MU_LANGUAGES_LANGUAGESTYPES_H
|
||||
|
||||
#include <QString>
|
||||
#include <QVersionNumber>
|
||||
#include <QJsonObject>
|
||||
#include <QObject>
|
||||
#include <QMetaObject>
|
||||
|
||||
namespace mu {
|
||||
namespace languages {
|
||||
class LanguageStatus
|
||||
{
|
||||
Q_GADGET
|
||||
public:
|
||||
enum class Status {
|
||||
Undefined = 0,
|
||||
Installed,
|
||||
NoInstalled
|
||||
};
|
||||
Q_ENUM(Status)
|
||||
};
|
||||
|
||||
struct Language
|
||||
{
|
||||
QString code;
|
||||
QString name;
|
||||
QString fileName;
|
||||
double fileSize = 0.0;
|
||||
bool isCurrent = false;
|
||||
LanguageStatus::Status status = LanguageStatus::Status::Undefined;
|
||||
|
||||
Language() = default;
|
||||
|
||||
QJsonObject toJson() const
|
||||
{
|
||||
return { { "name", name },
|
||||
{ "fileName", fileName },
|
||||
{ "fileSize", fileSize },
|
||||
{ "status", QString::number(static_cast<int>(status)) } };
|
||||
}
|
||||
};
|
||||
|
||||
using LanguagesHash = QHash<QString /*code*/, Language>;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MU_LANGUAGES_LANGUAGESTYPES_H
|
104
mu4/languages/qml/MuseScore/Languages/LanguagesModule.qml
Normal file
104
mu4/languages/qml/MuseScore/Languages/LanguagesModule.qml
Normal file
|
@ -0,0 +1,104 @@
|
|||
import QtQuick 2.7
|
||||
|
||||
import MuseScore.UiComponents 1.0
|
||||
import MuseScore.Languages 1.0
|
||||
|
||||
Rectangle {
|
||||
color: ui.theme.backgroundColor
|
||||
|
||||
Component.onCompleted: {
|
||||
languageListModel.load()
|
||||
}
|
||||
|
||||
LanguageListModel {
|
||||
id: languageListModel
|
||||
}
|
||||
|
||||
// TODO
|
||||
FlatButton {
|
||||
text: qsTrc("languages", "Update")
|
||||
|
||||
onClicked: {
|
||||
languageListModel.updateList()
|
||||
}
|
||||
}
|
||||
|
||||
GridView {
|
||||
id: view
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.topMargin: 50
|
||||
|
||||
model: languageListModel
|
||||
|
||||
clip: true
|
||||
|
||||
cellHeight: 150
|
||||
cellWidth: 200
|
||||
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
|
||||
delegate: Item {
|
||||
height: view.cellHeight
|
||||
width: view.cellWidth
|
||||
|
||||
Rectangle {
|
||||
|
||||
anchors.centerIn: parent
|
||||
|
||||
height: 130
|
||||
width: 180
|
||||
color: ui.theme.popupBackgroundColor
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
spacing: 10
|
||||
|
||||
StyledTextLabel {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
text: name
|
||||
}
|
||||
|
||||
Row {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
spacing: 4
|
||||
|
||||
FlatButton {
|
||||
text: qsTrc("languages", "Install")
|
||||
width: 60
|
||||
|
||||
visible: status === LanguageStatus.NoInstalled
|
||||
|
||||
onClicked: {
|
||||
languageListModel.install(index)
|
||||
}
|
||||
}
|
||||
FlatButton {
|
||||
text: qsTrc("languages", "Set as language")
|
||||
width: 60
|
||||
|
||||
visible: status === LanguageStatus.Installed && !isCurrent
|
||||
|
||||
onClicked: {
|
||||
languageListModel.setLanguage(index)
|
||||
}
|
||||
}
|
||||
FlatButton {
|
||||
text: qsTrc("languages", "Uninstall")
|
||||
width: 60
|
||||
|
||||
visible: status === LanguageStatus.Installed || status === LanguageStatus.NeedUpdate
|
||||
|
||||
onClicked: {
|
||||
languageListModel.uninstall(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
2
mu4/languages/qml/MuseScore/Languages/qmldir
Normal file
2
mu4/languages/qml/MuseScore/Languages/qmldir
Normal file
|
@ -0,0 +1,2 @@
|
|||
module MuseScore.Languages
|
||||
LanguagesModule 1.0 LanguagesModule.qml
|
138
mu4/languages/view/languagelistmodel.cpp
Normal file
138
mu4/languages/view/languagelistmodel.cpp
Normal file
|
@ -0,0 +1,138 @@
|
|||
//=============================================================================
|
||||
// MuseScore
|
||||
// Music Composition & Notation
|
||||
//
|
||||
// Copyright (C) 2020 MuseScore BVBA and others
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//=============================================================================
|
||||
#include "languagelistmodel.h"
|
||||
|
||||
#include "log.h"
|
||||
|
||||
using namespace mu::languages;
|
||||
|
||||
LanguageListModel::LanguageListModel(QObject* parent)
|
||||
: QAbstractListModel(parent)
|
||||
{
|
||||
m_roles.insert(rName, "name");
|
||||
m_roles.insert(rFileSize, "fileSize");
|
||||
m_roles.insert(rStatus, "status");
|
||||
m_roles.insert(rIsCurrent, "isCurrent");
|
||||
}
|
||||
|
||||
QVariant LanguageListModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
if (!index.isValid()) {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
Language item = m_list[index.row()];
|
||||
|
||||
switch (role) {
|
||||
case rName:
|
||||
return QVariant::fromValue(item.name);
|
||||
case rFileSize:
|
||||
return QVariant::fromValue(item.fileSize);
|
||||
case rStatus:
|
||||
return QVariant::fromValue(static_cast<int>(item.status));
|
||||
case rIsCurrent:
|
||||
return QVariant::fromValue(item.isCurrent);
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
int LanguageListModel::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
return m_list.count();
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> LanguageListModel::roleNames() const
|
||||
{
|
||||
return m_roles;
|
||||
}
|
||||
|
||||
void LanguageListModel::load()
|
||||
{
|
||||
m_list.clear();
|
||||
|
||||
ValCh<LanguagesHash> languages = languagesController()->languages();
|
||||
|
||||
beginResetModel();
|
||||
QList<Language> languageList = languages.val.values();
|
||||
std::sort(languageList.begin(), languageList.end(), [](const Language& l, const Language& r){
|
||||
return l.code < r.code;
|
||||
});
|
||||
|
||||
m_list = languageList;
|
||||
endResetModel();
|
||||
|
||||
RetCh<Language> languageChanged = languagesController()->languageChanged();
|
||||
languageChanged.ch.onReceive(this, [this](const Language& newLanguage) {
|
||||
for (int i = 0; i < m_list.count(); i++) {
|
||||
if (m_list[i].code == newLanguage.code) {
|
||||
m_list[i] = newLanguage;
|
||||
QModelIndex index = createIndex(i, 0);
|
||||
emit dataChanged(index, index);
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void LanguageListModel::updateList()
|
||||
{
|
||||
languagesController()->refreshLanguages();
|
||||
load();
|
||||
}
|
||||
|
||||
void LanguageListModel::install(int index)
|
||||
{
|
||||
if (index < 0 || index > m_list.count()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Ret ret = languagesController()->install(m_list.at(index).code);
|
||||
if (!ret) {
|
||||
LOGE() << "Error" << ret.code() << ret.text();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void LanguageListModel::uninstall(int index)
|
||||
{
|
||||
if (index < 0 || index > m_list.count()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Ret ret = languagesController()->uninstall(m_list.at(index).code);
|
||||
if (!ret) {
|
||||
LOGE() << "Error" << ret.code() << ret.text();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void LanguageListModel::setLanguage(int index)
|
||||
{
|
||||
if (index < 0 || index > m_list.count()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Ret ret = languagesController()->setLanguage(m_list.at(index).code);
|
||||
if (!ret) {
|
||||
LOGE() << "Error" << ret.code() << ret.text();
|
||||
return;
|
||||
}
|
||||
}
|
64
mu4/languages/view/languagelistmodel.h
Normal file
64
mu4/languages/view/languagelistmodel.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
//=============================================================================
|
||||
// MuseScore
|
||||
// Music Composition & Notation
|
||||
//
|
||||
// Copyright (C) 2020 MuseScore BVBA and others
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//=============================================================================
|
||||
#ifndef MU_LANGUAGES_LANGUAGELISTMODEL_H
|
||||
#define MU_LANGUAGES_LANGUAGELISTMODEL_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
|
||||
#include "modularity/ioc.h"
|
||||
#include "../ilanguagescontroller.h"
|
||||
#include "async/asyncable.h"
|
||||
|
||||
namespace mu {
|
||||
namespace languages {
|
||||
class LanguageListModel : public QAbstractListModel, async::Asyncable
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
INJECT(languages, ILanguagesController, languagesController)
|
||||
|
||||
public:
|
||||
LanguageListModel(QObject* parent = nullptr);
|
||||
|
||||
enum Roles {
|
||||
rName = Qt::UserRole + 1,
|
||||
rFileSize,
|
||||
rStatus,
|
||||
rIsCurrent
|
||||
};
|
||||
|
||||
QVariant data(const QModelIndex& index, int role) const override;
|
||||
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
QHash<int,QByteArray> roleNames() const override;
|
||||
|
||||
Q_INVOKABLE void load();
|
||||
Q_INVOKABLE void updateList();
|
||||
Q_INVOKABLE void install(int index);
|
||||
Q_INVOKABLE void uninstall(int index);
|
||||
Q_INVOKABLE void setLanguage(int index);
|
||||
|
||||
private:
|
||||
QHash<int, QByteArray> m_roles;
|
||||
QList<Language> m_list;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MU_LANGUAGES_LANGUAGELISTMODEL_H
|
Loading…
Reference in a new issue