Changed: #1307 Added extraction words options for: item, creature, sbrick, sphrase

--HG--
branch : gsoc2011-translationovqt
This commit is contained in:
cemycc 2011-07-05 05:01:13 +03:00
parent e55bbed5b4
commit a4f222c651
15 changed files with 835 additions and 1028 deletions

View file

@ -13,7 +13,9 @@ SET(OVQT_PLUG_TRANSLATION_MANAGER_HDR translation_manager_plugin.h
translation_manager_main_window.h
translation_manager_settings_page.h
translation_manager_editor.h
editor_worksheet.h)
editor_worksheet.h
extract_new_sheet_names.h
extract_bot_names.h)
SET(OVQT_PLUG_TRANSLATION_MANAGER_UIS translation_manager_settings_page.ui
translation_manager_main_window.ui)

View file

@ -1,6 +1,6 @@
// Object Viewer Qt - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Translation Manager Plugin - OVQT Plugin <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
// Copyright (C) 2011 Dzmitry Kamiahin <dnk-88@tut.by>
// Copyright (C) 2011 Emanuel Costea <cemycc@gmail.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
@ -24,22 +24,10 @@
#include <QtGui/QMessageBox>
#include <QtGui/QCloseEvent>
#include "extract_bot_names.h"
using namespace std;
struct TEntryInfo
{
string SheetName;
};
set<string> getGenericNames();
void cleanGenericNames();
map<string, TEntryInfo> getSimpleNames();
void cleanSimpleNames();
void setPathsForPrimitives(map<string,list<string> > config_paths, string ligo_class_file);
void extractBotNamesFromPrimitives();
string cleanupName(const std::string &name);
ucstring cleanupUcName(const ucstring &name);
namespace Plugin {
@ -251,12 +239,15 @@ void CEditorWorksheet::worksheetEditorChanged(int row, int column)
}
void CEditorWorksheet::extractBotNames()
void CEditorWorksheet::extractBotNames(list<string> filters, string level_design_path, NLLIGO::CLigoConfig ligoConfig)
{
bool modified = false;
// get SimpleNames
ExtractBotNames ebn;
ebn.setRequiredSettings(filters, level_design_path);
ebn.extractBotNamesFromPrimitives(ligoConfig);
// get SimpleNames
{
map<string, TEntryInfo> SimpleNames = getSimpleNames();
map<string, TEntryInfo> SimpleNames = ebn.getSimpleNames();
map<string, TEntryInfo>::iterator it(SimpleNames.begin()), last(SimpleNames.end());
for (; it != last; ++it)
@ -281,15 +272,15 @@ void CEditorWorksheet::extractBotNames()
if(!modified) modified = true;
}
}
cleanSimpleNames();
ebn.cleanSimpleNames();
}
// get GenericNames
{
set<string> GenericNames = getGenericNames();
set<string> GenericNames = ebn.getGenericNames();
set<string>::iterator it(GenericNames.begin()), last(GenericNames.end());
for (; it != last; ++it)
{
string gnName = "gn_" + cleanupName(*it);
string gnName = "gn_" + ebn.cleanupName(*it);
QList<QTableWidgetItem*> search_results = table_editor->findItems(tr((*it).c_str()), Qt::MatchExactly);
if(search_results.size() == 0)
{
@ -310,7 +301,7 @@ void CEditorWorksheet::extractBotNames()
if(!modified) modified = true;
}
}
cleanGenericNames();
ebn.cleanGenericNames();
}
if(modified)
{
@ -319,6 +310,77 @@ void CEditorWorksheet::extractBotNames()
}
void CEditorWorksheet::extractWords(QString filename, QString columnId, IWordListBuilder& wordListBuilder)
{
uint i;
// **** Load the excel sheet
// load
TWorksheet workSheet;
if(!loadExcelSheet(filename.toStdString(), workSheet, true))
{
nlwarning("Error reading '%s'. Aborted", filename.toStdString().c_str());
return;
}
// get the key column index
uint keyColIndex = 0;
if(!workSheet.findCol(columnId.toStdString(), keyColIndex))
{
nlwarning("Error: Don't find the column '%s'. '%s' Aborted", columnId.toStdString().c_str(), filename.toStdString().c_str());
return;
}
// get the name column index
uint nameColIndex;
if(!workSheet.findCol(ucstring("name"), nameColIndex))
{
nlwarning("Error: Don't find the column 'name'. '%s' Aborted", filename.toStdString().c_str());
return;
}
// **** List all words with the builder given
std::vector<string> allWords;
if(!wordListBuilder.buildWordList(allWords, filename.toStdString()))
{
return;
}
bool modified = false;
for(i = 0; i < allWords.size(); i++)
{
string keyName = allWords[i];
QList<QTableWidgetItem*> search_results = table_editor->findItems(tr(keyName.c_str()), Qt::MatchExactly);
if(search_results.size() == 0)
{
int knPos = 0, nPos = 0;
if(workSheet.getData(0, 0) == ucstring("*HASH_VALUE"))
{
knPos = keyColIndex - 1;
nPos = nameColIndex - 1;
} else {
knPos = keyColIndex;
nPos = nameColIndex;
}
const int currentRow = table_editor->rowCount();
table_editor->setRowCount(currentRow + 1);
// keyName row
QTableWidgetItem *key_name_row = new QTableWidgetItem();
key_name_row->setText(tr(keyName.c_str()));
key_name_row->setBackgroundColor(QColor("#F75D59"));
table_editor ->setItem(currentRow, knPos, key_name_row);
// nameColumn key
QTableWidgetItem *name_row = new QTableWidgetItem();
name_row->setText(QString("<GEN>") + tr(keyName.c_str()));
name_row->setBackgroundColor(QColor("#F75D59"));
table_editor ->setItem(currentRow, nPos, name_row);
if(!modified) modified = true;
}
}
if(modified)
{
setWindowModified(true);
}
}
void CEditorWorksheet::setCurrentFile(QString filename)
{
QFileInfo *file = new QFileInfo(filename);

View file

@ -1,3 +1,19 @@
// Translation Manager Plugin - OVQT Plugin <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
// Copyright (C) 2011 Emanuel Costea <cemycc@gmail.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef EDITOR_WORKSHEET_H
#define EDITOR_WORKSHEET_H
@ -7,6 +23,7 @@
#include "nel/misc/sheet_id.h"
#include "nel/misc/path.h"
#include "nel/misc/diff_tool.h"
#include "nel/ligo/ligo_config.h"
// Qt includes
#include <QtCore/QObject>
@ -16,6 +33,7 @@
#include <QtGui/QMdiSubWindow>
#include "translation_manager_editor.h"
#include "extract_new_sheet_names.h"
namespace Plugin {
@ -31,7 +49,8 @@ public:
void save();
void saveAs(QString filename);
void activateWindow();
void extractBotNames();
void extractBotNames(list<string> filters, string level_design_path, NLLIGO::CLigoConfig ligoConfig);
void extractWords(QString filename, QString columnId, IWordListBuilder &wordListBuilder);
bool isBotNamesTable();
void closeEvent(QCloseEvent *event);
private Q_SLOTS:

View file

@ -1,5 +1,6 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Translation Manager Plugin - OVQT Plugin <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
// Copyright (C) 2011 Emanuel Costea <cemycc@gmail.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
@ -14,67 +15,18 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "nel/misc/types_nl.h"
#include "nel/misc/config_file.h"
#include "nel/misc/sheet_id.h"
#include "nel/misc/path.h"
#include "nel/misc/diff_tool.h"
#include "nel/georges/u_form.h"
#include "nel/georges/u_form_elm.h"
#include "nel/georges/load_form.h"
#include "nel/ligo/ligo_config.h"
#include "nel/ligo/primitive.h"
#include "nel/ligo/primitive_utils.h"
#include "extract_bot_names.h"
using namespace std;
using namespace NLMISC;
using namespace NLLIGO;
using namespace STRING_MANAGER;
vector<string> Filters;
static CLigoConfig LigoConfig;
static bool RemoveOlds = false;
struct TCreatureInfo
namespace Plugin
{
CSheetId SheetId;
bool ForceSheetName;
bool DisplayName;
void readGeorges (const NLMISC::CSmartPtr<NLGEORGES::UForm> &form, const NLMISC::CSheetId &sheetId)
{
const NLGEORGES::UFormElm &item=form->getRootNode();
SheetId=sheetId;
item.getValueByName(ForceSheetName, "3d data.ForceDisplayCreatureName");
item.getValueByName(DisplayName, "3d data.DisplayName");
}
void serial(NLMISC::IStream &f)
{
f.serial(SheetId);
f.serial(ForceSheetName);
f.serial(DisplayName);
}
static uint getVersion ()
{
return 1;
}
void removed()
{
}
};
std::map<CSheetId, TCreatureInfo> Creatures;
TCreatureInfo *getCreature(const std::string &sheetName)
TCreatureInfo *ExtractBotNames::getCreature(const std::string &sheetName)
{
CSheetId id(sheetName+".creature");
@ -84,7 +36,7 @@ TCreatureInfo *getCreature(const std::string &sheetName)
return NULL;
}
string cleanupName(const std::string &name)
string ExtractBotNames::cleanupName(const std::string &name)
{
string ret;
@ -99,7 +51,7 @@ string cleanupName(const std::string &name)
return ret;
}
ucstring cleanupUcName(const ucstring &name)
ucstring ExtractBotNames::cleanupUcName(const ucstring &name)
{
ucstring ret;
@ -118,7 +70,7 @@ ucstring cleanupUcName(const ucstring &name)
/*
Removes first and last '$'
*/
ucstring makeGroupName(const ucstring & translationName)
ucstring ExtractBotNames::makeGroupName(const ucstring & translationName)
{
ucstring ret = translationName;
if (ret.size() >= 2)
@ -136,36 +88,31 @@ ucstring makeGroupName(const ucstring & translationName)
return ret;
}
struct TEntryInfo
{
string SheetName;
};
set<string> GenericNames;
map<string, TEntryInfo> SimpleNames;
set<string> Functions;
set<string> getGenericNames()
set<string> ExtractBotNames::getGenericNames()
{
return GenericNames;
}
map<string, TEntryInfo> getSimpleNames()
map<string, TEntryInfo> ExtractBotNames::getSimpleNames()
{
return SimpleNames;
}
void cleanSimpleNames()
void ExtractBotNames::cleanSimpleNames()
{
SimpleNames.clear();
}
void cleanGenericNames()
void ExtractBotNames::cleanGenericNames()
{
GenericNames.clear();
}
string removeAndStoreFunction(const std::string &fullName)
string ExtractBotNames::removeAndStoreFunction(const std::string &fullName)
{
string::size_type pos = fullName.find("$");
if (pos == string::npos)
@ -193,7 +140,7 @@ string removeAndStoreFunction(const std::string &fullName)
}
void addGenericName(const std::string &name, const std::string &sheetName)
void ExtractBotNames::addGenericName(const std::string &name, const std::string &sheetName)
{
TCreatureInfo *c = getCreature(sheetName);
if (!c || c->ForceSheetName || !c->DisplayName)
@ -213,7 +160,7 @@ void addGenericName(const std::string &name, const std::string &sheetName)
}
}
void addSimpleName(const std::string &name, const std::string &sheetName)
void ExtractBotNames::addSimpleName(const std::string &name, const std::string &sheetName)
{
TCreatureInfo *c = getCreature(sheetName);
if (!c || c->ForceSheetName || !c->DisplayName)
@ -238,18 +185,9 @@ void addSimpleName(const std::string &name, const std::string &sheetName)
}
}
void setPathsForPrimitives(map<string,list<string> > config_paths, string ligo_class_file)
void ExtractBotNames::setRequiredSettings(list<string> filters, string level_design_path)
{
for (std::list<string>::iterator it = config_paths["paths"].begin(); it != config_paths["paths"].end(); ++it)
{
CPath::addSearchPath(*it, true, false);
}
for (std::list<string>::iterator it = config_paths["pathsR"].begin(); it != config_paths["pathsR"].end(); ++it)
{
CPath::addSearchPath(*it, false, false);
}
for (std::list<string>::iterator it = config_paths["filters"].begin(); it != config_paths["filters"].end(); ++it)
for (std::list<string>::iterator it = filters.begin(); it != filters.end(); ++it)
{
Filters.push_back(*it);
}
@ -262,35 +200,28 @@ void setPathsForPrimitives(map<string,list<string> > config_paths, string ligo_c
if (Creatures.empty())
{
for (std::list<string>::iterator it = config_paths["georges"].begin(); it != config_paths["georges"].end(); ++it)
CPath::addSearchPath((*it).c_str(), true, false);
loadForm("creature", PACKED_SHEETS_NAME, Creatures, true);
loadForm("creature", PACKED_SHEETS_NAME, Creatures, true);
}
//-------------------------------------------------------------------
// init ligo config
string ligoPath = CPath::lookup(ligo_class_file, true, true);
LigoConfig.readPrimitiveClass(ligoPath.c_str(), false);
NLLIGO::Register();
CPrimitiveContext::instance().CurrentLigoConfig = &LigoConfig;
}
void extractBotNamesFromPrimitives()
void ExtractBotNames::extractBotNamesFromPrimitives(CLigoConfig ligoConfig)
{
//-------------------------------------------------------------------
// ok, ready for the real work,
// first, read the primitives files and parse the primitives
vector<string> files;
CPath::getFileList("primitive", files);
for (uint i=0; i<files.size(); ++i)
{
string pathName = files[i];
pathName = CPath::lookup(pathName);
// check filters
uint j=0;
for (j=0; j<Filters.size(); ++j)
@ -306,7 +237,7 @@ void extractBotNamesFromPrimitives()
CPrimitives primDoc;
CPrimitiveContext::instance().CurrentPrimitive = &primDoc;
loadXmlPrimitiveFile(primDoc, pathName, LigoConfig);
loadXmlPrimitiveFile(primDoc, pathName, ligoConfig);
// now parse the file
@ -444,341 +375,5 @@ void extractBotNamesFromPrimitives()
}
}
}
int extractBotNamesAll(map<string,list<string> > config_paths, string ligo_class_file, string trans_path, string work_path)
{
/*
//-------------------------------------------------------------------
// step 2 : load the reference file
nlinfo("Looking for missing translation:");
string work_path_file = work_path + "/bot_names.txt";
string trans_path_file = trans_path + "/bot_names.txt";
string title_path_file = work_path + "/title_words_wk.txt";
TWorksheet botNames;
if (!CFile::fileExists(work_path_file) || !loadExcelSheet(work_path_file, botNames))
{
botNames.resize(botNames.size() + 1);
botNames.insertColumn(botNames.ColCount);
botNames.setData(0,botNames.ColCount - 1,ucstring("bot name"));
botNames.insertColumn(botNames.ColCount);
botNames.setData(0,botNames.ColCount - 1,ucstring("translated name"));
botNames.insertColumn(botNames.ColCount);
botNames.setData(0,botNames.ColCount - 1,ucstring("sheet_name"));
}
TWorksheet transBotNames;
if (!CFile::fileExists(trans_path_file) || !loadExcelSheet(trans_path_file, transBotNames))
{
transBotNames.resize(transBotNames.size() + 1);
transBotNames.insertColumn(transBotNames.ColCount);
transBotNames.setData(0,transBotNames.ColCount - 1,ucstring("*HASH_VALUE"));
transBotNames.insertColumn(transBotNames.ColCount);
transBotNames.setData(0,transBotNames.ColCount - 1,ucstring("bot name"));
transBotNames.insertColumn(transBotNames.ColCount);
transBotNames.setData(0,transBotNames.ColCount - 1,ucstring("translated name"));
transBotNames.insertColumn(transBotNames.ColCount);
transBotNames.setData(0,transBotNames.ColCount - 1,ucstring("sheet_name"));
}
TWorksheet fcts;
if (!CFile::fileExists(title_path_file) || !loadExcelSheet(title_path_file, fcts))
{
fcts.resize(fcts.size() + 1);
fcts.insertColumn(fcts.ColCount);
fcts.setData(0,fcts.ColCount - 1,ucstring("title_id"));
fcts.insertColumn(fcts.ColCount);
fcts.setData(0,fcts.ColCount - 1,ucstring("name"));
fcts.insertColumn(fcts.ColCount);
fcts.setData(0,fcts.ColCount - 1,ucstring("women_name"));
}
loadExcelSheet(work_path_file, botNames, true);
loadExcelSheet(trans_path_file, transBotNames, true);
loadExcelSheet(title_path_file, fcts, true);
// add missing element
uint nbAddSimpleName = 0;
uint nbAddFunction = 0;
uint nbAddGenericName = 0;
uint botIdCol;
nlverify(botNames.findId(botIdCol));
uint transIdCol;
nlverify(transBotNames.findId(transIdCol));
uint fctsIdCol;
nlverify(fcts.findId(fctsIdCol));
// special treatment to add the sheet_name col
{
uint sheetCol;
if (!botNames.findCol(ucstring("sheet_name"), sheetCol))
{
botNames.insertColumn(botNames.ColCount);
botNames.setData(0, botNames.ColCount-1, ucstring("sheet_name"));
}
if (!transBotNames.findCol(ucstring("sheet_name"), sheetCol))
{
transBotNames.insertColumn(transBotNames.ColCount);
transBotNames.setData(0, transBotNames.ColCount-1, ucstring("sheet_name"));
}
}
// 1 - simple names
{
nlinfo(" Simple names...");
map<string, TEntryInfo>::iterator first(SimpleNames.begin()), last(SimpleNames.end());
for (; first != last; ++first)
{
uint rowIdx;
if (!botNames.findRow(botIdCol, first->first, rowIdx))
{
// we need to add the entry
rowIdx = botNames.size();
botNames.resize(botNames.size()+1);
botNames.setData(rowIdx, ucstring("bot name"), first->first);
botNames.setData(rowIdx, ucstring("translated name"), first->first);
botNames.setData(rowIdx, ucstring("sheet_name"), first->second.SheetName);
nbAddSimpleName++;
}
else
{
// set/update the sheet name info
// try to restore the existing translation
uint transRowIdx;
if (transBotNames.findRow(transIdCol, first->first, transRowIdx))
{
ucstring wkBotName = botNames.getData(rowIdx, ucstring("bot name"));
ucstring wkSheetName = botNames.getData(rowIdx, ucstring("sheet_name"));
ucstring wkTranslationName = botNames.getData(rowIdx, ucstring("translated name"));
ucstring ucWkHash;
uint64 hash = CI18N::makeHash(wkBotName + wkTranslationName +wkSheetName);
CI18N::hashToUCString(hash, ucWkHash);
ucstring trUcHash = transBotNames[transRowIdx][0];
bool isWkTranslationNameAGroupName = wkTranslationName.find(ucstring("$")) != ucstring::npos;
bool hashIsValide = std::equal(ucWkHash.begin(), ucWkHash.end(), trUcHash.begin()+1);
// Hash is equal get the translation
if (hashIsValide && !isWkTranslationNameAGroupName)
{
wkTranslationName = transBotNames.getData(transRowIdx, ucstring("translated name"));
wkSheetName = transBotNames.getData(transRowIdx, ucstring("sheet_name"));
botNames.setData(rowIdx, ucstring("translated name"), wkTranslationName);
botNames.setData(rowIdx, ucstring("sheet_name"), wkSheetName);
hash = CI18N::makeHash(wkBotName + wkTranslationName + wkSheetName);
// update the hash code
CI18N::hashToUCString(hash, transBotNames[transRowIdx][0]);
}
// bots_name.txt has been manually changed. We trust what the Level Designer has done. We don't destroy is work.
// or it is a simple
else
{
//use the "translated name" of the manually changed work/bot_name.txt
botNames.setData(rowIdx, ucstring("translated name"), wkTranslationName);
botNames.setData(rowIdx, ucstring("sheet_name"), wkSheetName);
}
}
}
}
}
// 2 - generic names
{
nlinfo(" Generic names...");
set<string>::iterator first(GenericNames.begin()), last(GenericNames.end());
for (; first != last; ++first)
{
string gnName = "gn_" + cleanupName(*first);
ucstring fctsTitleId;
ucstring fctsName;
// add or modify the bot names
uint rowIdx;
if (!botNames.findRow(botIdCol, *first, rowIdx))
{
// we need to add the entry
rowIdx = botNames.size();
botNames.resize(botNames.size()+1);
botNames.setData(rowIdx, ucstring("bot name"), *first);
botNames.setData(rowIdx, ucstring("translated name"), ucstring("$") + gnName + "$");
botNames.setData(rowIdx, ucstring("sheet_name"), ucstring());
fctsTitleId = gnName;
fctsName = *first;
nbAddSimpleName++;
}
else
{
// look in the translated table to remember the translated name to write it in the string file
ucstring wkBotName = botNames.getData(rowIdx, ucstring("bot name"));
ucstring wkTranslationName = botNames.getData(rowIdx, ucstring("translated name"));
ucstring wkSheetName = botNames.getData(rowIdx, ucstring("sheet_name"));
nlinfo("Bot name:%s\n",wkBotName.toString().c_str());
bool isWkTranslationNameAGroupName = wkTranslationName.find(ucstring("$")) != ucstring::npos;
if ( isWkTranslationNameAGroupName ) //work name looks like "$gn_***$: do not modify
{
//Do not change work/bot_name.txt
// update work/world_title.txt
ucstring transName;
fctsTitleId = makeGroupName(wkTranslationName);
uint transRowIdx;
if (transBotNames.findRow(transIdCol, *first, transRowIdx))
{
transName = transBotNames.getData(transRowIdx, ucstring("translated name"));
if (transName.find(ucstring("$")) != ucstring::npos)
{
transName = fctsTitleId;
}
}
else
{
transName = fctsTitleId;
}
//Do not touch anything
botNames.setData(rowIdx, ucstring("translated name"), wkTranslationName);
botNames.setData(rowIdx, ucstring("sheet_name"), wkSheetName);
// fctsTitleId = makeGroupName(wkTranslationName);
fctsName = transName;
}
else // WkTranslationName != "$gn*$"
{
uint transRowIdx;
ucstring transName;
ucstring wkSheetName;
// Get the translation as a simple name.
if (transBotNames.findRow(transIdCol, *first, transRowIdx))
{
transName = transBotNames.getData(transRowIdx, ucstring("translated name"));
ucstring trSheetName = transBotNames.getData(transRowIdx, ucstring("sheet_name"));
//tr."translation name" is
if (transName.find(ucstring("$")) != ucstring::npos)
{
//get Translation, update hash
botNames[rowIdx][1] = transName;
botNames[rowIdx][2] = trSheetName;
fctsTitleId = makeGroupName(transName);
fctsName = makeGroupName(transName);
ucstring trNewUcHash;
uint64 hash = CI18N::makeHash(wkBotName + transName +trSheetName);
CI18N::hashToUCString(hash, trNewUcHash);
transBotNames[transRowIdx][0] = ucstring("_") + trNewUcHash;
}
else //botNames."translated name" != $gn_$ && tansName."translated name" != $gn_$
{
// get the translation back
//update work/bot_name.txt
wkTranslationName = ucstring("$")+gnName+"$";
botNames[rowIdx][0] = wkBotName;
botNames[rowIdx][1] = wkTranslationName;
botNames[rowIdx][2] = wkSheetName;
//update translated/bot_name.txt
fctsName = transName; //transName
fctsTitleId = gnName;
ucstring trNewUcHash;
uint64 hash = CI18N::makeHash(botNames[rowIdx][0] + botNames[rowIdx][1] +botNames[rowIdx][2]);
CI18N::hashToUCString(hash, trNewUcHash);
transBotNames[transRowIdx][0] = ucstring("_") + trNewUcHash;
}
}
else //There is no translation yet
{
fctsName = wkTranslationName;
wkTranslationName = ucstring("$")+gnName+"$";
botNames[rowIdx][0] = wkBotName;
botNames[rowIdx][1] = wkTranslationName;
botNames[rowIdx][2] = wkSheetName;
fctsTitleId = gnName;
}
}
}
// look for a corresponding entry
uint gnNameRow;
if (!fcts.findRow(fctsIdCol, fctsTitleId, gnNameRow))
{
// not found, add it
gnNameRow = fcts.size();
fcts.resize(fcts.size()+1);
fcts.setData(gnNameRow, ucstring("title_id"), fctsTitleId);
fcts.setData(gnNameRow, ucstring("name"), fctsName);
nbAddGenericName++;
}
else //Update
{
}
}
}
// 3 - functions
{
nlinfo(" Functions...");
set<string>::iterator first(Functions.begin()), last(Functions.end());
for (; first != last; ++first)
{
string fctName = *first;
// look for a corresponding entry
uint functionRow;
if (!fcts.findRow(fctsIdCol, fctName, functionRow))
{
// not found, add it
functionRow = fcts.size();
fcts.resize(fcts.size()+1);
fcts.setData(functionRow, ucstring("title_id"), fctName);
fcts.setData(functionRow, ucstring("name"), *first);
nbAddFunction++;
}
}
}
// display resum\E9
nlinfo("Adding %u new simple name", nbAddSimpleName);
nlinfo("Adding %u new generic name", nbAddGenericName);
nlinfo("Adding %u new function name", nbAddFunction);
// saving the modified files
ucstring s = prepareExcelSheet(botNames);
CI18N::writeTextFile(work_path_file, s, false);
s = prepareExcelSheet(transBotNames);
CI18N::writeTextFile(trans_path_file, s, false);
s = prepareExcelSheet(fcts);
CI18N::writeTextFile(title_path_file, s, false);
*/
return 0;
}
}

