You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
380 lines
13 KiB
380 lines
13 KiB
/*==LICENSE==* |
|
|
|
CyanWorlds.com Engine - MMOG client, server and tools |
|
Copyright (C) 2011 Cyan Worlds, Inc. |
|
|
|
This program is free software: you can redistribute it and/or modify |
|
it under the terms of the GNU General Public License as published by |
|
the Free Software Foundation, either version 3 of the License, or |
|
(at your option) any later version. |
|
|
|
This program is distributed in the hope that it will be useful, |
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
GNU General Public License for more details. |
|
|
|
You should have received a copy of the GNU General Public License |
|
along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
|
|
Additional permissions under GNU GPL version 3 section 7 |
|
|
|
If you modify this Program, or any covered work, by linking or |
|
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, |
|
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent |
|
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK |
|
(or a modified version of those libraries), |
|
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, |
|
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG |
|
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the |
|
licensors of this Program grant you additional |
|
permission to convey the resulting work. Corresponding Source for a |
|
non-source form of such a combination shall include the source code for |
|
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered |
|
work. |
|
|
|
You can contact Cyan Worlds, Inc. by email legal@cyan.com |
|
or by snail mail at: |
|
Cyan Worlds, Inc. |
|
14617 N Newport Hwy |
|
Mead, WA 99021 |
|
|
|
*==LICENSE==*/ |
|
// Basic edit dialog stuff |
|
#include "plEditDlg.h" |
|
#include "plLocTreeView.h" |
|
#include "plAddDlgs.h" |
|
|
|
#include "pfLocalizationMgr/pfLocalizationMgr.h" |
|
#include "pfLocalizationMgr/pfLocalizationDataMgr.h" |
|
|
|
#include <QDialog> |
|
#include <QMessageBox> |
|
#include <QFileDialog> |
|
#include "ui_EditDialog.h" |
|
|
|
#include <functional> |
|
|
|
static void IAboutDialog(QWidget *parent) |
|
{ |
|
QDialog dlg(parent); |
|
QLabel *image = new QLabel(&dlg); |
|
image->setPixmap(QPixmap(":/icon1.ico")); |
|
QLabel *text = new QLabel(QObject::tr(R"(plLocalizationEditor |
|
A basic editor for Plasma 21 localization resource files |
|
Copyright (C) 2004 Cyan Worlds, Inc.)"), &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(); |
|
} |
|
|
|
EditDialog::EditDialog() |
|
: fEditMode(kEditNothing) |
|
{ |
|
fUI = new Ui_EditDialog; |
|
fUI->setupUi(this); |
|
|
|
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)); |
|
|
|
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); |
|
} |
|
|
|
EditDialog::~EditDialog() |
|
{ |
|
pfLocalizationMgr::Shutdown(); |
|
delete fUI; |
|
} |
|
|
|
// saves the current localization text to the data manager |
|
void EditDialog::SaveLocalizationText() |
|
{ |
|
if (fCurrentLocPath.IsEmpty()) |
|
return; // no path to save |
|
|
|
plString text = fUI->fLocalizationText->toPlainText().toUtf8().constData(); |
|
|
|
plString ageName, setName, elementName, elementLanguage; |
|
SplitLocalizationPath(fCurrentLocPath, ageName, setName, elementName, elementLanguage); |
|
|
|
if (ageName.IsEmpty() || setName.IsEmpty() || elementName.IsEmpty() || elementLanguage.IsEmpty()) |
|
return; |
|
|
|
plString name = plFormat("{}.{}.{}", ageName, setName, elementName); |
|
pfLocalizationDataMgr::Instance().SetElementPlainTextData(name, elementLanguage, text); |
|
} |
|
|
|
void EditDialog::LoadLocalization(const plString &locPath) |
|
{ |
|
if (locPath == fCurrentLocPath) |
|
return; |
|
|
|
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 |
|
EnableEdit(false); |
|
else |
|
{ |
|
EnableEdit(true); |
|
plString key = plFormat("{}.{}.{}", ageName, setName, elementName); |
|
plString elementText = pfLocalizationDataMgr::Instance().GetElementPlainTextData(key, elementLanguage); |
|
fUI->fLocalizationText->setPlainText(elementText.c_str()); |
|
} |
|
|
|
// now to setup the add/delete buttons |
|
if (!elementLanguage.IsEmpty()) // they have selected a language |
|
{ |
|
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 |
|
{ |
|
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); |
|
|
|
// they can't delete the only subtitle in a set |
|
fUI->fDeleteButton->setEnabled(elementNames.size() > 1); |
|
} |
|
else |
|
fUI->fDeleteButton->setEnabled(false); |
|
} |
|
} |
|
|
|
void EditDialog::EnableEdit(bool enable) |
|
{ |
|
if (!enable) |
|
fUI->fLocalizationText->setPlainText(""); |
|
|
|
fUI->fLocalizationText->setEnabled(enable); |
|
} |
|
|
|
void EditDialog::closeEvent(QCloseEvent *event) |
|
{ |
|
if (fCurrentSavePath.isEmpty()) // no data open |
|
{ |
|
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()) |
|
{ |
|
plString path = dlg.GetValue(); // path is age.set.name |
|
if (!pfLocalizationDataMgr::Instance().AddElement(path)) |
|
{ |
|
QMessageBox::critical(this, tr("Error"), |
|
tr("Couldn't add new element because one already exists with that name!")); |
|
} |
|
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 = plFormat("{}.{}.{}", ageName, setName, elementName); |
|
if (!pfLocalizationDataMgr::Instance().AddLocalization(key, newLanguage)) |
|
QMessageBox::critical(this, tr("Error"), tr("Couldn't add additional localization!")); |
|
else |
|
{ |
|
plString path = plFormat("{}.{}", key, newLanguage); |
|
fCurrentLocPath = ""; |
|
fUI->fLocalizationTree->clear(); |
|
fUI->fLocalizationTree->LoadData(path); |
|
LoadLocalization(path); |
|
} |
|
} |
|
} |
|
} |
|
|
|
void EditDialog::DeleteClicked() |
|
{ |
|
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) |
|
{ |
|
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) |
|
{ |
|
plString ageName, setName, elementName, elementLanguage; |
|
SplitLocalizationPath(fCurrentLocPath, ageName, setName, elementName, elementLanguage); |
|
plString key = plFormat("{}.{}.{}", ageName, setName, elementName); |
|
if (!pfLocalizationDataMgr::Instance().DeleteLocalization(key, elementLanguage)) |
|
QMessageBox::critical(this, tr("Error"), tr("Couldn't delete localization!")); |
|
else |
|
{ |
|
plString path = key + ".English"; |
|
fCurrentLocPath = ""; |
|
fUI->fLocalizationTree->clear(); |
|
fUI->fLocalizationTree->LoadData(path); |
|
LoadLocalization(path); |
|
} |
|
} |
|
} |
|
} |
|
|
|
// 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]; |
|
}
|
|
|