1 // Ryzom Core Studio - Translation Manager Plugin
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #include "translation_manager_constants.h"
19 #include "uxt_editor.h"
21 #include <QTableWidget>
22 #include <QFormLayout>
23 #include <QCloseEvent>
24 #include <QContextMenuEvent>
25 #include <QMessageBox>
27 #include <QFileDialog>
30 #include <QTextStream>
32 #include "nel/misc/diff_tool.h"
33 #include "nel/misc/i18n.h"
38 QString
getLang( const QString
&fn
)
41 int idx
= lang
.lastIndexOf( '/' );
45 lang
= lang
.mid( idx
+ 1 );
46 idx
= lang
.lastIndexOf( '.' );
50 lang
= lang
.left( idx
);
56 namespace TranslationManager
59 void markItemTranslated( QTableWidgetItem
*item
)
61 item
->setBackground( QColor::fromRgb( 126, 247, 134 ) );
64 void markItemUntranslated( QTableWidgetItem
*item
)
66 item
->setBackground( QColor::fromRgb( 247, 126, 126 ) );
75 t
= new QTableWidget();
80 std::vector
< STRING_MANAGER::TStringInfo
> infos
;
85 UXTEditor::UXTEditor( QMdiArea
*parent
) :
88 editor_type
= Constants::ED_UXT
;
89 setAttribute( Qt::WA_DeleteOnClose
);
91 d_ptr
= new UXTEditorPvt();
93 blockTableSignals( false );
96 UXTEditor::~UXTEditor()
102 void UXTEditor::open( QString filename
)
104 std::vector
< STRING_MANAGER::TStringInfo
> &infos
= d_ptr
->infos
;
105 QString lang
= getLang( filename
);
108 STRING_MANAGER::loadStringFile( filename
.toUtf8().constData(), infos
, false );
110 if( d_ptr
->infos
.size() == 0 )
112 // The work file cannot be found, cannot proceed
113 if( filename
.endsWith( "wk.uxt" ) )
115 QMessageBox::critical( this,
116 tr( "Error opening file.." ),
117 tr( "There was an error opening wk.uxt" ) );
121 int l
= filename
.lastIndexOf( "/" );
125 QString fn
= filename
.left( l
);
128 // The work file cannot be found, cannot proceed
129 STRING_MANAGER::loadStringFile( fn
.toUtf8().constData(), infos
, true );
130 if( d_ptr
->infos
.size() == 0 )
132 QMessageBox::critical( this,
133 tr( "Error opening Uxt file" ),
134 tr( "Neither the specified file nor wk.uxt could be opened." ) );
138 d_ptr
->loadedFromWK
= true;
141 blockTableSignals( true );
144 d_ptr
->t
->setColumnCount( 2 );
145 d_ptr
->t
->setRowCount( infos
.size() );
147 setHeaderText( "Id", lang
.toUpper() + " Text" );
151 std::vector
< STRING_MANAGER::TStringInfo
>::const_iterator itr
= infos
.begin();
152 while( itr
!= infos
.end() )
154 const STRING_MANAGER::TStringInfo
&info
= *itr
;
156 QTableWidgetItem
*name
= new QTableWidgetItem( info
.Identifier
.c_str() );
157 QTableWidgetItem
*text1
= new QTableWidgetItem( info
.Text
.toUtf8().c_str() );
159 d_ptr
->t
->setItem( i
, 0, name
);
160 d_ptr
->t
->setItem( i
, 1, text1
);
162 if( ( info
.HashValue
!= 0 ) && !d_ptr
->loadedFromWK
)
164 markItemTranslated( name
);
165 markItemTranslated( text1
);
169 markItemUntranslated( name
);
170 markItemUntranslated( text1
);
177 d_ptr
->t
->resizeColumnsToContents();
179 blockTableSignals( false );
181 setWidget( d_ptr
->t
);
183 current_file
= filename
;
184 setWindowTitle( filename
+ "[*]" );
185 setWindowFilePath( filename
);
188 void UXTEditor::save()
190 saveAs( current_file
);
193 void UXTEditor::saveAs( QString filename
)
196 if( !f
.open( QIODevice::WriteOnly
) )
199 QTextStream
out( &f
);
202 std::vector
< STRING_MANAGER::TStringInfo
>::const_iterator itr
= d_ptr
->infos
.begin();
203 while( itr
!= d_ptr
->infos
.end() )
207 // If text2 is not empty we can assume the string was translated, so we store with the correct hash
208 // If text2 is empty, it wasn't translated so we can just use the old hash.
209 // Additionally, if the strings were loaded from the wk.uxt file, we use a hash of 0 so we know it was not translated
210 if( itr
->Text2
.empty() )
212 if( d_ptr
->loadedFromWK
)
215 hash
= itr
->HashValue
;
219 hash
= NLMISC::CI18N::makeHash( itr
->Text2
);
222 QString hashLine
= "// HASH_VALUE ";
223 hashLine
+= QString( NLMISC::CI18N::hashToString( hash
).c_str() ).toUpper();
226 QString idxLine
= "// INDEX ";
227 idxLine
+= QString::number( idx
);
232 trLine
+= itr
->Identifier
.c_str();
236 if( itr
->Text2
.empty() )
237 trLine
+= itr
->Text
.toUtf8().c_str();
239 trLine
+= itr
->Text2
.toUtf8().c_str();
244 QString newLine
= "\r\n";
257 setWindowModified( false );
260 void UXTEditor::activateWindow()
266 void UXTEditor::insertRow()
268 blockTableSignals( true );
270 d_ptr
->infos
.push_back( STRING_MANAGER::TStringInfo() );
271 d_ptr
->t
->setRowCount( d_ptr
->t
->rowCount() + 1 );
272 int row
= d_ptr
->t
->rowCount() - 1;
274 QTableWidgetItem
*item1
= new QTableWidgetItem();
275 QTableWidgetItem
*item2
= new QTableWidgetItem();
276 d_ptr
->t
->setItem( row
, 0, item1
);
277 d_ptr
->t
->setItem( row
, 1, item2
);
279 markRowUntranslated( row
);
281 setWindowModified( true );
283 blockTableSignals( false );
287 void UXTEditor::deleteRow()
289 int r
= d_ptr
->t
->currentRow();
293 int answer
= QMessageBox::question( this,
294 tr( "Deleting a row" ),
295 tr( "Are you sure you want to delete this row?" ),
297 QMessageBox::Cancel
);
298 if( QMessageBox::Yes
!= answer
)
301 std::vector
< STRING_MANAGER::TStringInfo
>::iterator itr
= d_ptr
->infos
.begin();
303 d_ptr
->infos
.erase( itr
);
305 d_ptr
->t
->removeRow( r
);
307 setWindowModified( true );
310 void UXTEditor::closeEvent( QCloseEvent
*e
)
312 if( isWindowModified() )
314 int reply
= QMessageBox::question( this,
315 tr( "Table changed" ),
316 tr( "The table has changed. Would you like to save your changes?" ),
321 if( reply
== QMessageBox::Yes
)
330 void UXTEditor::contextMenuEvent( QContextMenuEvent
*e
)
332 QMenu
*menu
= new QMenu( this );
333 QAction
*insertAction
= new QAction( "Insert row", menu
);
334 QAction
*deleteAction
= new QAction( "Delete row", menu
);
335 QAction
*markAction
= new QAction( "Mark translated", menu
);
336 QAction
*unmarkAction
= new QAction( "Mark not-translated", menu
);
337 QAction
*saveAction
= new QAction( "Save", menu
);
338 QAction
*saveAsAction
= new QAction( "Save as..", menu
);
340 connect( insertAction
, SIGNAL( triggered( bool ) ), this, SLOT( insertRow() ) );
341 connect( deleteAction
, SIGNAL( triggered( bool ) ), this, SLOT( deleteRow() ) );
342 connect( markAction
, SIGNAL( triggered( bool ) ), this, SLOT( markTranslated() ) );
343 connect( unmarkAction
, SIGNAL( triggered( bool ) ), this, SLOT( markUntranslated() ) );
344 connect( saveAction
, SIGNAL( triggered( bool ) ), this, SLOT( onSaveClicked() ) );
345 connect( saveAsAction
, SIGNAL( triggered( bool ) ), this, SLOT( onSaveAsClicked() ) );
347 menu
->addAction( insertAction
);
348 menu
->addAction( deleteAction
);
349 menu
->addAction( markAction
);
350 menu
->addAction( unmarkAction
);
351 menu
->addAction( saveAction
);
352 menu
->addAction( saveAsAction
);
353 menu
->exec( e
->globalPos() );
356 void UXTEditor::onCellChanged( int row
, int column
)
358 QTableWidgetItem
*item
= d_ptr
->t
->item( row
, column
);
359 STRING_MANAGER::TStringInfo
&info
= d_ptr
->infos
[ row
];
362 info
.Identifier
= item
->text().toUtf8().constData();
365 info
.Text2
= item
->text().toUtf8().constData();
367 setWindowModified( true );
369 markRowTranslated( row
);
372 void UXTEditor::markTranslated()
374 int r
= d_ptr
->t
->currentRow();
378 STRING_MANAGER::TStringInfo
&info
= d_ptr
->infos
[ r
];
379 if( !info
.Text2
.empty() )
382 info
.Text2
= info
.Text
;
384 setWindowModified( true );
386 markRowTranslated( r
);
389 void UXTEditor::markUntranslated()
391 int r
= d_ptr
->t
->currentRow();
395 STRING_MANAGER::TStringInfo
&info
= d_ptr
->infos
[ r
];
400 setWindowModified( true );
402 markRowUntranslated( r
);
405 void UXTEditor::onSaveClicked()
410 void UXTEditor::onSaveAsClicked()
412 QString path
= current_file
;
413 int idx
= path
.lastIndexOf( '/' );
417 path
= path
.left( idx
+ 1 );
419 QString file
= QFileDialog::getSaveFileName( this,
420 tr( "Save Uxt as.." ),
422 tr( "Uxt files ( *.uxt)" ) );
430 void UXTEditor::setHeaderText( const QString
&id
, const QString
&text
)
432 QTableWidgetItem
*h1
= new QTableWidgetItem( id
);
433 QTableWidgetItem
*h2
= new QTableWidgetItem( text
);
434 h1
->setTextAlignment( Qt::AlignLeft
);
435 h2
->setTextAlignment( Qt::AlignLeft
);
436 d_ptr
->t
->setHorizontalHeaderItem( 0, h1
);
437 d_ptr
->t
->setHorizontalHeaderItem( 1, h2
);
440 void UXTEditor::blockTableSignals( bool block
)
443 disconnect( d_ptr
->t
, SIGNAL( cellChanged( int, int ) ), this, SLOT( onCellChanged( int, int ) ) );
445 connect( d_ptr
->t
, SIGNAL( cellChanged( int, int ) ), this, SLOT( onCellChanged( int, int ) ) );
448 void UXTEditor::markRowTranslated( int row
)
450 blockTableSignals( true );
452 QTableWidgetItem
*item1
= d_ptr
->t
->item( row
, 0 );
453 QTableWidgetItem
*item2
= d_ptr
->t
->item( row
, 1 );
454 markItemTranslated( item1
);
455 markItemTranslated( item2
);
457 blockTableSignals( false );
460 void UXTEditor::markRowUntranslated( int row
)
462 blockTableSignals( true );
464 QTableWidgetItem
*item1
= d_ptr
->t
->item( row
, 0 );
465 QTableWidgetItem
*item2
= d_ptr
->t
->item( row
, 1 );
466 markItemUntranslated( item1
);
467 markItemUntranslated( item2
);
469 blockTableSignals( false );