Browse Source

Port plLocalizationEditor to Qt5

Michael Hansen 10 years ago
parent
commit
f6d04e78c8
  1. 3
      Sources/Tools/CMakeLists.txt
  2. 39
      Sources/Tools/plLocalizationEditor/CMakeLists.txt
  3. 375
      Sources/Tools/plLocalizationEditor/plAddDlgs.cpp
  4. 53
      Sources/Tools/plLocalizationEditor/plAddDlgs.h
  5. 441
      Sources/Tools/plLocalizationEditor/plEditDlg.cpp
  6. 61
      Sources/Tools/plLocalizationEditor/plEditDlg.h
  7. 131
      Sources/Tools/plLocalizationEditor/plLocTreeView.cpp
  8. 19
      Sources/Tools/plLocalizationEditor/plLocTreeView.h
  9. 339
      Sources/Tools/plLocalizationEditor/plLocalizationEditor.cpp
  10. 124
      Sources/Tools/plLocalizationEditor/res/AddElement.ui
  11. 91
      Sources/Tools/plLocalizationEditor/res/AddLocalization.ui
  12. 178
      Sources/Tools/plLocalizationEditor/res/EditDialog.ui
  13. 5
      Sources/Tools/plLocalizationEditor/res/plLocalizationEditor.qrc
  14. 268
      Sources/Tools/plLocalizationEditor/res/plLocalizationEditor.rc
  15. 51
      Sources/Tools/plLocalizationEditor/res/resource.h

3
Sources/Tools/CMakeLists.txt

@ -1,4 +1,7 @@
if(PLASMA_BUILD_TOOLS)
find_package(Qt5Core REQUIRED)
find_package(Qt5Widgets REQUIRED)
add_subdirectory(plLocalizationEditor)
add_subdirectory(plResBrowser)
add_subdirectory(plShaderAssembler)

39
Sources/Tools/plLocalizationEditor/CMakeLists.txt

@ -8,24 +8,42 @@ add_definitions("-DUNICODE")
set(plLocalizationEditor_HEADERS
plAddDlgs.h
plEditDlg.h
plLocTreeView.h
plEditDlg.h
plLocTreeView.h
)
qt5_wrap_cpp(plLocalizationEditor_MOC ${plLocalizationEditor_HEADERS})
set(plLocalizationEditor_SOURCES
plAddDlgs.cpp
plEditDlg.cpp
plLocalizationEditor.cpp
plLocTreeView.cpp
plEditDlg.cpp
plLocalizationEditor.cpp
plLocTreeView.cpp
)
set(plLocalizationEditor_RESOURCES
res/plLocalizationEditor.rc
res/resource.h
res/icon1.ico
)
add_executable(plLocalizationEditor WIN32 ${plLocalizationEditor_HEADERS} ${plLocalizationEditor_SOURCES} ${plLocalizationEditor_RESOURCES})
set(plLocalizationEditor_RCC_SOURCES
res/plLocalizationEditor.qrc
)
qt5_add_resources(plLocalizationEditor_RCC ${plLocalizationEditor_RCC_SOURCES})
set(plLocalizationEditor_UIC_SOURCES
res/EditDialog.ui
res/AddElement.ui
res/AddLocalization.ui
)
qt5_wrap_ui(plLocalizationEditor_UIC ${plLocalizationEditor_UIC_SOURCES})
# For generated ui_*.h files
include_directories(${CMAKE_CURRENT_BINARY_DIR})
add_executable(plLocalizationEditor WIN32 ${plLocalizationEditor_HEADERS}
${plLocalizationEditor_SOURCES} ${plLocalizationEditor_RCC}
${plLocalizationEditor_UIC} ${plLocalizationEditor_MOC})
target_link_libraries(plLocalizationEditor CoreLib)
target_link_libraries(plLocalizationEditor pnSceneObject)
@ -33,12 +51,13 @@ target_link_libraries(plLocalizationEditor pnUUID)
target_link_libraries(plLocalizationEditor plResMgr)
target_link_libraries(plLocalizationEditor pfLocalizationMgr)
target_link_libraries(plLocalizationEditor ${EXPAT_LIBRARY})
target_link_libraries(plLocalizationEditor comctl32)
target_link_libraries(plLocalizationEditor Qt5::Widgets)
if(USE_VLD)
target_link_libraries(plLocalizationEditor ${VLD_LIBRARY})
endif()
source_group("Source Files" FILES ${plLocalizationEditor_SOURCES})
source_group("Source Files" FILES ${plLocalizationEditor_SOURCES} ${plLocalizationEditor_MOC})
source_group("Header Files" FILES ${plLocalizationEditor_HEADERS})
source_group("Resource Files" FILES ${plLocalizationEditor_RESOURCES})
source_group("Resource Files" FILES ${plLocalizationEditor_RCC_SOURCES} ${plLocalizationEditor_RCC}
${plLocalizationEditor_UIC_SOURCES} ${plLocalizationEditor_UIC})

375
Sources/Tools/plLocalizationEditor/plAddDlgs.cpp

