From 1b4fd9abe37f207831dcd9b95d10529e936329ca Mon Sep 17 00:00:00 2001 From: Sven Eberhardt Date: Tue, 9 May 2017 22:43:56 -0400 Subject: [PATCH] Editor: Add translation overview table (Tools menu) --- CMakeLists.txt | 3 + planet/System.ocg/LanguageDE.txt | 3 + planet/System.ocg/LanguageUS.txt | 3 + src/C4Include.h | 1 + src/editor/C4ConsoleQt.cpp | 3 + src/editor/C4ConsoleQtLocalizeOverview.cpp | 208 +++++++++++++++++++++ src/editor/C4ConsoleQtLocalizeOverview.h | 62 ++++++ src/editor/C4ConsoleQtLocalizeOverview.ui | 146 +++++++++++++++ src/editor/C4ConsoleQtLocalizeString.cpp | 2 +- src/editor/C4ConsoleQtMainWindow.ui | 29 +++ src/editor/C4ConsoleQtState.cpp | 20 ++ src/editor/C4ConsoleQtState.h | 2 + 12 files changed, 481 insertions(+), 1 deletion(-) create mode 100644 src/editor/C4ConsoleQtLocalizeOverview.cpp create mode 100644 src/editor/C4ConsoleQtLocalizeOverview.h create mode 100644 src/editor/C4ConsoleQtLocalizeOverview.ui diff --git a/CMakeLists.txt b/CMakeLists.txt index 96ed91d0c..b236f7031 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -765,6 +765,9 @@ if(WITH_QT_EDITOR) src/editor/C4ConsoleQtLocalizeString.cpp src/editor/C4ConsoleQtLocalizeString.h src/editor/C4ConsoleQtLocalizeString.ui + src/editor/C4ConsoleQtLocalizeOverview.cpp + src/editor/C4ConsoleQtLocalizeOverview.h + src/editor/C4ConsoleQtLocalizeOverview.ui src/editor/C4ConsoleQtMainWindow.ui src/editor/resource.qrc ${qt_editor_resources} diff --git a/planet/System.ocg/LanguageDE.txt b/planet/System.ocg/LanguageDE.txt index 8a7b587fe..8e802e580 100644 --- a/planet/System.ocg/LanguageDE.txt +++ b/planet/System.ocg/LanguageDE.txt @@ -84,9 +84,11 @@ IDS_CNS_NOTHING=Nichts IDS_CNS_OBJECT=Objekt IDS_CNS_OBJECTS=Objektliste IDS_CNS_OWNER=Besitzer: %s +IDS_CNS_PATH=Pfad IDS_CNS_PLRQUIT=%s löschen IDS_CNS_PLRQUITNET=%s (%s) löschen IDS_CNS_PROPERTIES=Eigenschaften +IDS_CNS_REFRESH=Aktualisieren IDS_CNS_REMOVE=Entfernen IDS_CNS_SAVEASERROR=Fehler beim Speichern des Szenarios nach %s. IDS_CNS_RECURSIVESAVEASERROR=Speichern in das existierende Szenario ist nicht möglich. Bitte neuen Pfad wählen. @@ -573,6 +575,7 @@ IDS_MNU_SWITCHRESOLUTION=Bildschirmauflösung ändern IDS_MNU_SWITCHRESOLUTION_LIKEIT=Neue Auflösung gewählt. Zufrieden? IDS_MNU_SWITCHRESOLUTION_UNDO=Alte Einstellung wird in %d Sekunden wiederhergestellt... IDS_MNU_TOOLS=Werkzeuge +IDS_MNU_TRANSLATIONTABLE=Übersetzungstabelle IDS_MNU_UPPERBOARD=Titelleiste IDS_MNU_VIEWPORT=Sichtfenster IDS_MNU_WINDOWS=Fenster diff --git a/planet/System.ocg/LanguageUS.txt b/planet/System.ocg/LanguageUS.txt index 8f6f09c96..289d53b05 100644 --- a/planet/System.ocg/LanguageUS.txt +++ b/planet/System.ocg/LanguageUS.txt @@ -84,9 +84,11 @@ IDS_CNS_NOTHING=Nothing IDS_CNS_OBJECT=Object IDS_CNS_OBJECTS=Object list IDS_CNS_OWNER=Owner: %s +IDS_CNS_PATH=Path IDS_CNS_PLRQUIT=Remove %s IDS_CNS_PLRQUITNET=Remove %s (%s) IDS_CNS_PROPERTIES=Properties +IDS_CNS_REFRESH=Refresh IDS_CNS_REMOVE=Remove IDS_CNS_SAVEASERROR=Error while saving the scenario to %s. IDS_CNS_RECURSIVESAVEASERROR=Cannot save into the existing scenario. Please choose another path. @@ -573,6 +575,7 @@ IDS_MNU_SWITCHRESOLUTION=Switch resolution IDS_MNU_SWITCHRESOLUTION_LIKEIT=This is your new resolution. Do you like it? IDS_MNU_SWITCHRESOLUTION_UNDO=Original resolution will be restored in %d seconds... IDS_MNU_TOOLS=Tools +IDS_MNU_TRANSLATIONTABLE=Translation table IDS_MNU_UPPERBOARD=Title board IDS_MNU_VIEWPORT=Viewport IDS_MNU_WINDOWS=Windows diff --git a/src/C4Include.h b/src/C4Include.h index 838f4dedf..a727bdcb4 100644 --- a/src/C4Include.h +++ b/src/C4Include.h @@ -61,6 +61,7 @@ constexpr bool SOLIDMASK_DEBUG = false; #include #include #include +#include #include #include "lib/Standard.h" diff --git a/src/editor/C4ConsoleQt.cpp b/src/editor/C4ConsoleQt.cpp index b259c3d68..d8cd0699b 100644 --- a/src/editor/C4ConsoleQt.cpp +++ b/src/editor/C4ConsoleQt.cpp @@ -25,6 +25,7 @@ #include "editor/C4ConsoleQtObjectListViewer.h" #include "editor/C4ConsoleQtPropListViewer.h" #include "editor/C4ConsoleQtShapes.h" +#include "editor/C4ConsoleQtLocalizeOverview.h" #include "editor/C4Console.h" #include "editor/C4ConsoleGUI.h" #include "script/C4AulExec.h" @@ -238,6 +239,8 @@ void C4ConsoleGUI::DoEnableControls(bool fEnable) if (!Active) return; state->SetEnabled(fEnable); state->SetLandscapeMode(::Landscape.GetMode(), ::Game.C4S.Landscape.FlatChunkShapes); // initial setting + // If disabling controls, also stop translation editing + if (!fEnable) state->translation_overview_dialogue.reset(); } bool C4ConsoleGUI::DoUpdateHaltCtrls(bool fHalt) diff --git a/src/editor/C4ConsoleQtLocalizeOverview.cpp b/src/editor/C4ConsoleQtLocalizeOverview.cpp new file mode 100644 index 000000000..7af546250 --- /dev/null +++ b/src/editor/C4ConsoleQtLocalizeOverview.cpp @@ -0,0 +1,208 @@ +/* +* OpenClonk, http://www.openclonk.org +* +* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/ +* Copyright (c) 2013, The OpenClonk Team and contributors +* +* Distributed under the terms of the ISC license; see accompanying file +* "COPYING" for details. +* +* "Clonk" is a registered trademark of Matthes Bender, used with permission. +* See accompanying file "TRADEMARK" for details. +* +* To redistribute this file separately, substitute the full license texts +* for the above references. +*/ + +/* String localization editors */ + +#include "C4Include.h" +#include "script/C4Value.h" +#include "config/C4Config.h" +#include "editor/C4ConsoleQtLocalizeOverview.h" +#include "c4group/C4Language.h" + + +/* Single string editor */ + +C4ConsoleQtLocalizeOverviewDlg::C4ConsoleQtLocalizeOverviewDlg(class QMainWindow *parent_window) + : QDialog(parent_window, Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowCloseButtonHint) +{ + ui.setupUi(this); + // Size + adjustSize(); + setMinimumSize(size()); +} + +int32_t C4ConsoleQtLocalizeOverviewDlg::GetColumnByLanguage(const char *lang) const +{ + // Language column by ID + auto iter = lang2col.find(QString(lang)); + if (iter != lang2col.end()) + { + return iter->second; + } + // No column matches + return -1; +} + +int32_t C4ConsoleQtLocalizeOverviewDlg::AddLanguageColumn(const char *lang_id, const char *lang_name) +{ + // Add column + int32_t col = ui.translationTable->columnCount(); + ui.translationTable->setColumnCount(col + 1); + ui.translationTable->horizontalHeader()->setSectionResizeMode(col, QHeaderView::Stretch); + // Set header + QString text(lang_id); + if (lang_name) + { + text.append(" - ").append(lang_name); + } + SetTableItem(0, col, TIT_Header, text); + // Remember language to resolve index + lang2col[QString(lang_id)] = col; + col2lang.emplace_back(QString(lang_id)); + return col; +} + +void C4ConsoleQtLocalizeOverviewDlg::SetTableItem(int32_t row, int32_t col, TableItemType item_type, const QString &text) +{ + // Set entry in translation table + auto item = new QTableWidgetItem(QString(text)); + // Headers and info columns cannot be edited + if (item_type != TIT_Entry) + { + item->setFlags(item->flags() & ~(Qt::ItemIsEditable)); // | Qt::ItemIsSelectable + } + // Set the entry + if (item_type == TIT_Header) + { + ui.translationTable->setHorizontalHeaderItem(col, item); + } + else + { + ui.translationTable->setItem(row, col, item); + } +} + +void C4ConsoleQtLocalizeOverviewDlg::reject() +{ + // Cleanup on dialogue close to avoid hanging proplists in C4Value + ClearTable(); + QDialog::reject(); +} + +void C4ConsoleQtLocalizeOverviewDlg::ClearTable() +{ + ui.translationTable->clearContents(); + lang_strings.clear(); + lang2col.clear(); + col2lang.clear(); +} + +void C4ConsoleQtLocalizeOverviewDlg::Refresh() +{ + // Re-fill + is_refreshing = true; + // This may take a while; show a dialogue + QProgressDialog progress(QString(LoadResStr("IDS_CNS_COLLECTINGLOCALIZATIONS")), QString(), 0, 0, this); + progress.setCancelButton(nullptr); // Can't cancel + progress.setWindowModality(Qt::WindowModal); + + // Clear previous + ClearTable(); + + // Collect localizable strings + C4PropertyCollection lang_string_collector; + lang_string_collector.CollectPropLists(P_Function, C4VString(&::Strings.P[P_Translate])); + lang_strings = lang_string_collector.GetEntries(); + + // Set up headers + ui.translationTable->setRowCount(lang_strings.size()); + ui.translationTable->setColumnCount(2); + SetTableItem(0, 0, TIT_Header, QString(LoadResStr("IDS_CNS_OBJECT"))); + SetTableItem(0, 1, TIT_Header, QString(LoadResStr("IDS_CNS_PATH"))); + ui.translationTable->setColumnWidth(0, 100); + ui.translationTable->setColumnWidth(1, 200); + col2lang.resize(2); + + // Add default language columns + int32_t lang_index = 0; + C4LanguageInfo *lang_info; + while (lang_info = ::Languages.GetInfo(lang_index++)) + { + AddLanguageColumn(lang_info->Code, lang_info->Name); + } + + // Add them to the table + int32_t row = 0; + for (auto &entry : lang_strings) + { + assert(entry.value.GetType() == C4V_PropList); + C4PropList *translations_proplist = entry.value._getPropList(); + assert(translations_proplist); + + // Add name and path + SetTableItem(row, 0, TIT_Info, QString(entry.name.getData())); + SetTableItem(row, 1, TIT_Info, QString(entry.path.GetGetPath())); + + // Add each language + for (C4String *lang_str : translations_proplist->GetSortedLocalProperties(false)) + { + if (lang_str->GetData().getLength() == 2) + { + C4Value text_val; + if (translations_proplist->GetPropertyByS(lang_str, &text_val)) + { + C4String *text = text_val.getStr(); + if (text) + { + int32_t col = GetColumnByLanguage(lang_str->GetCStr()); + if (col < 0) + { + // This is a non-default language. Add a column. + col = AddLanguageColumn(lang_str->GetCStr(), nullptr); + } + // Set text for this translation + SetTableItem(row, col, TIT_Entry, QString(text->GetCStr())); + } + } + } + } + ++row; + } + + // Done! + progress.close(); + is_refreshing = false; +} + +void C4ConsoleQtLocalizeOverviewDlg::OnTableItemChanged(QTableWidgetItem *item) +{ + // User edits only + if (is_refreshing) + { + return; + } + // Find path to proplist to edit + const C4PropertyPath &prop_path = lang_strings[item->row()].path; + // Find language to edit + QString lang_id = col2lang[item->column()]; + // Set to new value through control queue + QString new_value = item->text(); + if (new_value.length()) + { + // TODO: Would be better to handle escaping in the C4Value-to-string code + new_value = new_value.replace(R"(\)", R"(\\)").replace(R"(")", R"(\")"); + // Update in script + C4PropertyPath set_path(prop_path, lang_id.toUtf8().data()); + set_path.SetProperty((R"(")" + new_value + R"(")").toUtf8().data()); + } + else + { + // Empty string: Delete this language entry + prop_path.DoCall(FormatString(R""(ResetProperty("%s", %%s))"", lang_id.toUtf8().data()).getData()); + + } +} + diff --git a/src/editor/C4ConsoleQtLocalizeOverview.h b/src/editor/C4ConsoleQtLocalizeOverview.h new file mode 100644 index 000000000..df516e865 --- /dev/null +++ b/src/editor/C4ConsoleQtLocalizeOverview.h @@ -0,0 +1,62 @@ +/* +* OpenClonk, http://www.openclonk.org +* +* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/ +* Copyright (c) 2013, The OpenClonk Team and contributors +* +* Distributed under the terms of the ISC license; see accompanying file +* "COPYING" for details. +* +* "Clonk" is a registered trademark of Matthes Bender, used with permission. +* See accompanying file "TRADEMARK" for details. +* +* To redistribute this file separately, substitute the full license texts +* for the above references. +*/ + +/* String localization editor */ + +#ifndef INC_C4ConsoleQtLocalizeOverview +#define INC_C4ConsoleQtLocalizeOverview +#ifdef WITH_QT_EDITOR + +#include "C4Include.h" // needed for automoc +#include "editor/C4ConsoleGUI.h" // for glew.h +#include "editor/C4ConsoleQt.h" +#include "editor/C4PropertyPath.h" +#include "ui_C4ConsoleQtLocalizeOverview.h" + +class C4ConsoleQtLocalizeOverviewDlg : public QDialog +{ + Q_OBJECT + + Ui::LocalizeOverviewDialog ui; + std::vector lang_strings; + std::map lang2col; // Language-to-column lookup + std::vector col2lang; // Column-to-language loopup + bool is_refreshing{ false }; + + enum TableItemType + { + TIT_Header, // Top row + TIT_Info, // Name+Path columns + TIT_Entry, // Editable string entry + }; + +public: + C4ConsoleQtLocalizeOverviewDlg(class QMainWindow *parent_window); + +private: + int32_t GetColumnByLanguage(const char *lang) const; + int32_t AddLanguageColumn(const char *lang_id, const char *lang_name); + void SetTableItem(int32_t row, int32_t col, TableItemType item_type, const QString &text); + void reject() override; + void ClearTable(); + +public slots: + void Refresh(); + void OnTableItemChanged(QTableWidgetItem *item); +}; + +#endif // WITH_QT_EDITOR +#endif // INC_C4ConsoleQtLocalizeOverview diff --git a/src/editor/C4ConsoleQtLocalizeOverview.ui b/src/editor/C4ConsoleQtLocalizeOverview.ui new file mode 100644 index 000000000..2e0db512a --- /dev/null +++ b/src/editor/C4ConsoleQtLocalizeOverview.ui @@ -0,0 +1,146 @@ + + + LocalizeOverviewDialog + + + + 0 + 0 + 1022 + 456 + + + + + 0 + 0 + + + + IDS_CNS_TRANSLATE + + + + + + + + true + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + true + + + 300 + + + false + + + false + + + + + + + + + IDS_CNS_REFRESH + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + + + + + + + + buttonBox + accepted() + LocalizeOverviewDialog + accept() + + + 341 + 434 + + + 157 + 274 + + + + + buttonBox + rejected() + LocalizeOverviewDialog + reject() + + + 409 + 440 + + + 286 + 274 + + + + + translationTable + itemChanged(QTableWidgetItem*) + LocalizeOverviewDialog + OnTableItemChanged(QTableWidgetItem*) + + + 510 + 211 + + + 510 + 227 + + + + + refreshButton + pressed() + LocalizeOverviewDialog + Refresh() + + + 63 + 432 + + + 510 + 227 + + + + + + OnTableItemChanged(QTableWidgetItem*) + Refresh() + + diff --git a/src/editor/C4ConsoleQtLocalizeString.cpp b/src/editor/C4ConsoleQtLocalizeString.cpp index cb00e25fc..9673065a0 100644 --- a/src/editor/C4ConsoleQtLocalizeString.cpp +++ b/src/editor/C4ConsoleQtLocalizeString.cpp @@ -86,7 +86,7 @@ void C4ConsoleQtLocalizeStringDlg::DoError(const char *msg) QLineEdit *C4ConsoleQtLocalizeStringDlg::AddEditor(const char *language, const char *language_name) { - assert(!GetEditorByLanguage(const char *language)); + assert(!GetEditorByLanguage(language)); // Add editor widgets int32_t row = edited_languages.size(); QString language_label_text(language); diff --git a/src/editor/C4ConsoleQtMainWindow.ui b/src/editor/C4ConsoleQtMainWindow.ui index bfd55089a..d3ff8ddea 100644 --- a/src/editor/C4ConsoleQtMainWindow.ui +++ b/src/editor/C4ConsoleQtMainWindow.ui @@ -409,6 +409,7 @@ + @@ -1274,6 +1275,17 @@ Ctrl+Shift+E + + + IDS_MNU_TRANSLATIONTABLE + + + IDS_MNU_TRANSLATIONTABLE + + + IDS_MNU_TRANSLATIONTABLE + + @@ -2047,6 +2059,22 @@ + + actionTranslations + triggered() + MainWindow + OpenTranslationsOverview() + + + -1 + -1 + + + 477 + 312 + + + PlayPressed(bool) @@ -2096,5 +2124,6 @@ GradeDown() FileOpenInNetwork() FileExportPacked() + OpenTranslationsOverview() diff --git a/src/editor/C4ConsoleQtState.cpp b/src/editor/C4ConsoleQtState.cpp index ba968a1a0..0fd60c4bb 100644 --- a/src/editor/C4ConsoleQtState.cpp +++ b/src/editor/C4ConsoleQtState.cpp @@ -24,6 +24,7 @@ #include "editor/C4ConsoleQtNewScenario.h" #include "editor/C4ConsoleQtViewport.h" #include "editor/C4ConsoleQtShapes.h" +#include "editor/C4ConsoleQtLocalizeOverview.h" #include "editor/C4Console.h" #include "platform/StdRegistry.h" #include "landscape/C4Landscape.h" @@ -341,6 +342,24 @@ void C4ConsoleQtMainWindow::DrawSizeChanged(int newval) ::Console.ToolsDlg.SetGrade(newval); } +void C4ConsoleQtMainWindow::OpenTranslationsOverview() +{ + // Open/refresh translations overview dialogue + if (!state->translation_overview_dialogue) + { + state->translation_overview_dialogue.reset(new C4ConsoleQtLocalizeOverviewDlg(this)); + } + state->translation_overview_dialogue->Refresh(); + state->translation_overview_dialogue->show(); + state->translation_overview_dialogue->resize(size() * 8/10); + int32_t margin = size().width() / 10; + QRect geom = geometry(); + geom.adjust(margin, margin, -margin, -margin); + state->translation_overview_dialogue->setGeometry(geom); + state->translation_overview_dialogue->raise(); + state->translation_overview_dialogue->activateWindow(); +} + // File menu void C4ConsoleQtMainWindow::FileNew() { ::Console.FileNew(); } void C4ConsoleQtMainWindow::FileOpen() { ::Console.FileOpen(nullptr, false); } @@ -816,6 +835,7 @@ void C4ConsoleGUIState::UpdateActionStates() ui.actionStaticLandscape->setEnabled(enabled); ui.actionStaticFlatLandscape->setEnabled(enabled); ui.actionExactLandscape->setEnabled(enabled); + ui.actionTranslations->setEnabled(enabled); ui.foregroundMatTexComboBox->setEnabled(is_drawing); ui.backgroundMatTexComboBox->setEnabled(is_drawing); ui.drawSizeSlider->setEnabled(is_drawing); diff --git a/src/editor/C4ConsoleQtState.h b/src/editor/C4ConsoleQtState.h index 3d981fe32..2509adb6c 100644 --- a/src/editor/C4ConsoleQtState.h +++ b/src/editor/C4ConsoleQtState.h @@ -126,6 +126,7 @@ public slots: void StaticFlatLandscapePressed(bool down); void ExactLandscapePressed(bool down); void DrawSizeChanged(int newval); + void OpenTranslationsOverview(); // File menu void FileNew(); void FileOpen(); @@ -191,6 +192,7 @@ public: std::unique_ptr object_list_model; std::unique_ptr definition_list_model; std::unique_ptr disable_shortcut_filter; + std::unique_ptr translation_overview_dialogue; std::list viewports; std::list > client_actions; std::list > player_actions;