View file

@ -0,0 +1,111 @@
// Translation Manager Plugin - OVQT Plugin <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
// Copyright (C) 2011 Emanuel Costea <cemycc@gmail.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef EXTRACT_BOT_NAMES_H
#define EXTRACT_BOT_NAMES_H
#include "nel/misc/types_nl.h"
#include "nel/misc/config_file.h"
#include "nel/misc/sheet_id.h"
#include "nel/misc/path.h"
#include "nel/misc/diff_tool.h"
#include "nel/georges/u_form.h"
#include "nel/georges/u_form_elm.h"
#include "nel/georges/load_form.h"
#include "nel/ligo/ligo_config.h"
#include "nel/ligo/primitive.h"
#include "nel/ligo/primitive_utils.h"
using namespace std;
using namespace NLMISC;
using namespace NLLIGO;
using namespace STRING_MANAGER;
namespace Plugin
{
struct TCreatureInfo
{
CSheetId SheetId;
bool ForceSheetName;
bool DisplayName;
void readGeorges (const NLMISC::CSmartPtr<NLGEORGES::UForm> &form, const NLMISC::CSheetId &sheetId)
{
const NLGEORGES::UFormElm &item=form->getRootNode();
SheetId=sheetId;
item.getValueByName(ForceSheetName, "3d data.ForceDisplayCreatureName");
item.getValueByName(DisplayName, "3d data.DisplayName");
}
void serial(NLMISC::IStream &f)
{
f.serial(SheetId);
f.serial(ForceSheetName);
f.serial(DisplayName);
}
static uint getVersion ()
{
return 1;
}
void removed()
{
}
};
struct TEntryInfo
{
string SheetName;
};
struct ExtractBotNames
{
private:
vector<string> Filters;
std::map<CSheetId, TCreatureInfo> Creatures;
set<string> GenericNames;
map<string, TEntryInfo> SimpleNames;
set<string> Functions;
private:
TCreatureInfo *getCreature(const std::string &sheetName);
ucstring makeGroupName(const ucstring & translationName);
string removeAndStoreFunction(const std::string &fullName);
void addGenericName(const std::string &name, const std::string &sheetName);
void addSimpleName(const std::string &name, const std::string &sheetName);
public:
void extractBotNamesFromPrimitives(CLigoConfig ligoConfig);
void setRequiredSettings(list<string> filters, string level_design_path);
set<string> getGenericNames();
map<string, TEntryInfo> getSimpleNames();
string cleanupName(const std::string &name);
ucstring cleanupUcName(const ucstring &name);
void cleanSimpleNames();
void cleanGenericNames();
};
}
#endif /* EXTRACT_BOT_NAMES_H */