@ -41,291 +41,119 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
*==LICENSE==*/
// basic classes for encapsulating the add dialogs
#include "res/resource.h"
#include "plAddDlgs.h"
#include "plEditDlg.h"
#include "plResMgr/plLocalization.h"
#include "pfLocalizationMgr/pfLocalizationDataMgr.h"
#include <vector>
#include <map>
#include <QPushButton>
#include "ui_AddElement.h"
#include "ui_AddLocalization.h"
extern HINSTANCE gInstance;
#include <vector>
// very simple subclass for edit controls (and combo boxes) so that they only accept alphanumeric values
class AlphaNumericEditCtrl
// very simple validator for edit controls (and combo boxes) so that they only accept alphanumeric values
class AlphaNumbericValidator : public QValidator
{
int fCtrlID;
HWND fOwner, fEditBox;
LONG_PTR fPrevProc;
public:
AlphaNumericEditCtrl() : fCtrlID(0), fOwner(NULL), fEditBox(NULL), fPrevProc(NULL) {}
~AlphaNumericEditCtrl() {}
void Setup(int ctrlID, HWND owner, bool comboBox);
static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
};
std::map<int, AlphaNumericEditCtrl> editBoxMap;
AlphaNumbericValidator(QObject *parent = nullptr) : QValidator(parent) { }
// basic setup of the edit control
void AlphaNumericEditCtrl::Setup(int ctrlID, HWND owner, bool comboBox)
{
fCtrlID = ctrlID;
fOwner = owner;
// if we're a combo box, we need to subclass the edit control, not the combo box
if (comboBox)
virtual State validate(QString &input, int &pos) const override
{
COMBOBOXINFO cbinfo;
cbinfo.cbSize = sizeof(COMBOBOXINFO);
GetComboBoxInfo(GetDlgItem(fOwner, fCtrlID), &cbinfo);
fEditBox = cbinfo.hwndItem;
}
else
fEditBox = GetDlgItem(fOwner, fCtrlID);
// subclass the edit box so we can filter input (don't ask me why we have to double cast the
// function pointer to get rid of the compiler warning)
fPrevProc = SetWindowLongPtr(fEditBox, GWLP_WNDPROC, (LONG)(LONG_PTR)AlphaNumericEditCtrl::WndProc);
editBoxMap[fCtrlID] = *this;
}
// Message handler for our edit box
LRESULT CALLBACK AlphaNumericEditCtrl::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int ctrlID = GetDlgCtrlID(hWnd);
if (editBoxMap.find(ctrlID) == editBoxMap.end()) // control ID doesn't exist, so it's probably a combo boxes' edit ctrl
ctrlID = GetDlgCtrlID(GetParent(hWnd)); // so grab the parent's ID number instead
switch (message)
{
case WM_CHAR:
for (int ch = 0; ch < input.size(); ++ch)
{
AlphaNumericEditCtrl editBox = editBoxMap[ctrlID];
char theChar = (char)wParam;
// we only accept 0-9, a-z, A-Z, or backspace
if ((theChar < '0' || theChar > '9') && (theChar < 'a' || theChar > 'z') && (theChar < 'A' || theChar >'Z') && !(theChar == VK_BACK))
{
MessageBeep(-1); // alert the user
return FALSE; // and make sure the default handler doesn't get it
}
ushort theChar = input[ch].unicode();
if ((theChar < '0' || theChar > '9') && (theChar < 'a' || theChar > 'z')
&& (theChar < 'A' || theChar >'Z'))
return Invalid;
}
return Acceptable;
}
// Any messages we don't process must be passed onto the original window function
return CallWindowProc((WNDPROC)editBoxMap[ctrlID].fPrevProc, hWnd, message, wParam, lParam);
}
};
// plAddElementDlg - dialog for adding a single element
INT_PTR CALLBACK plAddElementDlg::IDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
plAddElementDlg::plAddElementDlg(const plString &parentPath, QWidget *parent)
: QDialog(parent), fBlockUpdates(false)
{
static plAddElementDlg* pthis = NULL;
fUI = new Ui_AddElement;
fUI->setupUi(this);
layout()->setSizeConstraint(QLayout::SetFixedSize);
switch (msg)
{
case WM_INITDIALOG:
pthis = (plAddElementDlg*)lParam;
if (!pthis->IInitDlg(hDlg))
EndDialog(hDlg, 0);
return FALSE;
case WM_COMMAND:
if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDOK)
{
EndDialog(hDlg, 1);
return TRUE;
}
else if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, 0);
return TRUE;
}
else if (HIWORD(wParam) == CBN_SELCHANGE && LOWORD(wParam) == IDC_PARENTAGE)
{
wchar_t buff[256];
// we do this whole get sel, get item because get text won't return the updated text
int index = (int)SendMessage(GetDlgItem(hDlg, IDC_PARENTAGE), CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
SendMessage(GetDlgItem(hDlg, IDC_PARENTAGE), CB_GETLBTEXT, (WPARAM)index, (LPARAM)buff);
pthis->fAgeName = plString::FromWchar(buff);
pthis->fAgeChanged = true;
pthis->IUpdateDlg(hDlg);
}
else if (HIWORD(wParam) == CBN_EDITCHANGE && LOWORD(wParam) == IDC_PARENTAGE)
{
wchar_t buff[256];
GetDlgItemTextW(hDlg, IDC_PARENTAGE, buff, 256);
pthis->fAgeName = plString::FromWchar(buff);
pthis->fAgeChanged = true;
pthis->IUpdateDlg(hDlg, false);
}
else if (HIWORD(wParam) == CBN_SELCHANGE && LOWORD(wParam) == IDC_PARENTSET)
{
wchar_t buff[256];
// we do this whole get sel, get item because get text won't return the updated text
int index = (int)SendMessage(GetDlgItem(hDlg, IDC_PARENTSET), CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
SendMessage(GetDlgItem(hDlg, IDC_PARENTSET), CB_GETLBTEXT, (WPARAM)index, (LPARAM)buff);
pthis->fSetName = plString::FromWchar(buff);
pthis->IUpdateDlg(hDlg);
}
else if (HIWORD(wParam) == CBN_EDITCHANGE && LOWORD(wParam) == IDC_PARENTSET)
{
wchar_t buff[256];
GetDlgItemTextW(hDlg, IDC_PARENTSET, buff, 256);
AlphaNumbericValidator *validator = new AlphaNumbericValidator(this);
fUI->fParentAge->setValidator(validator);
fUI->fParentSet->setValidator(validator);
fUI->fElementName->setValidator(validator);
pthis->fSetName = plString::FromWchar(buff);
pthis->IUpdateDlg(hDlg, false);
}
else if (HIWORD(wParam) == EN_UPDATE && LOWORD(wParam) == IDC_ELEMENTNAME)
{
wchar_t buff[256];
GetDlgItemTextW(hDlg, IDC_ELEMENTNAME, buff, 256);
pthis->fElementName = plString::FromWchar(buff);
connect(fUI->fParentAge, SIGNAL(currentTextChanged(QString)), SLOT(Update(QString)));
connect(fUI->fParentSet, SIGNAL(currentTextChanged(QString)), SLOT(Update(QString)));
connect(fUI->fElementName, SIGNAL(textChanged(QString)), SLOT(Update(QString)));
pthis->IUpdateDlg(hDlg);
}
break;
// throw away vars
plString element, lang;
SplitLocalizationPath(parentPath, fAgeName, fSetName, element, lang);
}
case WM_SYSCOMMAND:
switch (wParam)
{
case SC_CLOSE:
EndDialog(hDlg, 0);
return TRUE;
}
break;
}
return FALSE;
plAddElementDlg::~plAddElementDlg()
{
delete fUI;
}
bool plAddElementDlg::IInitDlg(HWND hDlg)
bool plAddElementDlg::DoPick()
{
HWND listCtrl = GetDlgItem(hDlg, IDC_PARENTAGE);
std::vector<plString> ageNames = pfLocalizationDataMgr::Instance().GetAgeList();
fBlockUpdates = true;
// add the age names to the list
for (int i = 0; i < ageNames.size(); i++)
SendMessage(listCtrl, CB_ADDSTRING, (WPARAM)0, (LPARAM)ageNames[i].c_str());
fUI->fParentAge->addItem(ageNames[i].c_str());
// select the age we were given
SendMessage(listCtrl, CB_SELECTSTRING, (WPARAM)-1, (LPARAM)fAgeName.c_str());
fUI->fParentAge->setCurrentText("");
fBlockUpdates = false;
fUI->fParentAge->setCurrentText(fAgeName.c_str());
AlphaNumericEditCtrl ageCtrl, setCtrl, subCtrl;
ageCtrl.Setup(IDC_PARENTAGE, hDlg, true);
setCtrl.Setup(IDC_PARENTSET, hDlg, true);
subCtrl.Setup(IDC_ELEMENTNAME, hDlg, false);
fAgeChanged = true;
IUpdateDlg(hDlg);
return true;
return exec() == QDialog::Accepted;
}
void plAddElementDlg::IUpdateDlg(HWND hDlg, bool setFocus)
void plAddElementDlg::Update(const QString &text)
{
plString pathStr = plString::Format("Path: %s.%s.%s", fAgeName.c_str(), fSetName.c_str(), fElementName.c_str());
SetDlgItemTextW(hDlg, IDC_PATH, pathStr.ToWchar());
if (fBlockUpdates)
return;
if (sender() == fUI->fParentAge)
fAgeName = plString(text.toUtf8().constData());
else if (sender() == fUI->fParentSet)
fSetName = plString(text.toUtf8().constData());
else if (sender() == fUI->fElementName)
fElementName = plString(text.toUtf8().constData());
if (fAgeChanged) // we only update this if the age changed (saves time and prevents weird bugs, like typing backwards)
fUI->fPathLabel->setText(tr("%1.%2.%3").arg(fAgeName.c_str())
.arg(fSetName.c_str()).arg(fElementName.c_str()));
if (sender() == fUI->fParentAge) // we only update this if the age changed
{
// now add the sets
HWND listCtrl = GetDlgItem(hDlg, IDC_PARENTSET);
SendMessage(listCtrl, CB_RESETCONTENT, (WPARAM)0, (LPARAM)0);
fUI->fParentSet->clear();
fUI->fParentSet->clearEditText();
std::vector<plString> setNames = pfLocalizationDataMgr::Instance().GetSetList(fAgeName);
// add the set names to the list
fBlockUpdates = true;
for (int i = 0; i < setNames.size(); i++)
SendMessage(listCtrl, CB_ADDSTRING, (WPARAM)0, (LPARAM)setNames[i].c_str());
fUI->fParentSet->addItem(setNames[i].c_str());
// select the set we currently have
int ret = (int)SendMessage(listCtrl, CB_SELECTSTRING, (WPARAM)-1, (LPARAM)fSetName.c_str());
if (ret == CB_ERR) // couldn't find the string, so just set it as the current string in the edit box
SetDlgItemTextW(hDlg, IDC_PARENTSET, fSetName.ToWchar());
fAgeChanged = false;
fUI->fParentSet->setCurrentText("");
fBlockUpdates = false;
fUI->fParentSet->setCurrentText(fSetName.c_str());
}
if (!fSetName.IsEmpty() && setFocus)
SetFocus(GetDlgItem(hDlg, IDC_ELEMENTNAME));
if (!fSetName.IsEmpty() && fElementName.IsEmpty())
EnableWindow(GetDlgItem(hDlg, IDOK), TRUE);
else
EnableWindow(GetDlgItem(hDlg, IDOK), FALSE);
}
plAddElementDlg::plAddElementDlg(plString parentPath)
{
// throw away vars
plString element, lang;
SplitLocalizationPath(parentPath, fAgeName, fSetName, element, lang);
}
bool plAddElementDlg::DoPick(HWND parent)
{
INT_PTR ret = DialogBoxParam(gInstance, MAKEINTRESOURCE(IDD_ADDELEMENT),
parent, IDlgProc, (LPARAM)this);
editBoxMap.clear();
return (ret != 0);
bool valid = !(fAgeName.IsEmpty() || fSetName.IsEmpty() || fElementName.IsEmpty());
fUI->fButtons->button(QDialogButtonBox::Ok)->setEnabled(valid);
}
// plAddLocalizationDlg - dialog for adding a single localization
INT_PTR CALLBACK plAddLocalizationDlg::IDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
static plAddLocalizationDlg* pthis = NULL;
switch (msg)
{
case WM_INITDIALOG:
pthis = (plAddLocalizationDlg*)lParam;
if (!pthis->IInitDlg(hDlg))
EndDialog(hDlg, 0);
return FALSE;
case WM_COMMAND:
if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDOK)
{
EndDialog(hDlg, 1);
return TRUE;
}
else if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, 0);
return TRUE;
}
else if (HIWORD(wParam) == CBN_SELCHANGE && LOWORD(wParam) == IDC_LANGUAGE)
{
wchar_t buff[256];
// we do this whole get sel, get item because get text won't return the updated text
int index = (int)SendMessage(GetDlgItem(hDlg, IDC_LANGUAGE), CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
SendMessage(GetDlgItem(hDlg, IDC_LANGUAGE), CB_GETLBTEXT, (WPARAM)index, (LPARAM)buff);
pthis->fLanguageName = plString::FromWchar(buff);
pthis->IUpdateDlg(hDlg);
}
break;
case WM_SYSCOMMAND:
switch (wParam)
{
case SC_CLOSE:
EndDialog(hDlg, 0);
return TRUE;
}
break;
}
return FALSE;
}
std::vector<plString> IGetAllLanguageNames()
{
int numLocales = plLocalization::GetNumLocales();
@ -342,10 +170,24 @@ std::vector<plString> IGetAllLanguageNames()
return retVal;
}
bool plAddLocalizationDlg::IInitDlg(HWND hDlg)
plAddLocalizationDlg::plAddLocalizationDlg(const plString &parentPath, QWidget *parent)
: QDialog(parent)
{
fUI = new Ui_AddLocalization;
fUI->setupUi(this);
layout()->setSizeConstraint(QLayout::SetFixedSize);
connect(fUI->fLanguage, SIGNAL(currentIndexChanged(int)), SLOT(SelectLanguage(int)));
// throw away vars
plString lang;
SplitLocalizationPath(parentPath, fAgeName, fSetName, fElementName, lang);
}
bool plAddLocalizationDlg::DoPick()
{
plString pathStr = plString::Format("Path: %s.%s.%s", fAgeName.c_str(), fSetName.c_str(), fElementName.c_str());
SetDlgItemTextW(hDlg, IDC_PATH, pathStr.ToWchar());
fUI->fPathLabel->setText(tr("%1.%2.%3").arg(fAgeName.c_str())
.arg(fSetName.c_str()).arg(fElementName.c_str()));
std::vector<plString> existingLanguages;
existingLanguages = pfLocalizationDataMgr::Instance().GetLanguages(fAgeName, fSetName, fElementName);
@ -353,61 +195,30 @@ bool plAddLocalizationDlg::IInitDlg(HWND hDlg)
std::vector<plString> missingLanguages = IGetAllLanguageNames();
for (int i = 0; i < existingLanguages.size(); i++) // remove all languages we already have
{
for (int j = 0; j < missingLanguages.size(); j++)
for (auto lit = missingLanguages.begin(); lit != missingLanguages.end(); )
{
if (missingLanguages[j] == existingLanguages[i])
{
missingLanguages.erase(missingLanguages.begin() + j);
j--;
}
if (*lit == existingLanguages[i])
lit = missingLanguages.erase(lit);
else
++lit;
}
}
HWND listCtrl = GetDlgItem(hDlg, IDC_LANGUAGE);
// see if any languages are missing
if (missingLanguages.size() == 0)
{
// none are missing, so disable the control
EnableWindow(listCtrl, FALSE);
IUpdateDlg(hDlg);
return true;
// none are missing, so close the dialog
return false;
}
// add the missing languages to the list
for (int i = 0; i < missingLanguages.size(); i++)
SendMessage(listCtrl, CB_ADDSTRING, (WPARAM)0, (LPARAM)missingLanguages[i].c_str());
fUI->fLanguage->addItem(missingLanguages[i].c_str());
// select the first language in the list
SendMessage(listCtrl, CB_SETCURSEL, (WPARAM)0, (LPARAM)0);
// and put it's value into the internal variable
wchar_t buff[256];
GetDlgItemText(hDlg, IDC_LANGUAGE, buff, 256);
fLanguageName = plString::FromWchar(buff);
IUpdateDlg(hDlg);
return true;
}
void plAddLocalizationDlg::IUpdateDlg(HWND hDlg)
{
if (!fLanguageName.IsEmpty())
EnableWindow(GetDlgItem(hDlg, IDOK), TRUE);
else
EnableWindow(GetDlgItem(hDlg, IDOK), FALSE);
}
plAddLocalizationDlg::plAddLocalizationDlg(plString parentPath)
{
// throw away vars
plString lang;
SplitLocalizationPath(parentPath, fAgeName, fSetName, fElementName, lang);
return exec() == QDialog::Accepted;
}
bool plAddLocalizationDlg::DoPick(HWND parent)
void plAddLocalizationDlg::SelectLanguage(int which)
{
INT_PTR ret = DialogBoxParam(gInstance, MAKEINTRESOURCE(IDD_ADDLOCALIZATION),
parent, IDlgProc, (LPARAM)this);
return (ret != 0);
fLanguageName = fUI->fLanguage->itemText(which).toUtf8().constData();
}

