Editor: Add translation overview table (Tools menu)

alut-include-path
Sven Eberhardt 2017-05-09 22:43:56 -04:00
parent 3289068ee0
commit 1b4fd9abe3
12 changed files with 481 additions and 1 deletions

View File

@ -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}

View File

@ -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

View File

@ -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

View File

@ -61,6 +61,7 @@ constexpr bool SOLIDMASK_DEBUG = false;
#include <string>
#include <utility>
#include <vector>
#include <unordered_set>
#include <math.h>
#include "lib/Standard.h"

View File

@ -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)

View File

@ -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());
}
}

View File

@ -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<C4PropertyCollection::Entry> lang_strings;
std::map<QString, int32_t> lang2col; // Language-to-column lookup
std::vector<QString> 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

View File

@ -0,0 +1,146 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>LocalizeOverviewDialog</class>
<widget class="QDialog" name="LocalizeOverviewDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1022</width>
<height>456</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string comment="res">IDS_CNS_TRANSLATE</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTableWidget" name="translationTable">
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<attribute name="horizontalHeaderVisible">
<bool>true</bool>
</attribute>
<attribute name="horizontalHeaderDefaultSectionSize">
<number>300</number>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderHighlightSections">
<bool>false</bool>
</attribute>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="refreshButton">
<property name="text">
<string comment="res">IDS_CNS_REFRESH</string>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Close</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>LocalizeOverviewDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>341</x>
<y>434</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>LocalizeOverviewDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>409</x>
<y>440</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>translationTable</sender>
<signal>itemChanged(QTableWidgetItem*)</signal>
<receiver>LocalizeOverviewDialog</receiver>
<slot>OnTableItemChanged(QTableWidgetItem*)</slot>
<hints>
<hint type="sourcelabel">
<x>510</x>
<y>211</y>
</hint>
<hint type="destinationlabel">
<x>510</x>
<y>227</y>
</hint>
</hints>
</connection>
<connection>
<sender>refreshButton</sender>
<signal>pressed()</signal>
<receiver>LocalizeOverviewDialog</receiver>
<slot>Refresh()</slot>
<hints>
<hint type="sourcelabel">
<x>63</x>
<y>432</y>
</hint>
<hint type="destinationlabel">
<x>510</x>
<y>227</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>OnTableItemChanged(QTableWidgetItem*)</slot>
<slot>Refresh()</slot>
</slots>
</ui>

View File

@ -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);

View File

@ -409,6 +409,7 @@
<addaction name="actionExactLandscape"/>
<addaction name="separator"/>
<addaction name="menuIDS_MNU_SHORTCUTS"/>
<addaction name="actionTranslations"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuTools"/>
@ -1274,6 +1275,17 @@
<string>Ctrl+Shift+E</string>
</property>
</action>
<action name="actionTranslations">
<property name="text">
<string comment="res">IDS_MNU_TRANSLATIONTABLE</string>
</property>
<property name="iconText">
<string comment="res">IDS_MNU_TRANSLATIONTABLE</string>
</property>
<property name="toolTip">
<string comment="res">IDS_MNU_TRANSLATIONTABLE</string>
</property>
</action>
</widget>
<resources>
<include location="resource.qrc"/>
@ -2047,6 +2059,22 @@
</hint>
</hints>
</connection>
<connection>
<sender>actionTranslations</sender>
<signal>triggered()</signal>
<receiver>MainWindow</receiver>
<slot>OpenTranslationsOverview()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>477</x>
<y>312</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>PlayPressed(bool)</slot>
@ -2096,5 +2124,6 @@
<slot>GradeDown()</slot>
<slot>FileOpenInNetwork()</slot>
<slot>FileExportPacked()</slot>
<slot>OpenTranslationsOverview()</slot>
</slots>
</ui>

View File

@ -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);

View File

@ -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<class C4ConsoleQtObjectListModel> object_list_model;
std::unique_ptr<class C4ConsoleQtDefinitionListModel> definition_list_model;
std::unique_ptr<class C4DisableShortcutFilter> disable_shortcut_filter;
std::unique_ptr<class C4ConsoleQtLocalizeOverviewDlg> translation_overview_dialogue;
std::list<class C4ConsoleQtViewportDockWidget *> viewports;
std::list<std::unique_ptr<C4ConsoleClientAction> > client_actions;
std::list<std::unique_ptr<C4ConsoleRemovePlayerAction> > player_actions;