View file

@ -0,0 +1,154 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "extract_new_sheet_names.h"
using namespace std;
using namespace NLMISC;
using namespace NLLIGO;
using namespace STRING_MANAGER;
namespace Plugin {
// ***************************************************************************
/*
* Specialisation of IWordListBuilder to list sheets in a directory
*/
bool CSheetWordListBuilder::buildWordList(std::vector<string> &allWords, string workSheetFileName)
{
SheetExt= toLower(SheetExt);
nlinfo("aaaa");
// verify the directory is correct
if(!CFile::isDirectory(SheetPath))
{
nlwarning("Error: Directory '%s' not found. '%s' Aborted", SheetPath.c_str(), workSheetFileName.c_str());
return false;
}
// list all files.
std::vector<string> allFiles;
allFiles.reserve(100000);
CPath::getPathContent(SheetPath, true, false, true, allFiles, NULL);
// Keep only the extension we want, and remove "_" (parent)
allWords.clear();
allWords.reserve(allFiles.size());
for(uint i=0;i<allFiles.size();i++)
{
string fileNameWithoutExt= CFile::getFilenameWithoutExtension(allFiles[i]);
string extension= toLower(CFile::getExtension(allFiles[i]));
// bad extension?
if(extension!=SheetExt)
continue;
// parent?
if(fileNameWithoutExt.empty()||fileNameWithoutExt[0]=='_')
continue;
// ok, add
allWords.push_back(toLower(fileNameWithoutExt));
}
return true;
}
// ***************************************************************************
/*
* Specialisation of IWordListBuilder to list new region/place name from .primitive
*/
bool CRegionPrimWordListBuilder::buildWordList(std::vector<string> &allWords, string workSheetFileName)
{
// verify the directory is correct
if(!CFile::isDirectory(PrimPath))
{
nlwarning("Error: Directory '%s' not found. '%s' Aborted", PrimPath.c_str(), workSheetFileName.c_str());
return false;
}
// list all files.
std::vector<string> allFiles;
allFiles.reserve(100000);
CPath::getPathContent(PrimPath, true, false, true, allFiles, NULL);
// parse all primitive that match the filter
allWords.clear();
allWords.reserve(100000);
// to avoid duplicate
set<string> allWordSet;
for(uint i=0;i<allFiles.size();i++)
{
string fileName= CFile::getFilename(allFiles[i]);
// filter don't match?
bool oneMatch= false;
for(uint filter=0;filter<PrimFilter.size();filter++)
{
if(testWildCard(fileName, PrimFilter[filter]))
oneMatch= true;
}
if(!oneMatch)
continue;
// ok, read the file
CPrimitives PrimDoc;
CPrimitiveContext::instance().CurrentPrimitive = &PrimDoc;
// if (!loadXmlPrimitiveFile(PrimDoc, allFiles[i], LigoConfig))
// {
// nlwarning("Error: cannot open file '%s'. '%s' Aborted", allFiles[i].c_str(), workSheetFileName.c_str());
// CPrimitiveContext::instance().CurrentPrimitive = NULL;
// return false;
// }
CPrimitiveContext::instance().CurrentPrimitive = NULL;
// For all primitives of interest
const char *listClass[]= {"continent", "region", "place", "stable",
"teleport_destination", "room_template"};
const char *listProp[]= {"name", "name", "name", "name",
"place_name", "place_name"};
const uint numListClass= sizeof(listClass)/sizeof(listClass[0]);
const uint numListProp= sizeof(listProp)/sizeof(listProp[0]);
nlctassert(numListProp==numListClass);
for(uint cid=0;cid<numListClass;cid++)
{
// parse the whole hierarchy
TPrimitiveClassPredicate predCont(listClass[cid]);
CPrimitiveSet<TPrimitiveClassPredicate> setPlace;
TPrimitiveSet placeRes;
setPlace.buildSet(PrimDoc.RootNode, predCont, placeRes);
// for all found
for (uint placeId= 0; placeId < placeRes.size(); ++placeId)
{
string primName;
if(placeRes[placeId]->getPropertyByName(listProp[cid], primName) && !primName.empty())
{
primName= toLower(primName);
// avoid duplicate
if(allWordSet.insert(primName).second)
{
allWords.push_back(primName);
}
}
}
}
}
return true;
}
}