53
Sources/Tools/plLocalizationEditor/plAddDlgs.h

@ -43,41 +43,48 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#ifndef __plAddDlgs_h__
#define __plAddDlgs_h__
#include "HeadSpin.h"
#include "hsWindows.h"
#include <QDialog>
#include "plString.h"
class plAddElementDlg
class plAddElementDlg : public QDialog
{
protected:
static INT_PTR CALLBACK IDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
Q_OBJECT
bool IInitDlg(HWND hDlg);
void IUpdateDlg(HWND hDlg, bool setFocus = true);
plString fAgeName, fSetName, fElementName;
bool fAgeChanged;
public:
plAddElementDlg(plString parentPath);
plAddElementDlg(const plString &parentPath, QWidget *parent = nullptr);
virtual ~plAddElementDlg();
bool DoPick(); // returns true if [Ok] clicked, false otherwise.
plString GetValue() const
{
return plString::Format("%s.%s.%s", fAgeName.c_str(), fSetName.c_str(), fElementName.c_str());
}
bool DoPick(HWND parent); // returns true if [Ok] clicked, false otherwise.
plString GetValue() {return plString::Format("%s.%s.%s", fAgeName.c_str(), fSetName.c_str(), fElementName.c_str());}
private slots:
void Update(const QString &text);
private:
class Ui_AddElement *fUI;
plString fAgeName, fSetName, fElementName;
bool fBlockUpdates;
};
class plAddLocalizationDlg
class plAddLocalizationDlg : public QDialog
{
protected:
static INT_PTR CALLBACK IDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
Q_OBJECT
bool IInitDlg(HWND hDlg);
void IUpdateDlg(HWND hDlg);
plString fAgeName, fSetName, fElementName, fLanguageName;
public:
plAddLocalizationDlg(plString parentPath);
plAddLocalizationDlg(const plString &parentPath, QWidget *parent = nullptr);
bool DoPick(); // returns true if [Ok] clicked, false otherwise.
const plString &GetValue() const { return fLanguageName; }
bool DoPick(HWND parent); // returns true if [Ok] clicked, false otherwise.
plString GetValue() {return fLanguageName;}
private slots:
void SelectLanguage(int which);
private:
class Ui_AddLocalization *fUI;
plString fAgeName, fSetName, fElementName, fLanguageName;
};
#endif

441
Sources/Tools/plLocalizationEditor/plEditDlg.cpp

