diff --git a/CMakeLists.txt b/CMakeLists.txt index 48b4e1b..40cc03b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,8 @@ set(CMAKE_MODULE_PATH ${GPUI_SOURCE_DIR}/cmake) set(GPUI_DIR "${CMAKE_BINARY_DIR}") +include(TranslationUtils) + if(UNIX) include(GNUInstallDirs) else() diff --git a/cmake/TranslationUtils.cmake b/cmake/TranslationUtils.cmake new file mode 100644 index 0000000..507575c --- /dev/null +++ b/cmake/TranslationUtils.cmake @@ -0,0 +1,13 @@ +function(add_translation_resource out_file) + set(qm_files ${ARGN}) + set(resource ${CMAKE_CURRENT_SOURCE_DIR}/translations.qrc) + + file(WRITE ${resource} "\n \n") + foreach(LANG ${qm_files}) + get_filename_component(file_name ${LANG} NAME) + file(APPEND ${resource} " ${file_name}\n") + endforeach() + file(APPEND ${resource} " \n\n") + + set(${out_file} ${resource} PARENT_SCOPE) +endfunction() diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 058d5c0..56896ea 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -1,4 +1,4 @@ -find_package(Qt5 COMPONENTS Widgets Qml REQUIRED) +find_package(Qt5 COMPONENTS Widgets Qml LinguistTools REQUIRED) set(CMAKE_INCLUDE_CURRENT_DIR ON) @@ -45,6 +45,15 @@ set(MOC_HEADERS smbfilebrowser.h ) +set(TS_FILES + i18n/gui_en.ts + i18n/gui_ru.ts +) + +set_source_files_properties(${TS_FILES} PROPERTIES OUTPUT_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}) + +qt5_add_translation(QM_FILES ${TS_FILES}) + qt5_wrap_ui(UI_SOURCES ${UI_FORMS}) qt5_wrap_cpp(MOC_SOURCES ${MOC_HEADERS}) @@ -52,7 +61,11 @@ add_definitions( -DGPUI_GUI_LIBRARY ) -add_gpui_library(gpui-gui ${UI_SOURCES} ${MOC_SOURCES} ${SOURCES}) +add_translation_resource(RESOURCES_SRC ${QM_FILES}) + +qt5_add_resources(LIB_RESOURCES ${RESOURCES_SRC}) + +add_gpui_library(gpui-gui ${UI_SOURCES} ${MOC_SOURCES} ${SOURCES} ${LIB_RESOURCES}) target_link_libraries(gpui-gui Qt5::Widgets Qt5::Qml) target_link_libraries(gpui-gui gpui-model gpui-io) diff --git a/src/gui/commandlineparser.cpp b/src/gui/commandlineparser.cpp index 7020edb..56ea4db 100644 --- a/src/gui/commandlineparser.cpp +++ b/src/gui/commandlineparser.cpp @@ -54,8 +54,8 @@ CommandLineParser::~CommandLineParser() CommandLineParser::CommandLineParseResult CommandLineParser::parseCommandLine(CommandLineOptions *options, QString *errorMessage) { - const QCommandLineOption pathOption("p", "The full path of policy to edit.", "path"); - const QCommandLineOption bundleOption("b", "The full path of policy bundle to load.", "path"); + const QCommandLineOption pathOption("p", QObject::tr("The full path of policy to edit."), QObject::tr("path")); + const QCommandLineOption bundleOption("b", QObject::tr("The full path of policy bundle to load."), QObject::tr("path")); d->parser->setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions); d->parser->addOption(pathOption); diff --git a/src/gui/contentwidget.cpp b/src/gui/contentwidget.cpp index b5bedc7..169516c 100644 --- a/src/gui/contentwidget.cpp +++ b/src/gui/contentwidget.cpp @@ -144,6 +144,11 @@ void ContentWidget::setPolicyWidgetState(ContentWidget::PolicyWidgetState state) } } +void ContentWidget::onLanguageChaged() +{ + ui->retranslateUi(this); +} + void ContentWidget::onListItemClicked(const QModelIndex &index) { d->currentIndex = index; @@ -153,8 +158,8 @@ void ContentWidget::onListItemClicked(const QModelIndex &index) if (d->commandGroup.canExecute() && !d->cancelFlag) { QMessageBox::StandardButton reply; - reply = QMessageBox::question(this, "Save settings dialog", - "Policy settings were modified do you want to save them?", + reply = QMessageBox::question(this, QObject::tr("Save settings dialog"), + QObject::tr("Policy settings were modified do you want to save them?"), QMessageBox::Yes | QMessageBox::No); if (reply == QMessageBox::Yes) { diff --git a/src/gui/contentwidget.h b/src/gui/contentwidget.h index 0552d3e..54b9649 100644 --- a/src/gui/contentwidget.h +++ b/src/gui/contentwidget.h @@ -61,6 +61,8 @@ namespace gpui { void setPolicyWidgetState(PolicyWidgetState state); + void onLanguageChaged(); + signals: void modelItemSelected(const QModelIndex& index); void savePolicyChanges(); diff --git a/src/gui/i18n/gui_en.ts b/src/gui/i18n/gui_en.ts new file mode 100644 index 0000000..2ccd1c4 --- /dev/null +++ b/src/gui/i18n/gui_en.ts @@ -0,0 +1,356 @@ + + + + + ContentWidget + + + Form + Form + + + + Local Policies + Local Policies + + + + Policy State + Policy State + + + + Not Configured + Not Configured + + + + Enabled + Enabled + + + + Disabled + Disabled + + + + Help: + Help: + + + + Supported on: + Supported on: + + + + MainWindow + + + MainWindow + MainWindow + + + + &File + &File + + + + &Action + &Action + + + + &View + &View + + + + &Help + &Help + + + + toolBar + toolBar + + + + Go &Back + Go &Back + + + + Go Back + Go Back + + + + Alt+Left + Alt+Left + + + + Go &Forward + Go &Forward + + + + Go Forward + Go Forward + + + + Alt+Right + Alt+Right + + + + Go &Up + Go &Up + + + + Go Up + Go Up + + + + Alt+Up + Alt+Up + + + + &Reload + &Reload + + + + Reload + Reload + + + + + Ctrl+R + Ctrl+R + + + + &Small Icon View + &Small Icon View + + + + Small Icon View + Small Icon View + + + + &Large Icon View + &Large Icon View + + + + Large Icon View + Large Icon View + + + + &Compact List View + &Compact List View + + + + Compact List View + Compact List View + + + + &Options + &Options + + + + Options + Options + + + + &Exit + &Exit + + + + Exit + Exit + + + + &Add/Remove Columns + &Add/Remove Columns + + + + Add/Remove Columns + Add/Remove Columns + + + + Ctrl+A + Ctrl+A + + + + &Detailed List View + &Detailed List View + + + + Detailed List View + Detailed List View + + + + &Select DC + &Select DC + + + + Select Domain Controller + Select Domain Controller + + + + &Customize + &Customize + + + + Customize + Customize + + + + Open &Policy Directory + Open &Policy Directory + + + + Ctrl+O + Ctrl+O + + + + Open &User Registry Source + Open &User Registry Source + + + + &Save Registry Source + &Save Registry Source + + + + Ctrl+S + Ctrl+S + + + + Open &Machine Registry Source + Open &Machine Registry Source + + + + &Language + &Language + + + + QObject + + + The full path of policy to edit. + The full path of policy to edit. + + + + + path + path + + + + The full path of policy bundle to load. + The full path of policy bundle to load. + + + + Save settings dialog + Save settings dialog + + + + Policy settings were modified do you want to save them? + Policy settings were modified do you want to save them? + + + + Description: + Description: + + + + Options: + Options: + + + + Machine + Machine + + + + Machine level policies + Machine level policies + + + + User + User + + + + User level policies + User level policies + + + + SmbFileBrowser + + + Dialog + Dialog + + + + back + back + + + + Up + Up + + + + gpui::MainWindow + + + Open Directory + Open Directory + + + diff --git a/src/gui/i18n/gui_ru.ts b/src/gui/i18n/gui_ru.ts new file mode 100644 index 0000000..7c524a5 --- /dev/null +++ b/src/gui/i18n/gui_ru.ts @@ -0,0 +1,356 @@ + + + + + ContentWidget + + + Form + Форма + + + + Local Policies + Локальные политики + + + + Policy State + Состояние политики + + + + Not Configured + Не настроено + + + + Enabled + Включено + + + + Disabled + Выключено + + + + Help: + Помощь: + + + + Supported on: + Поддерживается на: + + + + MainWindow + + + MainWindow + Главное окно + + + + &File + &Файл + + + + &Action + &Действие + + + + &View + &Вид + + + + &Help + &Помощь + + + + toolBar + панель инструментов + + + + Go &Back + &Назад + + + + Go Back + Назад + + + + Alt+Left + Alt+Left + + + + Go &Forward + &Вперёд + + + + Go Forward + Вперёд + + + + Alt+Right + Alt+Right + + + + Go &Up + &Вверх + + + + Go Up + Вверх + + + + Alt+Up + Alt+Up + + + + &Reload + &Обновить + + + + Reload + Обновить + + + + + Ctrl+R + Ctrl+R + + + + &Small Icon View + &Маленькие иконки + + + + Small Icon View + Маленькие иконки + + + + &Large Icon View + &Большие иконки + + + + Large Icon View + Большие иконки + + + + &Compact List View + &Компактный список + + + + Compact List View + Компактный список + + + + &Options + &Настройки + + + + Options + Настройки + + + + &Exit + &Выход + + + + Exit + Выход + + + + &Add/Remove Columns + &Добавить/Удалить колонки + + + + Add/Remove Columns + Добавить/Удалить колонки + + + + Ctrl+A + Ctrl+A + + + + &Detailed List View + &Детальный список + + + + Detailed List View + Детальный список + + + + &Select DC + &Выберите контролер домена + + + + Select Domain Controller + Выберите контролер домена + + + + &Customize + &Настроить + + + + Customize + Настроить + + + + Open &Policy Directory + &Открыть папку с ADMX файлами + + + + Ctrl+O + Ctrl+O + + + + Open &User Registry Source + &Открыть пользовательский POL файл + + + + &Save Registry Source + &Сохранить настройки + + + + Ctrl+S + Ctrl+S + + + + Open &Machine Registry Source + &Открыть машинный POL файл + + + + &Language + &Язык + + + + QObject + + + The full path of policy to edit. + Полный путь для редактируемой политики. + + + + + path + путь + + + + The full path of policy bundle to load. + Полный путь к набору ADMX файлов. + + + + Save settings dialog + Состояние настроек + + + + Policy settings were modified do you want to save them? + Настройки политки были изменены, хотите сохранить их? + + + + Description: + Описание: + + + + Options: + Опции: + + + + Machine + Компьютер + + + + Machine level policies + Политики настройки компьютера + + + + User + Пользователь + + + + User level policies + Политики настройки пользователей + + + + SmbFileBrowser + + + Dialog + Диалог + + + + back + Назад + + + + Up + Вверх + + + + gpui::MainWindow + + + Open Directory + Открыть папку + + + diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index 8671d95..eb055fe 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -41,6 +41,11 @@ #include +void registerResources() +{ + Q_INIT_RESOURCE(translations); +} + namespace gpui { class MainWindowPrivate { @@ -59,6 +64,11 @@ public: std::unique_ptr sortModel = nullptr; + std::vector> translators; + QString localeName; + + CommandLineOptions options; + MainWindowPrivate() : userRegistry(new model::registry::Registry()) , userRegistrySource(new model::registry::PolRegistrySource(userRegistry)) @@ -129,8 +139,21 @@ MainWindow::MainWindow(CommandLineOptions &options, QWidget *parent) , d(new MainWindowPrivate()) , ui(new Ui::MainWindow()) { + registerResources(); + + QLocale locale; + std::unique_ptr qtTranslator = std::make_unique(); + qtTranslator->load(locale, "gui", "_", ":/"); + QCoreApplication::installTranslator(qtTranslator.get()); + d->translators.push_back(std::move(qtTranslator)); + d->localeName = locale.name().replace("_", "-"); + + d->options = options; + ui->setupUi(this); + createLanguageMenu(); + d->contentWidget = new ContentWidget(this); d->contentWidget->setMachineRegistrySource(d->machineRegistrySource.get()); d->contentWidget->setUserRegistrySource(d->userRegistrySource.get()); @@ -146,15 +169,17 @@ MainWindow::MainWindow(CommandLineOptions &options, QWidget *parent) connect(ui->actionSaveRegistrySource, &QAction::triggered, this, &MainWindow::onRegistrySourceSave); connect(ui->treeView, &QTreeView::clicked, d->contentWidget, &ContentWidget::modelItemSelected); - if (!options.policyBundle.isEmpty()) + if (d->options.policyBundle.isEmpty()) { - loadPolicyBundleFolder(options.policyBundle); + d->options.policyBundle = "/usr/share/PolicyDefinitions"; } - if (!options.path.isEmpty()) + loadPolicyBundleFolder(d->options.policyBundle, d->localeName); + + if (!d->options.path.isEmpty()) { - d->userRegistryPath = options.path + "/User/Registry.pol"; - d->machineRegistryPath = options.path + "/Machine/Registry.pol"; + d->userRegistryPath = d->options.path + "/User/Registry.pol"; + d->machineRegistryPath = d->options.path + "/Machine/Registry.pol"; onPolFileOpen(d->userRegistryPath, d->userRegistry, d->userRegistrySource, [&](model::registry::AbstractRegistrySource* source) @@ -186,10 +211,10 @@ void MainWindow::closeEvent(QCloseEvent *event) QMainWindow::closeEvent(event); } -void gpui::MainWindow::loadPolicyBundleFolder(const QString& path) +void gpui::MainWindow::loadPolicyBundleFolder(const QString& path, const QString &locale) { auto bundle = std::make_unique(); - d->model = bundle->loadFolder(path.toStdString(), "ru-ru"); + d->model = bundle->loadFolder(path.toStdString(), locale.toStdString()); d->sortModel = std::make_unique(); d->sortModel->setSourceModel(d->model.get()); @@ -205,13 +230,13 @@ void gpui::MainWindow::loadPolicyBundleFolder(const QString& path) void MainWindow::onDirectoryOpen() { - QString directory = QFileDialog::getExistingDirectory( - this, - tr("Open Directory"), - QDir::homePath(), - QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); + d->options.policyBundle = QFileDialog::getExistingDirectory( + this, + tr("Open Directory"), + QDir::homePath(), + QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); - loadPolicyBundleFolder(directory); + loadPolicyBundleFolder(d->options.policyBundle, d->localeName); } void MainWindow::onUserRegistrySourceOpen() @@ -260,6 +285,34 @@ void MainWindow::on_actionExit_triggered() QApplication::quit(); } +void MainWindow::onLanguageChanged(QAction *action) +{ + for (const auto& translator : d->translators) + { + qApp->removeTranslator(translator.get()); + } + d->translators.clear(); + + QString language = action->data().toString(); + + std::unique_ptr qtTranslator = std::make_unique(); + bool loadResult = qtTranslator->load("gui_" + language + ".qm", ":/"); + QCoreApplication::installTranslator(qtTranslator.get()); + d->translators.push_back(std::move(qtTranslator)); + qWarning() << "Load language " << language << loadResult; + + QLocale locale(language); + + d->localeName = locale.name().replace("_", "-"); + + loadPolicyBundleFolder(d->options.policyBundle, d->localeName); + + d->contentWidget->onLanguageChaged(); + ui->retranslateUi(this); + + ui->treeView->selectionModel()->clearSelection(); +} + void MainWindow::onRegistrySourceOpen(std::shared_ptr& registry, std::unique_ptr& source, std::function callback) @@ -325,4 +378,39 @@ void MainWindow::onPolFileOpen(const QString &path, } } +void MainWindow::createLanguageMenu() +{ + QActionGroup* langGroup = new QActionGroup(this); + langGroup->setExclusive(true); + + connect(langGroup, &QActionGroup::triggered, this, &MainWindow::onLanguageChanged); + + QString defaultLocale = QLocale::system().name().left(QLocale::system().name().lastIndexOf('_')); + QDir dir(":/"); + QStringList fileNames = dir.entryList(QStringList("gui_*.qm")); + + QMenu* menu = new QMenu(this); + ui->actionLanguage->setMenu(menu); + + for (QString locale : fileNames) + { + locale.truncate(locale.lastIndexOf('.')); + locale.remove(0, locale.lastIndexOf('_') + 1); + + QString language = QLocale::languageToString(QLocale(locale).language()); + + QAction *action = new QAction(language, this); + action->setCheckable(true); + action->setData(locale); + + menu->addAction(action); + langGroup->addAction(action); + + if (defaultLocale == locale) + { + action->setChecked(true); + } + } +} + } diff --git a/src/gui/mainwindow.h b/src/gui/mainwindow.h index 86bb88b..1380428 100644 --- a/src/gui/mainwindow.h +++ b/src/gui/mainwindow.h @@ -66,6 +66,8 @@ namespace gpui { void on_actionExit_triggered(); + void onLanguageChanged(QAction *action); + private: void onRegistrySourceOpen(std::shared_ptr& registry, std::unique_ptr& source, @@ -76,7 +78,9 @@ namespace gpui { std::unique_ptr& source, std::function callback); - void loadPolicyBundleFolder(const QString& path); + void loadPolicyBundleFolder(const QString& path, const QString& locale); + + void createLanguageMenu(); }; } diff --git a/src/gui/mainwindow.ui b/src/gui/mainwindow.ui index ebcb801..329c22a 100644 --- a/src/gui/mainwindow.ui +++ b/src/gui/mainwindow.ui @@ -100,6 +100,7 @@ + @@ -311,6 +312,11 @@ Open &Machine Registry Source + + + &Language + + diff --git a/src/gui/presentationbuilder.cpp b/src/gui/presentationbuilder.cpp index db9a67e..8ab14ca 100644 --- a/src/gui/presentationbuilder.cpp +++ b/src/gui/presentationbuilder.cpp @@ -87,8 +87,8 @@ namespace gui QHBoxLayout* createCaptions() { QHBoxLayout* horizontalLayout = new QHBoxLayout(); - QLabel* descriptionLabel = new QLabel("Description:"); - QLabel* optionLabel = new QLabel("Options:"); + QLabel* descriptionLabel = new QLabel(QObject::tr("Description:")); + QLabel* optionLabel = new QLabel(QObject::tr("Options:")); horizontalLayout->addWidget(descriptionLabel); horizontalLayout->addWidget(optionLabel); return horizontalLayout; @@ -200,9 +200,26 @@ namespace gui virtual void visit(ListBox &widget) const override { - QListWidget* listWidget = new QListWidget(); + QListWidget* listBox = new QListWidget(); - QLayoutItem* container = createAndAttachLabel(listWidget, QString::fromStdString(widget.label)); + QLayoutItem* container = createAndAttachLabel(listBox, QString::fromStdString(widget.label)); + + if (m_policy && m_source) + { + std::pair keyValuePair = findKeyAndValueName(); + + if (m_source->isValuePresent(keyValuePair.first, keyValuePair.second)) + { + QString items = m_source->getValue(keyValuePair.first, keyValuePair.second).value(); + listBox->addItems(items.split('\0', QString::SplitBehavior::SkipEmptyParts)); + } + + listBox->connect(listBox, &QListWidget::itemChanged, [=](QListWidgetItem *item) { + createCommand([=](){ + QString items = m_source->getValue(keyValuePair.first, keyValuePair.second).value(); + }); + }); + } addToLayout(container); } diff --git a/src/gui/translations.qrc b/src/gui/translations.qrc new file mode 100644 index 0000000..364ad03 --- /dev/null +++ b/src/gui/translations.qrc @@ -0,0 +1,6 @@ + + + gui_en.qm + gui_ru.qm + + diff --git a/src/model/bundle/policybundle.cpp b/src/model/bundle/policybundle.cpp index 4dd5a08..4db4243 100644 --- a/src/model/bundle/policybundle.cpp +++ b/src/model/bundle/policybundle.cpp @@ -88,8 +88,8 @@ std::unique_ptr PolicyBundle::loadFolder(const std::string& QStandardItem* rootItem = d->treeModel->invisibleRootItem(); - d->rootMachineItem = createItem("Machine", "folder", "Machine level policies"); - d->rootUserItem = createItem("User", "folder", "User level policies"); + d->rootMachineItem = createItem(QObject::tr("Machine"), "folder", QObject::tr("Machine level policies")); + d->rootUserItem = createItem(QObject::tr("User"), "folder", QObject::tr("User level policies")); rootItem->appendRow(d->rootMachineItem); rootItem->appendRow(d->rootUserItem);