View file

@ -0,0 +1,70 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef EXTRACT_NEW_SHEET_NAMES_H
#define EXTRACT_NEW_SHEET_NAMES_H
#include "nel/misc/types_nl.h"
#include "nel/misc/config_file.h"
#include "nel/misc/sheet_id.h"
#include "nel/misc/path.h"
#include "nel/misc/diff_tool.h"
#include "nel/misc/algo.h"
#include "nel/georges/u_form.h"
#include "nel/georges/u_form_elm.h"
#include "nel/georges/load_form.h"
#include "nel/ligo/ligo_config.h"
#include "nel/ligo/primitive.h"
#include "nel/ligo/primitive_utils.h"
using namespace std;
using namespace NLMISC;
using namespace NLLIGO;
using namespace STRING_MANAGER;
namespace Plugin {
// ***************************************************************************
/*
* Interface to build the whole list of words (key id) for a specific worksheet
*/
struct IWordListBuilder
{
virtual bool buildWordList(std::vector<string> &allWords, string workSheetFileName) =0;
};
struct CSheetWordListBuilder : public IWordListBuilder
{
string SheetExt;
string SheetPath;
virtual bool buildWordList(std::vector<string> &allWords, string workSheetFileName);
};
struct CRegionPrimWordListBuilder : public IWordListBuilder
{
string PrimPath;
vector<string> PrimFilter;
virtual bool buildWordList(std::vector<string> &allWords, string workSheetFileName);
};
}
#endif /* EXTRACT_NEW_SHEET_NAMES_H */