@ -41,250 +41,339 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
*==LICENSE==*/
// Basic edit dialog stuff
#include "plEditDlg.h"
#include "res/resource.h"
#include "plLocTreeView.h"
#include "plAddDlgs.h"
#include "pfLocalizationMgr/pfLocalizationMgr.h"
#include "pfLocalizationMgr/pfLocalizationDataMgr.h"
#include <map>
#include <QDialog>
#include <QMessageBox>
#include <QFileDialog>
#include "ui_EditDialog.h"
HWND gEditDlg = NULL;
extern HINSTANCE gInstance;
extern HWND gTreeView;
#include <functional>
// global data for this dialog
plString gCurrentPath;
#define ABOUT_TEXT R"(plLocalizationEditor
A basic editor for Plasma 21 localization resource files
Copyright (C) 2004 Cyan Worlds, Inc.)"
// split a subtitle path up into its component parts
void SplitLocalizationPath(plString path, plString &ageName, plString &setName, plString &locName, plString &locLanguage)
static void IAboutDialog(QWidget *parent)
{
ageName = setName = locName = locLanguage = "";
std::vector<plString> tokens = path.Tokenize(".");
if (tokens.size() >= 1)
ageName = tokens[0];
if (tokens.size() >= 2)
setName = tokens[1];
if (tokens.size() >= 3)
locName = tokens[2];
if (tokens.size() >= 4)
locLanguage = tokens[3];
QDialog dlg(parent);
QLabel *image = new QLabel(&dlg);
image->setPixmap(QPixmap(":/icon1.ico"));
QLabel *text = new QLabel(QObject::tr(ABOUT_TEXT), &dlg);
QPushButton *ok = new QPushButton(QObject::tr("OK"), &dlg);
ok->setDefault(true);
QHBoxLayout *layout = new QHBoxLayout(&dlg);
layout->setMargin(8);
layout->setSpacing(10);
layout->addWidget(image);
layout->addWidget(text);
layout->addWidget(ok);
dlg.connect(ok, &QPushButton::clicked, &dlg, &QDialog::accept);
dlg.exec();
}
// saves the current localization text to the data manager
void SaveLocalizationText()
EditDialog::EditDialog()
: fEditMode(kEditNothing)
{
if (gCurrentPath.IsEmpty())
return; // no path to save
fUI = new Ui_EditDialog;
fUI->setupUi(this);
uint32_t textLen = (uint32_t)SendMessage(GetDlgItem(gEditDlg, IDC_LOCALIZATIONTEXT), WM_GETTEXTLENGTH, (WPARAM)0, (LPARAM)0);
wchar_t *buffer = new wchar_t[textLen + 2];
GetDlgItemTextW(gEditDlg, IDC_LOCALIZATIONTEXT, buffer, textLen + 1);
buffer[textLen + 1] = 0;
plString plainTextData = plString::FromWchar(buffer);
delete [] buffer;
plString ageName, setName, elementName, elementLanguage;
SplitLocalizationPath(gCurrentPath, ageName, setName, elementName, elementLanguage);
connect(fUI->fOpenAction, SIGNAL(triggered()), SLOT(OpenDataDirectory()));
connect(fUI->fSaveCurrentAction, SIGNAL(triggered()), SLOT(SaveToCurrent()));
connect(fUI->fSaveOtherAction, SIGNAL(triggered()), SLOT(SaveToDirectory()));
connect(fUI->fExitAction, SIGNAL(triggered()), SLOT(close()));
connect(fUI->fAboutAction, &QAction::triggered, std::bind(&IAboutDialog, this));
plString name = plString::Format("%s.%s.%s", ageName.c_str(), setName.c_str(), elementName.c_str());
pfLocalizationDataMgr::Instance().SetElementPlainTextData(name, elementLanguage, plainTextData);
connect(fUI->fLocalizationTree, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
SLOT(LocPathChanged(QTreeWidgetItem*,QTreeWidgetItem*)));
connect(fUI->fAddButton, SIGNAL(clicked()), SLOT(AddClicked()));
connect(fUI->fDeleteButton, SIGNAL(clicked()), SLOT(DeleteClicked()));
EnableEdit(false);
}
// Reset all controls to their default values (except for static controls)
void ResetDlgDefaults()
EditDialog::~EditDialog()
{
SetDlgItemTextW(gEditDlg, IDC_LOCALIZATIONTEXT, L"");
pfLocalizationMgr::Shutdown();
delete fUI;
}
// Enable/disable all edit controls (some won't enable/disable unless an audio file is loaded and the subtitle is timed)
void EnableDlg(BOOL enable)
// saves the current localization text to the data manager
void EditDialog::SaveLocalizationText()
{
if (!enable)
ResetDlgDefaults(); // reset controls to defaults
if (fCurrentLocPath.IsEmpty())
return; // no path to save
EnableWindow(GetDlgItem(gEditDlg, IDC_LOCALIZATIONTEXT), enable);
plString text = fUI->fLocalizationText->toPlainText().toUtf8().constData();
plString ageName, setName, elementName, elementLanguage;
SplitLocalizationPath(fCurrentLocPath, ageName, setName, elementName, elementLanguage);
plString name = plString::Format("%s.%s.%s", ageName.c_str(), setName.c_str(), elementName.c_str());
pfLocalizationDataMgr::Instance().SetElementPlainTextData(name, elementLanguage, text);
}
// updates the edit dialog based on the path specified
void UpdateEditDlg(plString locPath)
void EditDialog::LoadLocalization(const plString &locPath)
{
if (locPath == gCurrentPath)
if (locPath == fCurrentLocPath)
return;
gCurrentPath = locPath;
plString itemText = plString::Format("Text (%s):", locPath.c_str());
SetDlgItemTextW(gEditDlg, IDC_LOCPATH, itemText.ToWchar());
fCurrentLocPath = locPath;
fUI->fTextPathLabel->setText(QString("Text (%1):").arg(locPath.c_str()));
plString ageName, setName, elementName, elementLanguage;
SplitLocalizationPath(locPath, ageName, setName, elementName, elementLanguage);
// now make sure they've drilled down deep enough to enable the dialog
if (elementLanguage.IsEmpty()) // not deep enough
EnableDlg(FALSE);
EnableEdit(false);
else
{
EnableDlg(TRUE);
EnableEdit(true);
plString key = plString::Format("%s.%s.%s", ageName.c_str(), setName.c_str(), elementName.c_str());
plString elementText = pfLocalizationDataMgr::Instance().GetElementPlainTextData(key, elementLanguage);
SetDlgItemTextW(gEditDlg, IDC_LOCALIZATIONTEXT, elementText.ToWchar());
fUI->fLocalizationText->setPlainText(elementText.c_str());
}
// now to setup the add/delete buttons
if (!elementLanguage.IsEmpty()) // they have selected a language
{
SetDlgItemText(gEditDlg, IDC_ADD, L"Add Localization");
EnableWindow(GetDlgItem(gEditDlg, IDC_ADD), TRUE);
SetDlgItemText(gEditDlg, IDC_DELETE, L"Delete Localization");
if (elementLanguage != "English") // don't allow them to delete the default language
EnableWindow(GetDlgItem(gEditDlg, IDC_DELETE), TRUE);
else
EnableWindow(GetDlgItem(gEditDlg, IDC_DELETE), FALSE);
fEditMode = kEditLocalization;
fUI->fAddButton->setText(tr("Add Localization"));
fUI->fAddButton->setEnabled(true);
fUI->fDeleteButton->setText(tr("Delete Localization"));
// don't allow them to delete the default language
fUI->fDeleteButton->setEnabled(elementLanguage != "English");
}
else // they have selected something else
{
SetDlgItemText(gEditDlg, IDC_ADD, L"Add Element");
EnableWindow(GetDlgItem(gEditDlg, IDC_ADD), TRUE);
SetDlgItemText(gEditDlg, IDC_DELETE, L"Delete Element");
fEditMode = kEditElement;
fUI->fAddButton->setText(tr("Add Element"));
fUI->fAddButton->setEnabled(true);
fUI->fDeleteButton->setText(tr("Delete Element"));
if (!elementName.IsEmpty()) // they have selected an individual element
{
std::vector<plString> elementNames = pfLocalizationDataMgr::Instance().GetElementList(ageName, setName);
if (elementNames.size() > 1) // they can't delete the only subtitle in a set
EnableWindow(GetDlgItem(gEditDlg, IDC_DELETE), TRUE);
else
EnableWindow(GetDlgItem(gEditDlg, IDC_DELETE), FALSE);
// they can't delete the only subtitle in a set
fUI->fDeleteButton->setEnabled(elementNames.size() > 1);
}
else
EnableWindow(GetDlgItem(gEditDlg, IDC_DELETE), FALSE);
fUI->fDeleteButton->setEnabled(false);
}
}
BOOL HandleCommandMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
void EditDialog::EnableEdit(bool enable)
{
int wmID, wmEvent;
wmID = LOWORD(wParam);
wmEvent = HIWORD(wParam);
if (!enable)
fUI->fLocalizationText->setPlainText("");
switch (wmEvent)
fUI->fLocalizationText->setEnabled(enable);
}
void EditDialog::closeEvent(QCloseEvent *event)
{
if (fCurrentSavePath.isEmpty()) // no data open
{
case BN_CLICKED:
switch (wmID)
event->accept();
return;
}
SaveLocalizationText(); // make sure any changed text is saved to the manager
QMessageBox::StandardButton result = QMessageBox::question(this, tr("Save Changes"),
tr("Do you wish to save your changes?"),
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
if (result == QMessageBox::Yes)
SaveToDirectory();
if (result == QMessageBox::Cancel)
event->ignore();
else
event->accept();
}
void EditDialog::OpenDataDirectory()
{
QString path = QFileDialog::getExistingDirectory(this,
tr("Select a localization data directory:"),
QDir::current().absolutePath(),
QFileDialog::ShowDirsOnly | QFileDialog::ReadOnly);
if (!path.isEmpty())
{
plWaitCursor waitCursor(this);
pfLocalizationMgr::Shutdown();
fCurrentSavePath = path;
pfLocalizationMgr::Initialize(fCurrentSavePath.toUtf8().constData());
fUI->fLocalizationTree->clear();
fUI->fLocalizationTree->LoadData("");
SetTitle(path);
fUI->fSaveCurrentAction->setEnabled(true);
fUI->fSaveOtherAction->setEnabled(true);
}
}
void EditDialog::SaveToCurrent()
{
SaveLocalizationText(); // make sure any changed text is saved to the manager
// save it to our current directory
QMessageBox::StandardButton result = QMessageBox::question(this, tr("Save to Current Directory"),
tr("Are you sure you want to save to the current directory? Current data will be overwritten!"),
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
if (result == QMessageBox::Yes)
{
plWaitCursor waitCursor(this);
pfLocalizationDataMgr::Instance().WriteDatabaseToDisk(fCurrentSavePath.toUtf8().constData());
}
else if (result == QMessageBox::No)
SaveToDirectory();
// and if it's cancel we don't do anything
}
void EditDialog::SaveToDirectory()
{
SaveLocalizationText(); // make sure any changed text is saved to the manager
QString path = QFileDialog::getExistingDirectory(this,
tr("Select a directory to save the localization data to:"),
fCurrentSavePath, QFileDialog::ShowDirsOnly);
// save it to a new directory
if (!path.isEmpty())
{
plWaitCursor waitCursor(this);
fCurrentSavePath = path;
SetTitle(path);
pfLocalizationDataMgr::Instance().WriteDatabaseToDisk(fCurrentSavePath.toUtf8().constData());
}
}
void EditDialog::LocPathChanged(QTreeWidgetItem *current, QTreeWidgetItem *)
{
SaveLocalizationText(); // save any current changes to the database
LoadLocalization(fUI->fLocalizationTree->CurrentPath());
}
void EditDialog::AddClicked()
{
SaveLocalizationText(); // save any current changes to the database
if (fEditMode == kEditElement)
{
plAddElementDlg dlg(fCurrentLocPath, this);
if (dlg.DoPick())
{
case IDC_ADD:
plString path = dlg.GetValue(); // path is age.set.name
if (!pfLocalizationDataMgr::Instance().AddElement(path))
{
SaveLocalizationText(); // save any current changes to the database
plString buttonText;
wchar_t buff[256];
GetDlgItemText(gEditDlg, IDC_ADD, buff, 256);
buttonText = plString::FromWchar(buff);
if (buttonText == "Add Element")
{
plAddElementDlg dlg(gCurrentPath);
if (dlg.DoPick(gEditDlg))
{
plString path = dlg.GetValue(); // path is age.set.name
if (!pfLocalizationDataMgr::Instance().AddElement(path))
MessageBox(gEditDlg, L"Couldn't add new element because one already exists with that name!", L"Error", MB_ICONERROR | MB_OK);
else
{
gCurrentPath = "";
plLocTreeView::ClearTreeView(gTreeView);
plLocTreeView::FillTreeViewFromData(gTreeView, path);
UpdateEditDlg(path);
}
}
}
else if (buttonText == "Add Localization")
{
plAddLocalizationDlg dlg(gCurrentPath);
if (dlg.DoPick(gEditDlg))
{
plString newLanguage = dlg.GetValue();
plString ageName, setName, elementName, elementLanguage;
SplitLocalizationPath(gCurrentPath, ageName, setName, elementName, elementLanguage);
plString key = plString::Format("%s.%s.%s", ageName.c_str(), setName.c_str(), elementName.c_str());
if (!pfLocalizationDataMgr::Instance().AddLocalization(key, newLanguage))
MessageBox(gEditDlg, L"Couldn't add additional localization!", L"Error", MB_ICONERROR | MB_OK);
else
{
plString path = plString::Format("%s.%s", key.c_str(), newLanguage.c_str());
gCurrentPath = "";
plLocTreeView::ClearTreeView(gTreeView);
plLocTreeView::FillTreeViewFromData(gTreeView, path);
UpdateEditDlg(path);
}
}
}
return FALSE;
QMessageBox::critical(this, tr("Error"),
tr("Couldn't add new element because one already exists with that name!"));
}
case IDC_DELETE:
else
{
fCurrentLocPath = "";
fUI->fLocalizationTree->clear();
fUI->fLocalizationTree->LoadData(path);
LoadLocalization(path);
}
}
}
else if (fEditMode == kEditLocalization)
{
plAddLocalizationDlg dlg(fCurrentLocPath, this);
if (dlg.DoPick())
{
plString newLanguage = dlg.GetValue();
plString ageName, setName, elementName, elementLanguage;
SplitLocalizationPath(fCurrentLocPath, ageName, setName, elementName, elementLanguage);
plString key = plString::Format("%s.%s.%s", ageName.c_str(), setName.c_str(), elementName.c_str());
if (!pfLocalizationDataMgr::Instance().AddLocalization(key, newLanguage))
QMessageBox::critical(this, tr("Error"), tr("Couldn't add additional localization!"));
else
{
SaveLocalizationText(); // save any current changes to the database
plString messageText = plString::Format("Are you sure that you want to delete %s?", gCurrentPath.c_str());
int res = MessageBoxW(gEditDlg, messageText.ToWchar(), L"Delete", MB_ICONQUESTION | MB_YESNO);
if (res == IDYES)
{
plString buttonText;
wchar_t buff[256];
GetDlgItemText(gEditDlg, IDC_DELETE, buff, 256);
buttonText = plString::FromWchar(buff);
if (buttonText == "Delete Element")
{
if (!pfLocalizationDataMgr::Instance().DeleteElement(gCurrentPath))
MessageBox(gEditDlg, L"Couldn't delete element!", L"Error", MB_ICONERROR | MB_OK);
else
{
plString path = gCurrentPath;
gCurrentPath = "";
plLocTreeView::ClearTreeView(gTreeView);
plLocTreeView::FillTreeViewFromData(gTreeView, path);
UpdateEditDlg(path);
}
}
else if (buttonText == "Delete Localization")
{
plString ageName, setName, elementName, elementLanguage;
SplitLocalizationPath(gCurrentPath, ageName, setName, elementName, elementLanguage);
plString key = plString::Format("%s.%s.%s", ageName.c_str(), setName.c_str(), elementName.c_str());
if (!pfLocalizationDataMgr::Instance().DeleteLocalization(key, elementLanguage))
MessageBox(gEditDlg, L"Couldn't delete localization!", L"Error", MB_ICONERROR | MB_OK);
else
{
plString path = gCurrentPath;
gCurrentPath = "";
plLocTreeView::ClearTreeView(gTreeView);
plLocTreeView::FillTreeViewFromData(gTreeView, path);
UpdateEditDlg(path);
}
}
}
plString path = plString::Format("%s.%s", key.c_str(), newLanguage.c_str());
fCurrentLocPath = "";
fUI->fLocalizationTree->clear();
fUI->fLocalizationTree->LoadData(path);
LoadLocalization(path);
}
return FALSE;
}
}
return (BOOL)DefWindowProc(hWnd, msg, wParam, lParam);
}
// our dialog's window procedure
INT_PTR CALLBACK EditDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
void EditDialog::DeleteClicked()
{
switch(msg)
SaveLocalizationText(); // save any current changes to the database
QMessageBox::StandardButton reply = QMessageBox::question(this, tr("Delete"),
tr("Are you sure that you want to delete %1?").arg(fCurrentLocPath.c_str()));
if (reply == QMessageBox::Yes)
{
case WM_INITDIALOG:
if (fEditMode == kEditElement)
{
if (!pfLocalizationDataMgr::Instance().DeleteElement(fCurrentLocPath))
QMessageBox::critical(this, tr("Error"), tr("Couldn't delete element!"));
else
{
plString path = fCurrentLocPath;
fCurrentLocPath = "";
fUI->fLocalizationTree->clear();
fUI->fLocalizationTree->LoadData(path);
LoadLocalization(path);
}
}
else if (fEditMode == kEditLocalization)
{
gEditDlg = hWnd;
EnableDlg(FALSE);
plString ageName, setName, elementName, elementLanguage;
SplitLocalizationPath(fCurrentLocPath, ageName, setName, elementName, elementLanguage);
plString key = plString::Format("%s.%s.%s", ageName.c_str(), setName.c_str(), elementName.c_str());
if (!pfLocalizationDataMgr::Instance().DeleteLocalization(key, elementLanguage))
QMessageBox::critical(this, tr("Error"), tr("Couldn't delete localization!"));
else
{
plString path = fCurrentLocPath;
fCurrentLocPath = "";
fUI->fLocalizationTree->clear();
fUI->fLocalizationTree->LoadData(path);
LoadLocalization(path);
}
}
break;
case WM_COMMAND:
return HandleCommandMessage(hWnd, msg, wParam, lParam);
}
}
return FALSE;
// split a subtitle path up into its component parts
void SplitLocalizationPath(const plString &path, plString &ageName,
plString &setName, plString &locName, plString &locLanguage)
{
ageName = setName = locName = locLanguage = "";
std::vector<plString> tokens = path.Tokenize(".");
if (tokens.size() >= 1)
ageName = tokens[0];
if (tokens.size() >= 2)
setName = tokens[1];
if (tokens.size() >= 3)
locName = tokens[2];
if (tokens.size() >= 4)
locLanguage = tokens[3];
}

61
Sources/Tools/plLocalizationEditor/plEditDlg.h

@ -43,30 +43,69 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#ifndef _pfEditDlg_h
#define _pfEditDlg_h
#include "HeadSpin.h"
#include "hsWindows.h"
#include <QMainWindow>
#include "plString.h"
class plString;
class QTreeWidgetItem;
class EditDialog : public QMainWindow
{
Q_OBJECT
public:
EditDialog();
virtual ~EditDialog();
void SetTitle(const QString &path)
{
QString title = "plLocalizationEditor";
if (!path.isEmpty())
title += " - " + path;
setWindowTitle(title);
}
void SaveLocalizationText();
void LoadLocalization(const plString &path);
void EnableEdit(bool enable);
protected:
virtual void closeEvent(QCloseEvent *event);
private slots:
void OpenDataDirectory();
void SaveToCurrent();
void SaveToDirectory();
void LocPathChanged(QTreeWidgetItem *current, QTreeWidgetItem *);
void AddClicked();
void DeleteClicked();
private:
class Ui_EditDialog *fUI;
QString fCurrentSavePath;
plString fCurrentLocPath;
enum { kEditNothing, kEditElement, kEditLocalization } fEditMode;
};
// Little trick to show a wait cursor while something is working
class plWaitCursor
{
HCURSOR fOrig;
QWidget *fParent;
public:
plWaitCursor()
plWaitCursor(QWidget *parent) : fParent(parent)
{
fOrig = SetCursor(LoadCursor(NULL, IDC_WAIT));
fParent->setCursor(Qt::WaitCursor);
}
~plWaitCursor()
{
SetCursor(fOrig);
fParent->unsetCursor();
}
};
void SplitLocalizationPath(plString path, plString &ageName, plString &setName, plString &locName, plString &locLanguage);
void SaveLocalizationText();
void UpdateEditDlg(plString subtitlePath);
INT_PTR CALLBACK EditDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
void SplitLocalizationPath(const plString &path, plString &ageName,
plString &setName, plString &locName, plString &locLanguage);
#endif

131
Sources/Tools/plLocalizationEditor/plLocTreeView.cpp

@ -42,45 +42,11 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "plLocTreeView.h"
#include "plEditDlg.h"
#include "HeadSpin.h"
#include <commctrl.h>
#include <shlwapi.h>
#include "res/resource.h"
#include <vector>
#include <list>
#include "pfLocalizationMgr/pfLocalizationDataMgr.h"
extern HINSTANCE gInstance;
plString plLocTreeView::fPath = "";
HTREEITEM AddLeaf(HWND hTree, HTREEITEM hParent, plString text, bool sort = true)
{
// Semi-hack to keep these around as Win32 expects
static std::list<plStringBuffer<wchar_t>> bufs;
plStringBuffer<wchar_t> buf = text.ToWchar();
bufs.push_back(buf);
TVITEM tvi = {0};
tvi.mask = TVIF_TEXT | TVIF_PARAM;
tvi.pszText = const_cast<LPWSTR>(buf.GetData());
tvi.cchTextMax = static_cast<int>(buf.GetSize());
tvi.lParam = NULL;
TVINSERTSTRUCT tvins = {0};
tvins.item = tvi;
tvins.hParent = hParent;
if (sort)
tvins.hInsertAfter = TVI_SORT;
else
tvins.hInsertAfter = TVI_LAST;
return TreeView_InsertItem(hTree, &tvins);
}
void plLocTreeView::FillTreeViewFromData(HWND treeCtrl, plString selectionPath)
void plLocTreeView::LoadData(const plString &selectionPath)
{
plString targetAge, targetSet, targetElement, targetLang;
SplitLocalizationPath(selectionPath, targetAge, targetSet, targetElement, targetLang);
@ -92,12 +58,13 @@ void plLocTreeView::FillTreeViewFromData(HWND treeCtrl, plString selectionPath)
for (int curAge = 0; curAge < ages.size(); curAge++)
{
// add the age to the tree
HTREEITEM ageItem = AddLeaf(treeCtrl, NULL, ages[curAge]);
QTreeWidgetItem *ageItem = new QTreeWidgetItem(this, QStringList { ages[curAge].c_str() });
ageItem->setData(0, kLocPathRole, QString(ages[curAge].c_str()));
if (ages[curAge] == targetAge)
{
TreeView_SelectItem(treeCtrl, ageItem);
TreeView_EnsureVisible(treeCtrl, ageItem);
setCurrentItem(ageItem);
scrollToItem(ageItem);
ageMatched = true;
}
else
@ -108,12 +75,13 @@ void plLocTreeView::FillTreeViewFromData(HWND treeCtrl, plString selectionPath)
{
std::vector<plString> elements = pfLocalizationDataMgr::Instance().GetElementList(ages[curAge], sets[curSet]);
HTREEITEM setItem = AddLeaf(treeCtrl, ageItem, sets[curSet]);
QTreeWidgetItem *setItem = new QTreeWidgetItem(ageItem, QStringList { sets[curSet].c_str() });
setItem->setData(0, kLocPathRole, QString("%1.%2").arg(ages[curAge].c_str()).arg(sets[curSet].c_str()));
if ((sets[curSet] == targetSet) && ageMatched)
{
TreeView_SelectItem(treeCtrl, setItem);
TreeView_EnsureVisible(treeCtrl, setItem);
setCurrentItem(setItem);
scrollToItem(setItem);
setMatched = true;
}
else
@ -121,12 +89,14 @@ void plLocTreeView::FillTreeViewFromData(HWND treeCtrl, plString selectionPath)
for (int curElement = 0; curElement < elements.size(); curElement++)
{
HTREEITEM subItem = AddLeaf(treeCtrl, setItem, elements[curElement]);
QTreeWidgetItem *subItem = new QTreeWidgetItem(setItem, QStringList { elements[curElement].c_str() });
subItem->setData(0, kLocPathRole, QString("%1.%2.%3").arg(ages[curAge].c_str())
.arg(sets[curSet].c_str()).arg(elements[curElement].c_str()));
if (elements[curElement] == targetElement && setMatched)
{
TreeView_SelectItem(treeCtrl, subItem);
TreeView_EnsureVisible(treeCtrl, subItem);
setCurrentItem(subItem);
scrollToItem(subItem);
elementMatched = true;
if (targetLang.IsEmpty())
@ -138,78 +108,27 @@ void plLocTreeView::FillTreeViewFromData(HWND treeCtrl, plString selectionPath)
std::vector<plString> languages = pfLocalizationDataMgr::Instance().GetLanguages(ages[curAge], sets[curSet], elements[curElement]);
for (int curLang = 0; curLang < languages.size(); curLang++)
{
HTREEITEM langItem = AddLeaf(treeCtrl, subItem, languages[curLang]);
QTreeWidgetItem *langItem = new QTreeWidgetItem(subItem, QStringList { languages[curLang].c_str() });
langItem->setData(0, kLocPathRole, QString("%1.%2.%3.%4").arg(ages[curAge].c_str())
.arg(sets[curSet].c_str()).arg(elements[curElement].c_str())
.arg(languages[curLang].c_str()));
if (languages[curLang] == targetLang && elementMatched)
{
TreeView_SelectItem(treeCtrl, langItem);
TreeView_EnsureVisible(treeCtrl, langItem);
setCurrentItem(langItem);
scrollToItem(langItem);
}
}
}
}
}
}
void plLocTreeView::ClearTreeView(HWND treeCtrl)
{
TreeView_DeleteAllItems(treeCtrl);
sortByColumn(0, Qt::AscendingOrder);
}
void plLocTreeView::SelectionChanged(HWND treeCtrl)
plString plLocTreeView::CurrentPath() const
{
HTREEITEM hItem = TreeView_GetSelection(treeCtrl);
std::vector<plString> path;
fPath = "";
while (hItem)
{
wchar_t s[200];
TVITEM tvi = {0};
tvi.hItem = hItem;
tvi.mask = TVIF_TEXT;
tvi.pszText = s;
tvi.cchTextMax = 200;
TreeView_GetItem(treeCtrl, &tvi);
path.push_back(plString::FromWchar(tvi.pszText));
hItem = TreeView_GetParent(treeCtrl, hItem);
}
while (!path.empty())
{
fPath += path.back();
path.pop_back();
if (!path.empty())
fPath += ".";
}
}
void plLocTreeView::SelectionDblClicked(HWND treeCtrl)
{
HTREEITEM hItem = TreeView_GetSelection(treeCtrl);
std::vector<plString> path;
fPath = "";
while (hItem)
{
wchar_t s[200];
TVITEM tvi = {0};
tvi.hItem = hItem;
tvi.mask = TVIF_TEXT;
tvi.pszText = s;
tvi.cchTextMax = 200;
TreeView_GetItem(treeCtrl, &tvi);
path.push_back(plString::FromWchar(tvi.pszText));
hItem = TreeView_GetParent(treeCtrl, hItem);
}
while (!path.empty())
{
fPath += path.back();
path.pop_back();
if (!path.empty())
fPath += ".";
}
return (currentItem() != nullptr)
? plString(currentItem()->data(0, kLocPathRole).toString().toUtf8().constData())
: plString();
}

19
Sources/Tools/plLocalizationEditor/plLocTreeView.h

@ -42,22 +42,21 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#ifndef _plLocTreeView_h
#define _plLocTreeView_h
#include "HeadSpin.h"
#include <QTreeWidget>
#include "plString.h"
class plLocTreeView
class plLocTreeView : public QTreeWidget
{
protected:
static plString fPath;
public:
static void FillTreeViewFromData(HWND treeCtrl, plString selectionPath);
static void ClearTreeView(HWND treeCtrl);
enum Roles
{
kLocPathRole = Qt::UserRole
};
static void SelectionChanged(HWND treeCtrl);
static void SelectionDblClicked(HWND treeCtrl);
plLocTreeView(QWidget *parent = nullptr) : QTreeWidget(parent) { }
static plString GetPath() {return fPath;}
void LoadData(const plString &path);
plString CurrentPath() const;
};
#endif //_plLocTreeView_h

339
Sources/Tools/plLocalizationEditor/plLocalizationEditor.cpp

@ -39,12 +39,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
Mead, WA 99021
*==LICENSE==*/
#define CLASSNAME L"plLocalizationEditor"
#define WINDOWNAME L"plLocalizationEditor"
#define IDC_REGTREEVIEW 1000
#define FILE_MENU_POS 0 // 0-based index of the file sub menu
#include "pnAllCreatables.h"
#include "plResMgr/plResMgrCreatable.h"
@ -57,340 +51,25 @@ REGISTER_CREATABLE(plAgeLoaded2Msg);
REGISTER_CREATABLE(plAgeBeginLoadingMsg);
REGISTER_CREATABLE(plInitialAgeStateLoadedMsg);
#include "pfLocalizationMgr/pfLocalizationMgr.h"
#include "pfLocalizationMgr/pfLocalizationDataMgr.h"
#include "plResMgr/plResManager.h"
#include "plLocTreeView.h"
#include <QApplication>
#include "plEditDlg.h"
#include "HeadSpin.h"
#include <commdlg.h>
#include <commctrl.h>
#include <shlwapi.h>
#include <shlobj.h>
#include "res/resource.h"
HINSTANCE gInstance = NULL;
HWND gMainWindow = NULL;
HWND gTreeView = NULL; // the tree view for display of localization strings
extern HWND gEditDlg; // the main edit dialog for the localization strings
std::wstring gCurPath = L""; // current data path
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
BOOL WinInit(HINSTANCE hInst, int nCmdShow);
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
int main(int argc, char *argv[])
{
MSG msg;
HACCEL accelTable = LoadAccelerators(hInst, MAKEINTRESOURCE(IDR_ACCELERATOR1));
if (!WinInit(hInst, nCmdShow))
return -1;
QApplication app(argc, argv);
app.setApplicationName("plLocalizationEditor");
app.setWindowIcon(QIcon(":/icon1.ico"));
plResManager *rMgr = new plResManager;
hsgResMgr::Init(rMgr);
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(gMainWindow, accelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
pfLocalizationMgr::Shutdown();
EditDialog editWin;
editWin.show();
int retn = app.exec();
hsgResMgr::Shutdown();
return 0;
}
BOOL WinInit(HINSTANCE hInst, int nCmdShow)
{
LoadLibrary(L"Riched20.dll"); // so we can use our rich edit control
gInstance = hInst;
WNDCLASSEX wcEx;
wcEx.cbSize = sizeof(WNDCLASSEX);
wcEx.style = CS_HREDRAW | CS_VREDRAW;
wcEx.lpfnWndProc = MainWndProc;
wcEx.cbClsExtra = 0;
wcEx.cbWndExtra = 0;
wcEx.hInstance = hInst;
wcEx.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_APPICON));
wcEx.hCursor = LoadCursor(NULL, IDC_ARROW);
wcEx.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
wcEx.lpszMenuName = MAKEINTRESOURCE(IDR_APPMENU);
wcEx.lpszClassName = CLASSNAME;
wcEx.hIconSm = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_APPICON), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
if (!RegisterClassEx(&wcEx))
return FALSE;
DWORD dwStyle = WS_POPUP | WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE;
DWORD dwExStyle = WS_EX_CONTROLPARENT;
// Create a window
gMainWindow = CreateWindowEx(dwExStyle, CLASSNAME, WINDOWNAME, dwStyle, 10, 10, 800, 500, NULL, NULL, hInst, NULL);
if (gMainWindow == NULL)
return FALSE;
return TRUE;
return retn;
}
void SetWindowTitle(HWND hWnd, std::wstring path)
{
std::wstring title = L"plLocalizationEditor";
if (path != L"")
title += L"-" + path;
SetWindowText(hWnd, title.c_str());
}
INT_PTR CALLBACK AboutDialogProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if(msg == WM_COMMAND)
EndDialog(hWnd, 0);
return 0;
}
void RequestSaveOnExit()
{
if (gCurPath == L"") // no data open
return;
static bool alreadyRequested = false; // make sure we don't ask multiple times
if (alreadyRequested)
return;
alreadyRequested = true;
SaveLocalizationText(); // make sure any changed text is saved to the manager
int res = MessageBox(NULL, L"Do you wish to save your changes?", L"Save Changes", MB_ICONQUESTION | MB_YESNO);
if (res == IDYES)
{
// save it to a new directory
BROWSEINFO bInfo;
LPITEMIDLIST itemList;
LPMALLOC shMalloc;
wchar_t path[MAX_PATH];
memset(&bInfo, 0, sizeof(bInfo));
bInfo.hwndOwner = NULL;
bInfo.pidlRoot = NULL;
bInfo.pszDisplayName = path;
bInfo.lpszTitle = L"Select a directory to save the localization data to:";
bInfo.ulFlags = BIF_EDITBOX;
itemList = SHBrowseForFolder(&bInfo);
if (itemList != NULL)
{
plWaitCursor waitCursor;
SHGetPathFromIDList(itemList, path);
SHGetMalloc(&shMalloc);
shMalloc->Free(itemList);
shMalloc->Release();
gCurPath = path;
char *sPath = hsWStringToString(gCurPath.c_str());
pfLocalizationDataMgr::Instance().WriteDatabaseToDisk(sPath);
delete [] sPath;
}
}
}
LRESULT CALLBACK HandleCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
switch (LOWORD(wParam))
{
case ID_FILE_EXIT:
RequestSaveOnExit();
PostQuitMessage(0);
break;
case ID_FILE_OPENDATADIRECTORY:
{
BROWSEINFO bInfo;
LPITEMIDLIST itemList;
LPMALLOC shMalloc;
wchar_t path[MAX_PATH];
memset(&bInfo, 0, sizeof(bInfo));
bInfo.hwndOwner = hWnd;
bInfo.pidlRoot = NULL;
bInfo.pszDisplayName = path;
bInfo.lpszTitle = L"Select a localization data directory:";
bInfo.ulFlags = BIF_USENEWUI | BIF_VALIDATE | BIF_RETURNONLYFSDIRS | BIF_NONEWFOLDERBUTTON;
itemList = SHBrowseForFolder(&bInfo);
if (itemList != NULL)
{
plWaitCursor waitCursor;
SHGetPathFromIDList(itemList, path);
SHGetMalloc(&shMalloc);
shMalloc->Free(itemList);
shMalloc->Release();
pfLocalizationMgr::Shutdown();
char *sPath = hsWStringToString(path);
pfLocalizationMgr::Initialize(sPath);
delete [] sPath;
plLocTreeView::ClearTreeView(gTreeView);
plLocTreeView::FillTreeViewFromData(gTreeView, "");
gCurPath = path;
SetWindowTitle(hWnd, path);
HMENU menu = GetMenu(hWnd);
HMENU fileMenu = GetSubMenu(menu, FILE_MENU_POS);
EnableMenuItem(fileMenu, ID_FILE_SAVETOCUR, MF_ENABLED);
EnableMenuItem(fileMenu, ID_FILE_SAVETONEW, MF_ENABLED);
}
}
break;
case ID_FILE_SAVETOCUR:
{
SaveLocalizationText(); // make sure any changed text is saved to the manager
// save it to our current directory
int res = MessageBox(hWnd, L"Are you sure you want to save to the current directory? Current data will be overwritten!", L"Save to Current Directory", MB_ICONQUESTION | MB_YESNOCANCEL);
if (res == IDYES)
{
plWaitCursor waitCursor;
char *sPath = hsWStringToString(gCurPath.c_str());
pfLocalizationDataMgr::Instance().WriteDatabaseToDisk(sPath);
delete [] sPath;
}
else if (res == IDNO)
SendMessage(hWnd, WM_COMMAND, (WPARAM)ID_FILE_SAVETONEW, (LPARAM)0);
// and if it's cancel we don't do anything
}
break;
case ID_FILE_SAVETONEW:
{
SaveLocalizationText(); // make sure any changed text is saved to the manager
// save it to a new directory
BROWSEINFO bInfo;
LPITEMIDLIST itemList;
LPMALLOC shMalloc;
wchar_t path[MAX_PATH];
memset(&bInfo, 0, sizeof(bInfo));
bInfo.hwndOwner = hWnd;
bInfo.pidlRoot = NULL;
bInfo.pszDisplayName = path;
bInfo.lpszTitle = L"Select a directory to save the localization data to:";
bInfo.ulFlags = BIF_EDITBOX;
itemList = SHBrowseForFolder(&bInfo);
if (itemList != NULL)
{
plWaitCursor waitCursor;
SHGetPathFromIDList(itemList, path);
SHGetMalloc(&shMalloc);
shMalloc->Free(itemList);
shMalloc->Release();
gCurPath = path;
SetWindowTitle(hWnd, path);
char *sPath = hsWStringToString(gCurPath.c_str());
pfLocalizationDataMgr::Instance().WriteDatabaseToDisk(sPath);
delete [] sPath;
}
}
break;
case ID_HELP_ABOUT:
DialogBox(gInstance, MAKEINTRESOURCE(IDD_ABOUT), hWnd, AboutDialogProc);
break;
}
return 0;
}
void SizeControls(HWND parent)
{
RECT clientRect, editRect;
GetClientRect(parent, &clientRect);
GetClientRect(gEditDlg, &editRect);
SetWindowPos(gTreeView, NULL, 0, 0, clientRect.right - editRect.right - 4, clientRect.bottom, 0);
OffsetRect(&editRect, clientRect.right - editRect.right, (clientRect.bottom >> 1) - (editRect.bottom >> 1));
SetWindowPos(gEditDlg, NULL, editRect.left, editRect.top, 0, 0, SWP_NOSIZE);
}
void InitWindowControls(HWND hWnd)
{
RECT clientRect;
GetClientRect(hWnd, &clientRect);
gTreeView = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TREEVIEW, L"Tree View", WS_VISIBLE | WS_CHILD | WS_BORDER |
TVS_HASLINES | TVS_HASBUTTONS | TVS_LINESATROOT | TVS_SHOWSELALWAYS,
0, 0, 0, 0, hWnd, (HMENU)IDC_REGTREEVIEW, gInstance, NULL);
gEditDlg = CreateDialog(gInstance, MAKEINTRESOURCE(IDD_EDITDLG), hWnd, EditDlgProc);
SizeControls(hWnd);
}
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CREATE:
InitCommonControls();
InitWindowControls(hWnd);
break;
case WM_CLOSE:
RequestSaveOnExit();
DestroyWindow(hWnd);
break;
case WM_DESTROY:
RequestSaveOnExit();
plLocTreeView::ClearTreeView(gTreeView);
PostQuitMessage(0);
break;
case WM_SIZING:
case WM_SIZE:
SizeControls(hWnd);
break;
case WM_GETMINMAXINFO:
{
MINMAXINFO* pmmi = (MINMAXINFO*)lParam;
pmmi->ptMinTrackSize.x = 800;
pmmi->ptMinTrackSize.y = 500;
return 0;
}
case WM_NOTIFY:
if(wParam == IDC_REGTREEVIEW)
{
SaveLocalizationText(); // save any current changes to the database
NMHDR *hdr = (NMHDR*)lParam;
if(hdr->code == TVN_SELCHANGED)
plLocTreeView::SelectionChanged(gTreeView);
else if(hdr->code == NM_DBLCLK)
plLocTreeView::SelectionDblClicked(gTreeView);
UpdateEditDlg(plLocTreeView::GetPath());
}
break;
case WM_COMMAND:
return HandleCommand(hWnd, wParam, lParam);
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
/* Enable themes in Windows XP and later */
#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

124
Sources/Tools/plLocalizationEditor/res/AddElement.ui

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AddElement</class>
<widget class="QDialog" name="AddElement">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>300</width>
<height>138</height>
</rect>
</property>
<property name="windowTitle">
<string>Add Element</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Path:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="fPathLabel"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Parent Age:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="fParentAge">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Parent Set:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="fParentSet">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Element Name:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="fElementName"/>
</item>
<item row="4" column="0" colspan="2">
<widget class="QDialogButtonBox" name="fButtons">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>fButtons</sender>
<signal>accepted()</signal>
<receiver>AddElement</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>fButtons</sender>
<signal>rejected()</signal>
<receiver>AddElement</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

91
Sources/Tools/plLocalizationEditor/res/AddLocalization.ui

@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AddLocalization</class>
<widget class="QDialog" name="AddLocalization">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>300</width>
<height>86</height>
</rect>
</property>
<property name="windowTitle">
<string>Add Localization</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Path:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="fPathLabel"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Language</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="fLanguage">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QDialogButtonBox" name="fButtons">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>fButtons</sender>
<signal>accepted()</signal>
<receiver>AddLocalization</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>fButtons</sender>
<signal>rejected()</signal>
<receiver>AddLocalization</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

178
Sources/Tools/plLocalizationEditor/res/EditDialog.ui