View file

@ -1,3 +1,19 @@
// Translation Manager Plugin - OVQT Plugin <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
// Copyright (C) 2011 Emanuel Costea <cemycc@gmail.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef TRANSLATION_MANAGER_EDITOR_H
#define TRANSLATION_MANAGER_EDITOR_H

View file

@ -1,6 +1,6 @@
// Object Viewer Qt - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Translation Manager Plugin - OVQT Plugin <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
// Copyright (C) 2011 Dzmitry Kamiahin <dnk-88@tut.by>
// Copyright (C) 2011 Emanuel Costea <cemycc@gmail.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
@ -46,21 +46,6 @@
#include <QtGui/QCloseEvent>
struct TEntryInfo
{
string SheetName;
};
set<string> getGenericNames();
void cleanGenericNames();
map<string, TEntryInfo> getSimpleNames();
void cleanSimpleNames();
void setPathsForPrimitives(map<string,list<string> > config_paths, string ligo_class_file);
void extractBotNamesFromPrimitives();
string cleanupName(const std::string &name);
ucstring cleanupUcName(const ucstring &name);
namespace Plugin
{
@ -74,9 +59,8 @@ CMainWindow::CMainWindow(QWidget *parent)
windowMapper = new QSignalMapper(this);
connect(windowMapper, SIGNAL(mapped(QWidget*)), this, SLOT(setActiveSubWindow(QWidget*)));
// set extraction scripts counters
execution_count["extract_bot_names"] = 0;
initialize_settings["georges"] = false;
initialize_settings["ligo"] = false;
readSettings();
createToolbar();
m_undoStack = new QUndoStack(this);
@ -99,9 +83,33 @@ void CMainWindow::createToolbar()
QMenu *wordsExtractionMenu = new QMenu("&Words extraction...");
wordsExtractionMenu->setIcon(QIcon(Core::Constants::ICON_SETTINGS));
_ui.toolBar->addAction(wordsExtractionMenu->menuAction());
// extract bot names
QAction *extractBotNamesAct = wordsExtractionMenu->addAction("&Extract bot names...");
extractBotNamesAct->setStatusTip(tr("Extract bot names from primitives."));
connect(extractBotNamesAct, SIGNAL(triggered()), this, SLOT(extractBotNames()));
// signal mapper for extraction words
QSignalMapper *wordsExtractionMapper = new QSignalMapper(this);
connect(wordsExtractionMapper, SIGNAL(mapped(QString)), this, SLOT(extractWords(QString)));
// extract item words
QAction *extractItemWordsAct = wordsExtractionMenu->addAction("&Extract item words...");
extractItemWordsAct->setStatusTip(tr("Extract item words"));
connect(extractItemWordsAct, SIGNAL(triggered()), wordsExtractionMapper, SLOT(map()));
wordsExtractionMapper->setMapping(extractItemWordsAct, "item");
// extract creature words
QAction *extractCreatureWordsAct = wordsExtractionMenu->addAction("&Extract creature words...");
extractCreatureWordsAct->setStatusTip(tr("Extract creature words"));
connect(extractCreatureWordsAct, SIGNAL(triggered()), wordsExtractionMapper, SLOT(map()));
wordsExtractionMapper->setMapping(extractCreatureWordsAct, "creature");
// extract sbrick words
QAction *extractSbrickWordsAct = wordsExtractionMenu->addAction("&Extract sbrick words...");
extractSbrickWordsAct->setStatusTip(tr("Extract sbrick words"));
connect(extractSbrickWordsAct, SIGNAL(triggered()), wordsExtractionMapper, SLOT(map()));
wordsExtractionMapper->setMapping(extractSbrickWordsAct, "sbrick");
// extract sphrase words
QAction *extractSphraseWordsAct = wordsExtractionMenu->addAction("&Extract sphrase words...");
extractSphraseWordsAct->setStatusTip(tr("Extract sphrase words"));
connect(extractSphraseWordsAct, SIGNAL(triggered()), wordsExtractionMapper, SLOT(map()));
wordsExtractionMapper->setMapping(extractSphraseWordsAct, "sphrase");
// Windows menu
windowMenu = new QMenu(tr("&Windows..."), _ui.toolBar);
@ -194,6 +202,29 @@ void CMainWindow::open()
}
void CMainWindow::openWorkFile(QString file)
{
QFileInfo* file_path = new QFileInfo(QString("%1/%2").arg(QString(work_path.c_str())).arg(file));
if(file_path->exists())
{
if(isWorksheetEditor(file_path->filePath()))
{
CEditorWorksheet *new_window = new CEditorWorksheet(_ui.mdiArea);
new_window->open(file_path->filePath());
new_window->activateWindow();
}
} else {
QErrorMessage error;
QString text;
text.append("The ");
text.append(file_path->fileName());
text.append(" file don't exists.");
error.showMessage(text);
error.exec();
}
}
void CMainWindow::save()
{
CEditor* current_window = qobject_cast<CEditor*>(_ui.mdiArea->currentSubWindow());
@ -223,49 +254,101 @@ void CMainWindow::saveAs()
}
}
void CMainWindow::initializeSettings(bool georges = false)
{
if(georges == true && initialize_settings["georges"] == false)
{
CPath::addSearchPath(level_design_path + "/DFN", true, false);
CPath::addSearchPath(level_design_path + "/Game_elem/Creature", true, false);
initialize_settings["georges"] = true;
}
if(initialize_settings["ligo"] == false)
{
//-------------------------------------------------------------------
// init ligo config
string ligoPath = CPath::lookup("world_editor_classes.xml", true, true);
ligoConfig.readPrimitiveClass(ligoPath.c_str(), false);
NLLIGO::Register();
NLLIGO::CPrimitiveContext::instance().CurrentLigoConfig = &ligoConfig;
initialize_settings["ligo"] = true;
}
}
void CMainWindow::extractWords(QString type)
{
CEditor* editor_window = qobject_cast<CEditor*>(_ui.mdiArea->currentSubWindow());
CEditorWorksheet* current_window = qobject_cast<CEditorWorksheet*>(editor_window);
// initializeSettings(false);
CSheetWordListBuilder builder;
QString column_name;
if(type == "item")
{
column_name = "item ID";
builder.SheetExt = "sitem";
builder.SheetPath = level_design_path + "/game_element/sitem";
} else if(type == "creature") {
column_name = "creature ID";
builder.SheetExt = "creature";
builder.SheetPath = level_design_path + "/Game_elem/Creature/fauna";
} else if(type == "sbrick") {
column_name = "sbrick ID";
builder.SheetExt = "sbrick";
builder.SheetPath = level_design_path + "/game_element/sbrick";
} else if(type == "sphrase") {
column_name = "sphrase ID";
builder.SheetExt = "sphrase";
builder.SheetPath = level_design_path + "/game_element/sphrase";
}
current_window->extractWords(current_window->windowFilePath(), column_name, builder);
}
void CMainWindow::extractBotNames()
{
if(verifySettings() == true)
{
CEditorWorksheet* current_window;
if(_ui.mdiArea->subWindowList().size() > 0)
{
CEditor* editor_window = qobject_cast<CEditor*>(_ui.mdiArea->currentSubWindow());
if(QString(editor_window->widget()->metaObject()->className()) == "QTableWidget") // Sheet Editor
{
CEditorWorksheet* current_window = qobject_cast<CEditorWorksheet*>(editor_window);
current_window = qobject_cast<CEditorWorksheet*>(editor_window);
QString file_path = current_window->subWindowFilePath();
if(!current_window->isBotNamesTable())
{
list<CEditor*> subWindows = convertSubWindowList(_ui.mdiArea->subWindowList());
list<CEditor*>::iterator it = subWindows.begin();
bool finded = false;
for(; it != subWindows.end(), finded != true; ++it)
for(; it != subWindows.end(); ++it)
{
current_window = qobject_cast<CEditorWorksheet*>((*it));
file_path = current_window->subWindowFilePath();
if(current_window->isBotNamesTable())
{
finded = true;
current_window->activateWindow();
}
current_window = qobject_cast<CEditorWorksheet*>((*it));
file_path = current_window->subWindowFilePath();
if(current_window->isBotNamesTable())
{
finded = true;
current_window->activateWindow();
}
}
if(!finded)
{
open();
openWorkFile("bot_names_wk.txt");
current_window = qobject_cast<CEditorWorksheet*>(_ui.mdiArea->currentSubWindow());
file_path = current_window->windowFilePath();
}
}
if(execution_count["extract_bot_names"] == 0)
setPathsForPrimitives(config_paths, ligo_path);
extractBotNamesFromPrimitives();
execution_count["extract_bot_names"] = execution_count["extract_bot_names"] + 1;
current_window->extractBotNames();
// if(current_window->isWindowModified())
// {
// }
}
}
} else {
openWorkFile("bot_names_wk.txt");
current_window = qobject_cast<CEditorWorksheet*>(_ui.mdiArea->currentSubWindow());
QString file_path = current_window->windowFilePath();
}
initializeSettings(true);
current_window->extractBotNames(filters, level_design_path, ligoConfig);
}
}
@ -273,22 +356,14 @@ void CMainWindow::readSettings()
{
QSettings *settings = Core::ICore::instance()->settings();
settings->beginGroup("translationmanager");
list<string> paths = convertQStringList(settings->value("paths").toStringList()); /* paths */
config_paths["paths"] = paths;
list<string> pathsR = convertQStringList(settings->value("pathsR").toStringList()); /* pathsR */
config_paths["pathsR"] = pathsR;
list<string> georges = convertQStringList(settings->value("georges").toStringList()); /* georges */
config_paths["georges"] = georges;
list<string> filters = convertQStringList(settings->value("filters").toStringList()); /* filters */
config_paths["filters"] = filters;
filters = convertQStringList(settings->value("filters").toStringList()); /* filters */
languages = convertQStringList(settings->value("trlanguages").toStringList()); /* languages */
ligo_path = settings->value("ligo").toString().toStdString();
translation_path = settings->value("translation").toString().toStdString();
work_path = settings->value("work").toString().toStdString();
settings->endGroup();
settings->endGroup();
settings->beginGroup(Core::Constants::DATA_PATH_SECTION);
level_design_path = settings->value(Core::Constants::LEVELDESIGN_PATH).toString().toStdString();
settings->endGroup();
}
void CMainWindow::debug(QString text)
@ -305,10 +380,7 @@ bool CMainWindow::verifySettings()
QSettings *settings = Core::ICore::instance()->settings();
settings->beginGroup("translationmanager");
if(settings->value("paths").toList().count() == 0
|| settings->value("pathsR").toList().count() == 0
|| settings->value("georges").toList().count() == 0
|| settings->value("filters").toList().count() == 0)
if(settings->value("filters").toList().count() == 0)
{
QErrorMessage error_settings;
error_settings.showMessage("Please write all the paths on the settings dialog.");

View file

@ -1,6 +1,6 @@
// Object Viewer Qt - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Translation Manager Plugin - OVQT Plugin <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
// Copyright (C) 2011 Dzmitry Kamiahin <dnk-88@tut.by>
// Copyright (C) 2011 Emanuel Costea <cemycc@gmail.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
@ -27,6 +27,7 @@
#include "nel/misc/sheet_id.h"
#include "nel/misc/path.h"
#include "nel/misc/diff_tool.h"
#include "nel/ligo/ligo_config.h"
// Qt includes
#include <QtCore/QObject>
@ -51,13 +52,6 @@ using namespace std;
namespace Plugin
{
class CMdiSubWindow;
struct WStatus
{
bool modified;
};
class CMainWindow : public QMainWindow
{
Q_OBJECT
@ -75,15 +69,16 @@ private:
QMenu *windowMenu;
QSignalMapper *windowMapper;
// config
map<string, list<string> > config_paths;
map<string,bool> initialize_settings;
list<string> filters;
list<string> languages;
string ligo_path;
string level_design_path;
string translation_path;
string work_path;
// counts
map<string, int> execution_count;
NLLIGO::CLigoConfig ligoConfig;
private Q_SLOTS:
void extractBotNames();
void extractWords(QString);
void open();
void save();
void saveAs();
@ -93,12 +88,13 @@ private Q_SLOTS:
void debug(QString text); // TODO
private:
void openWorkFile(QString file);
void updateToolbar(QMdiSubWindow *window);
bool verifySettings();
void readSettings();
void createMenus();
void createToolbar();
void initializeSettings(bool georges);
list<string> convertQStringList(QStringList listq);
list<CEditor*> convertSubWindowList(QList<QMdiSubWindow*> listq);
bool isWorksheetEditor(QString filename);

View file

@ -1,3 +1,20 @@
// Translation Manager Plugin - OVQT Plugin <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
// Copyright (C) 2011 Emanuel Costea <cemycc@gmail.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// Project includes
#include "translation_manager_plugin.h"
#include "translation_manager_settings_page.h"

View file

@ -1,3 +1,20 @@
// Translation Manager Plugin - OVQT Plugin <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
// Copyright (C) 2011 Emanuel Costea <cemycc@gmail.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef TRANSLATION_MANAGER_PLUGIN_H
#define TRANSLATION_MANAGER_PLUGIN_H

View file

@ -1,6 +1,6 @@
// Object Viewer Qt - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Translation Manager Plugin - OVQT Plugin <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
// Copyright (C) 2011 Dzmitry Kamiahin <dnk-88@tut.by>
// Copyright (C) 2011 Emanuel Costea <cemycc@gmail.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
@ -69,12 +69,6 @@ QWidget *CTranslationManagerSettingsPage::createPage(QWidget *parent)
_currentPage = new QWidget(parent);
_ui.setupUi(_currentPage);
readSettings();
connect(_ui.paths_add, SIGNAL(clicked()), this, SLOT(pathAdd()));
connect(_ui.paths_del, SIGNAL(clicked()), this, SLOT(pathDel()));
connect(_ui.pathsR_add, SIGNAL(clicked()), this, SLOT(pathRAdd()));
connect(_ui.pathsR_del, SIGNAL(clicked()), this, SLOT(pathRDel()));
connect(_ui.georges_add, SIGNAL(clicked()), this, SLOT(georgeAdd()));
connect(_ui.georges_del, SIGNAL(clicked()), this, SLOT(georgeDel()));
connect(_ui.filter_add, SIGNAL(clicked()), this, SLOT(filterAdd()));
connect(_ui.filter_del, SIGNAL(clicked()), this, SLOT(filterDel()));
connect(_ui.lang_add, SIGNAL(clicked()), this, SLOT(languageAdd()));
@ -85,66 +79,6 @@ QWidget *CTranslationManagerSettingsPage::createPage(QWidget *parent)
return _currentPage;
}
void CTranslationManagerSettingsPage::pathAdd()
{
QString newPath = QFileDialog::getExistingDirectory(_currentPage, "", lastDir);
if (!newPath.isEmpty())
{
QListWidgetItem *newItem = new QListWidgetItem;
newItem->setText(newPath);
newItem->setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
_ui.paths_list->addItem(newItem);
lastDir = newPath;
}
}
void CTranslationManagerSettingsPage::pathDel()
{
QListWidgetItem *removeItem = _ui.paths_list->takeItem(_ui.paths_list->currentRow());
if (!removeItem)
delete removeItem;
}
void CTranslationManagerSettingsPage::pathRAdd()
{
QString newPath = QFileDialog::getExistingDirectory(_currentPage, "", lastDir);
if (!newPath.isEmpty())
{
QListWidgetItem *newItem = new QListWidgetItem;
newItem->setText(newPath);
newItem->setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
_ui.pathsR_list->addItem(newItem);
lastDir = newPath;
}
}
void CTranslationManagerSettingsPage::pathRDel()
{
QListWidgetItem *removeItem = _ui.pathsR_list->takeItem(_ui.pathsR_list->currentRow());
if (!removeItem)
delete removeItem;
}
void CTranslationManagerSettingsPage::georgeAdd()
{
QString newPath = QFileDialog::getExistingDirectory(_currentPage, "", lastDir);
if (!newPath.isEmpty())
{
QListWidgetItem *newItem = new QListWidgetItem;
newItem->setText(newPath);
newItem->setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
_ui.georges_list->addItem(newItem);
lastDir = newPath;
}
}
void CTranslationManagerSettingsPage::georgeDel()
{
QListWidgetItem *removeItem = _ui.georges_list->takeItem(_ui.georges_list->currentRow());
if (!removeItem)
delete removeItem;
}
void CTranslationManagerSettingsPage::filterAdd()
{
QString newValue = _ui.filter_edit->text();
@ -208,15 +142,12 @@ void CTranslationManagerSettingsPage::apply()
void CTranslationManagerSettingsPage::readSettings()
{
QStringList paths, pathsR, georges, filters, languages;
QStringList filters, languages;
QString ligo, translation, work;
QSettings *settings = Core::ICore::instance()->settings();
settings->beginGroup("translationmanager");
paths = settings->value("paths").toStringList(); /* paths */
pathsR = settings->value("pathsR").toStringList(); /* pathsR */
georges = settings->value("georges").toStringList(); /* georges */
filters = settings->value("filters").toStringList(); /* filters */
languages = settings->value("trlanguages").toStringList(); /* languages */
ligo = settings->value("ligo").toString();
@ -224,30 +155,6 @@ void CTranslationManagerSettingsPage::readSettings()
work = settings->value("work").toString();
settings->endGroup();
// paths
Q_FOREACH(QString path, paths)
{
QListWidgetItem *newItem = new QListWidgetItem;
newItem->setText(path);
newItem->setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
_ui.paths_list->addItem(newItem);
}
// pathsR
Q_FOREACH(QString pathR, pathsR)
{
QListWidgetItem *newItem = new QListWidgetItem;
newItem->setText(pathR);
newItem->setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
_ui.pathsR_list->addItem(newItem);
}
// georges
Q_FOREACH(QString george, georges)
{
QListWidgetItem *newItem = new QListWidgetItem;
newItem->setText(george);
newItem->setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
_ui.georges_list->addItem(newItem);
}
// filter
Q_FOREACH(QString filter, filters)
{
@ -264,8 +171,6 @@ void CTranslationManagerSettingsPage::readSettings()
newItem->setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
_ui.lang_list->addItem(newItem);
}
// ligo
_ui.ligo_edit->setText(ligo);
// translation
_ui.translation_edit->setText(translation);
// work
@ -275,25 +180,14 @@ void CTranslationManagerSettingsPage::readSettings()
void CTranslationManagerSettingsPage::writeSettings()
{
QStringList paths, pathsR, georges, filters, languages;
QStringList filters, languages;
QString ligo, translation, work;
// paths
for (int i = 0; i < _ui.paths_list->count(); ++i)
paths << _ui.paths_list->item(i)->text();
// pathsR
for (int i = 0; i < _ui.pathsR_list->count(); ++i)
pathsR << _ui.pathsR_list->item(i)->text();
// georges
for (int i = 0; i < _ui.georges_list->count(); ++i)
georges << _ui.georges_list->item(i)->text();
// filters
for (int i = 0; i < _ui.filter_list->count(); ++i)
filters << _ui.filter_list->item(i)->text();
// languages
for (int i = 0; i < _ui.lang_list->count(); ++i)
languages << _ui.lang_list->item(i)->text();
// ligo path
ligo = _ui.ligo_edit->text();
// translations path
translation = _ui.translation_edit->text();
// work path
@ -301,12 +195,8 @@ void CTranslationManagerSettingsPage::writeSettings()
QSettings *settings = Core::ICore::instance()->settings();
settings->beginGroup("translationmanager");
settings->setValue("paths", paths);
settings->setValue("pathsR", pathsR);
settings->setValue("georges", georges);
settings->setValue("filters", filters);
settings->setValue("trlanguages", languages);
settings->setValue("ligo", ligo);
settings->setValue("trlanguages", languages);
settings->setValue("translation", translation);
settings->setValue("work", work);
settings->endGroup();

View file

@ -1,6 +1,6 @@
// Object Viewer Qt - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Translation Manager Plugin - OVQT Plugin <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
// Copyright (C) 2011 Dzmitry Kamiahin <dnk-88@tut.by>
// Copyright (C) 2011 Emanuel Costea <cemycc@gmail.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
@ -15,7 +15,6 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef TRANSLATION_MANAGER_SETTINGS_PAGE_H
#define TRANSLATION_MANAGER_SETTINGS_PAGE_H
@ -49,12 +48,6 @@ public:
virtual void apply();
virtual void finish() {}
private Q_SLOTS:
void pathAdd();
void pathDel();
void pathRAdd();
void pathRDel();
void georgeAdd();
void georgeDel();
void filterAdd();
void filterDel();
void languageAdd();

View file

@ -6,388 +6,181 @@
<rect>
<x>0</x>
<y>0</y>
<width>490</width>
<height>496</height>
<width>533</width>
<height>478</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>1</number>
</property>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Core paths</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Paths</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>318</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="paths_add">
<property name="text">
<string>dwadwadwa</string>
</property>
<property name="icon">
<iconset resource="../object_viewer/object_viewer.qrc">
<normaloff>:/icons/ic_nel_add_item.png</normaloff>:/icons/ic_nel_add_item.png</iconset>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonIconOnly</enum>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="paths_del">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../object_viewer/object_viewer.qrc">
<normaloff>:/icons/ic_nel_delete_item.png</normaloff>:/icons/ic_nel_delete_item.png</iconset>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QListWidget" name="paths_list"/>
</item>
</layout>
</item>
<item row="1" column="0">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Paths non recursives</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>218</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="pathsR_add">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../object_viewer/object_viewer.qrc">
<normaloff>:/icons/ic_nel_add_item.png</normaloff>:/icons/ic_nel_add_item.png</iconset>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="pathsR_del">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../object_viewer/object_viewer.qrc">
<normaloff>:/icons/ic_nel_delete_item.png</normaloff>:/icons/ic_nel_delete_item.png</iconset>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QListWidget" name="pathsR_list"/>
</item>
</layout>
</item>
<item row="2" column="0">
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Georges Paths</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>258</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="georges_add">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../object_viewer/object_viewer.qrc">
<normaloff>:/icons/ic_nel_add_item.png</normaloff>:/icons/ic_nel_add_item.png</iconset>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="georges_del">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../object_viewer/object_viewer.qrc">
<normaloff>:/icons/ic_nel_delete_item.png</normaloff>:/icons/ic_nel_delete_item.png</iconset>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QListWidget" name="georges_list"/>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>Translation files paths</string>
</attribute>
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>9</x>
<y>190</y>
<width>454</width>
<height>161</height>
</rect>
<widget class="QGroupBox" name="groupBox">
<property name="geometry">
<rect>
<x>0</x>
<y>10</y>
<width>531</width>
<height>421</height>
</rect>
</property>
<property name="title">
<string>Translation Manager Plugin</string>
</property>
<widget class="QWidget" name="">
<property name="geometry">
<rect>
<x>0</x>
<y>30</y>
<width>521</width>
<height>232</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Filters</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>Ligo class file - This is the name of the world_editor_classes.xml file.</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="ligo_edit"/>
</item>
<item>
<widget class="QLabel" name="label_8">
<property name="text">
<string>Work directory</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QLineEdit" name="work_edit"/>
</item>
<item>
<widget class="QToolButton" name="work_add">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="label_6">
<property name="text">
<string>Translation directory</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QLineEdit" name="translation_edit"/>
</item>
<item>
<widget class="QToolButton" name="translation_add">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>9</x>
<y>10</y>
<width>211</width>
<height>181</height>
</rect>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="filter_edit"/>
</item>
<item row="0" column="2">
<widget class="QToolButton" name="filter_add">
<property name="text">
<string/>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Filters</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="filter_edit"/>
</item>
<item row="0" column="2">
<widget class="QToolButton" name="filter_add">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../object_viewer/object_viewer.qrc">
<normaloff>:/icons/ic_nel_add_item.png</normaloff>:/icons/ic_nel_add_item.png</iconset>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QToolButton" name="filter_del">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../object_viewer/object_viewer.qrc">
<normaloff>:/icons/ic_nel_delete_item.png</normaloff>:/icons/ic_nel_delete_item.png</iconset>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0" colspan="4">
<widget class="QListWidget" name="filter_list"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>240</x>
<y>10</y>
<width>221</width>
<height>181</height>
</rect>
<property name="icon">
<iconset resource="../core/core.qrc">
<normaloff>:/core/icons/ic_nel_add_item.png</normaloff>:/core/icons/ic_nel_add_item.png</iconset>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Languages</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="lang_edit"/>
</item>
<item row="0" column="2">
<widget class="QToolButton" name="lang_add">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../object_viewer/object_viewer.qrc">
<normaloff>:/icons/ic_nel_add_item.png</normaloff>:/icons/ic_nel_add_item.png</iconset>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QToolButton" name="lang_del">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../object_viewer/object_viewer.qrc">
<normaloff>:/icons/ic_nel_delete_item.png</normaloff>:/icons/ic_nel_delete_item.png</iconset>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0" colspan="4">
<widget class="QListWidget" name="lang_list"/>
</item>
</layout>
</widget>
</widget>
</widget>
</item>
</layout>
</item>
<item row="0" column="3">
<widget class="QToolButton" name="filter_del">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../core/core.qrc">
<normaloff>:/core/icons/ic_nel_delete_item.png</normaloff>:/core/icons/ic_nel_delete_item.png</iconset>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Languages</string>
</property>
</widget>
</item>
<item row="0" column="5">
<widget class="QLineEdit" name="lang_edit"/>
</item>
<item row="0" column="6">
<widget class="QToolButton" name="lang_add">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../core/core.qrc">
<normaloff>:/core/icons/ic_nel_add_item.png</normaloff>:/core/icons/ic_nel_add_item.png</iconset>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="7">
<widget class="QToolButton" name="lang_del">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../core/core.qrc">
<normaloff>:/core/icons/ic_nel_delete_item.png</normaloff>:/core/icons/ic_nel_delete_item.png</iconset>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0" colspan="4">
<widget class="QListWidget" name="filter_list"/>
</item>
<item row="1" column="4" colspan="4">
<widget class="QListWidget" name="lang_list"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="">
<property name="geometry">
<rect>
<x>0</x>
<y>340</y>
<width>521</width>
<height>60</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Translation directory</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLineEdit" name="translation_edit"/>
</item>
<item row="1" column="1">
<widget class="QToolButton" name="translation_add">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="">
<property name="geometry">
<rect>
<x>0</x>
<y>270</y>
<width>521</width>
<height>60</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Work directory</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLineEdit" name="work_edit"/>
</item>
<item row="1" column="1">
<widget class="QToolButton" name="work_add">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</widget>
<resources>
<include location="../../object_viewer_qt.qrc"/>
<include location="../object_viewer/object_viewer.qrc"/>
<include location="../core/core.qrc"/>
</resources>
<connections/>
</ui>