@ -0,0 +1,178 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>EditDialog</class>
<widget class="QMainWindow" name="EditDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>500</height>
</rect>
</property>
<property name="windowTitle">
<string>plLocalizationEditor</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="1,3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="plLocTreeView" name="fLocalizationTree">
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>10</number>
</property>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Localization Tree</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="fAddButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Add</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="fDeleteButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Delete</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Localization Information</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="fTextPathLabel">
<property name="text">
<string>Text:</string>
</property>
</widget>
</item>
<item>
<widget class="QPlainTextEdit" name="fLocalizationText"/>
</item>
</layout>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>21</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>&amp;File</string>
</property>
<addaction name="fOpenAction"/>
<addaction name="separator"/>
<addaction name="fSaveCurrentAction"/>
<addaction name="fSaveOtherAction"/>
<addaction name="separator"/>
<addaction name="fExitAction"/>
</widget>
<widget class="QMenu" name="menu_Help">
<property name="title">
<string>&amp;Help</string>
</property>
<addaction name="fAboutAction"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menu_Help"/>
</widget>
<action name="fOpenAction">
<property name="text">
<string>&amp;Open Data Directory...</string>
</property>
<property name="shortcut">
<string>Ctrl+O</string>
</property>
</action>
<action name="fSaveCurrentAction">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>&amp;Save to Current Directory</string>
</property>
<property name="shortcut">
<string>Ctrl+S</string>
</property>
</action>
<action name="fSaveOtherAction">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>S&amp;ave to Specified Directory...</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+S</string>
</property>
</action>
<action name="fExitAction">
<property name="text">
<string>E&amp;xit</string>
</property>
</action>
<action name="fAboutAction">
<property name="text">
<string>&amp;About</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
<class>plLocTreeView</class>
<extends>QTreeWidget</extends>
<header>plLocTreeView.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

5
Sources/Tools/plLocalizationEditor/res/plLocalizationEditor.qrc

@ -0,0 +1,5 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>icon1.ico</file>
</qresource>
</RCC>

268
Sources/Tools/plLocalizationEditor/res/plLocalizationEditor.rc

@ -1,268 +0,0 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#define APSTUDIO_HIDDEN_SYMBOLS
#include "windows.h"
#undef APSTUDIO_HIDDEN_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_APPICON ICON "icon1.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
IDR_APPMENU MENU
BEGIN
POPUP "&File"
BEGIN
MENUITEM "&Open Data Directory...\tCtrl+O",
ID_FILE_OPENDATADIRECTORY
MENUITEM SEPARATOR
MENUITEM "&Save to Current Directory\tCtrl+S", ID_FILE_SAVETOCUR
, GRAYED
MENUITEM "S&ave to Specified Directory...\tCtrl+Shift+S",
ID_FILE_SAVETONEW, GRAYED
MENUITEM SEPARATOR
MENUITEM "E&xit", ID_FILE_EXIT
END
POPUP "&Help"
BEGIN
MENUITEM "&About ...", ID_HELP_ABOUT
END
END
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_ABOUT DIALOGEX 0, 0, 275, 40
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION |
WS_SYSMENU
CAPTION "About plLocalizationEditor"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,221,6,50,14
ICON IDI_APPICON,IDC_STATIC,7,7,21,20
LTEXT "plLocalizationEditor\nA basic editor for Plasma 21 localization resource files\nCopyright (C) 2004 Cyan Worlds, Inc.",
IDC_STATIC,33,7,180,26
END
IDD_EDITDLG DIALOGEX 0, 0, 421, 280
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
PUSHBUTTON "Add",IDC_ADD,72,20,138,14,WS_DISABLED
PUSHBUTTON "Delete",IDC_DELETE,216,20,132,14,WS_DISABLED
GROUPBOX "Localization Tree",IDC_STATIC,7,7,407,32
GROUPBOX "Localization Information",IDC_STATIC,7,45,407,228
LTEXT "Text:",IDC_LOCPATH,15,57,391,8
CONTROL "",IDC_LOCALIZATIONTEXT,"RichEdit20A",ES_MULTILINE |
ES_AUTOHSCROLL | WS_DISABLED | WS_BORDER | WS_VSCROLL |
WS_HSCROLL | WS_TABSTOP,15,71,391,194
END
IDD_ADDELEMENT DIALOGEX 0, 0, 186, 91
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION |
WS_SYSMENU
CAPTION "Add Element"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
COMBOBOX IDC_PARENTAGE,57,19,122,51,CBS_DROPDOWN | CBS_SORT |
WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_PARENTSET,57,34,122,51,CBS_DROPDOWN | CBS_SORT |
WS_VSCROLL | WS_TABSTOP
EDITTEXT IDC_ELEMENTNAME,57,49,122,14,ES_AUTOHSCROLL
DEFPUSHBUTTON "OK",IDOK,129,70,50,14
PUSHBUTTON "Cancel",IDCANCEL,73,70,50,14
LTEXT "Path:",IDC_PATH,7,7,172,8
LTEXT "Parent Age:",IDC_STATIC,7,22,48,8
LTEXT "Parent Set:",IDC_STATIC,7,37,38,8
LTEXT "Element Name:",IDC_STATIC,7,52,49,8
END
IDD_ADDLOCALIZATION DIALOGEX 0, 0, 186, 59
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION |
WS_SYSMENU
CAPTION "Add Localization"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
COMBOBOX IDC_LANGUAGE,45,19,134,65,CBS_DROPDOWNLIST | CBS_SORT |
WS_VSCROLL | WS_TABSTOP
DEFPUSHBUTTON "OK",IDOK,129,38,50,14
PUSHBUTTON "Cancel",IDCANCEL,73,38,50,14
LTEXT "Path:",IDC_PATH,7,7,172,8
LTEXT "Language:",IDC_STATIC,7,21,35,8
END
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,1
PRODUCTVERSION 1,0,0,1
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Cyan Worlds, Inc."
VALUE "FileDescription", "plLocalizationEditor"
VALUE "FileVersion", "1, 0, 0, 1"
VALUE "InternalName", "plLocalizationEditor"
VALUE "LegalCopyright", "Copyright © 2004"
VALUE "OriginalFilename", "plLocalizationEditor.exe"
VALUE "ProductName", "Cyan Worlds Localization Editor"
VALUE "ProductVersion", "1, 0, 0, 1"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
"#include ""windows.h""\r\n"
"#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_ABOUT, DIALOG
BEGIN
RIGHTMARGIN, 252
END
IDD_EDITDLG, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 414
VERTGUIDE, 15
VERTGUIDE, 72
VERTGUIDE, 210
VERTGUIDE, 216
VERTGUIDE, 348
VERTGUIDE, 406
TOPMARGIN, 7
BOTTOMMARGIN, 273
HORZGUIDE, 71
HORZGUIDE, 265
END
IDD_ADDELEMENT, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 179
TOPMARGIN, 7
BOTTOMMARGIN, 84
END
IDD_ADDLOCALIZATION, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 179
TOPMARGIN, 7
BOTTOMMARGIN, 52
END
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Accelerator
//
IDR_ACCELERATOR1 ACCELERATORS
BEGIN
"O", ID_FILE_OPENDATADIRECTORY, VIRTKEY, CONTROL, NOINVERT
"S", ID_FILE_SAVETOCUR, VIRTKEY, CONTROL, NOINVERT
"S", ID_FILE_SAVETONEW, VIRTKEY, SHIFT, CONTROL,
NOINVERT
END
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

51
Sources/Tools/plLocalizationEditor/res/resource.h

@ -1,51 +0,0 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by plLocalizationEditor.rc
//
#define IDC_MYICON 2
#define IDI_APPICON 102
#define IDD_PLLOCALIZATIONEDITOR_DIALOG 102
#define IDS_APP_TITLE 103
#define IDD_ABOUTBOX 103
#define IDI_PLLOCALIZATIONEDITOR 107
#define IDI_SMALL 108
#define IDC_PLLOCALIZATIONEDITOR 109
#define IDR_APPMENU 109
#define IDD_ADDELEMENT 113
#define IDD_ADDLOCALIZATION 114
#define IDR_MAINFRAME 128
#define IDD_ABOUT 129
#define IDR_ACCELERATOR1 130
#define IDD_EDITDLG 131
#define IDC_RICHEDIT21 1000
#define IDC_LOCALIZATIONTEXT 1002
#define IDC_APPLY 1014
#define IDC_DISCARD 1015
#define IDC_LOCPATH 1019
#define IDC_ADD 1020
#define IDC_DELETE 1021
#define IDC_PATH 1023
#define IDC_PARENTSET 1026
#define IDC_ELEMENTNAME 1027
#define IDC_PARENTAGE 1028
#define IDC_LANGUAGE 1028
#define ID_FILE_EXIT 32772
#define ID_HELP_ABOUT 32773
#define ID_FILE_OPENDATADIRECTORY 32774
#define ID_FILE_SAVETOSPECIFIEDDIRECTORY 32778
#define ID_FILE_SAVETOCURRENTDIRECTORY 32779
#define ID_FILE_SAVETOCUR 32782
#define ID_FILE_SAVETONEW 32783
#define IDC_STATIC -1
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC 1
#define _APS_NEXT_RESOURCE_VALUE 132
#define _APS_NEXT_COMMAND_VALUE 32784
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 110
#endif
#endif
Loading…
Cancel
Save