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.
tqt3/tools/linguist/linguist/trwindow.cpp

2072 lines
64 KiB

/**********************************************************************
** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved.
**
** This file is part of TQt Linguist.
**
** This file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free
** Software Foundation and appearing in the files LICENSE.GPL2
** and LICENSE.GPL3 included in the packaging of this file.
** Alternatively you may (at your option) use any later version
** of the GNU General Public License if such license has been
** publicly approved by Trolltech ASA (or its successors, if any)
** and the KDE Free TQt Foundation.
**
** Please review the following information to ensure GNU General
** Public Licensing requirements will be met:
** http://trolltech.com/products/qt/licenses/licensing/opensource/.
** If you are unsure which license is appropriate for your use, please
** review the following information:
** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
** or contact the sales department at sales@trolltech.com.
**
** Licensees holding valid TQt Commercial licenses may use this file in
** accordance with the TQt Commercial License Agreement provided with
** the Software.
**
** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
** herein.
**
**********************************************************************/
/* TRANSLATOR TrWindow
This is the application's main window.
*/
#include "trwindow.h"
#include "listviews.h"
#include "finddialog.h"
#include "msgedit.h"
#include "phrasebookbox.h"
#include "printout.h"
#include "about.h"
#include "phraselv.h"
#include "statistics.h"
#include <ntqaccel.h>
#include <ntqaction.h>
#include <ntqapplication.h>
#include <ntqbitmap.h>
#include <ntqdict.h>
#include <ntqdockarea.h>
#include <ntqdockwindow.h>
#include <ntqfile.h>
#include <ntqfiledialog.h>
#include <ntqfileinfo.h>
#include <ntqheader.h>
#include <ntqlabel.h>
#include <ntqlayout.h>
#include <ntqmenubar.h>
#include <ntqmessagebox.h>
#include <ntqpopupmenu.h>
#include <ntqregexp.h>
#include <ntqsettings.h>
#include <ntqstatusbar.h>
#include <ntqtoolbar.h>
#include <ntqwhatsthis.h>
#include <ntqprocess.h>
#include <ntqassistantclient.h>
#include <stdlib.h>
#define pagecurl_mask_width 53
#define pagecurl_mask_height 51
static const uchar pagecurl_mask_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x0f, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0xfe, 0xff,
0xff, 0xff, 0xff, 0x0f, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00,
0xc0, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff,
0x0f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0xfe, 0xff,
0xff, 0xff, 0x0f, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00,
0xfc, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x0f,
0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0xf0, 0xff, 0xff,
0xff, 0x0f, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0xf0,
0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x0f, 0x00,
0x00, 0xe0, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff,
0x0f, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0xe0, 0xff,
0xff, 0xff, 0x0f, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00,
0xe0, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x0f,
0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0xe0, 0xff, 0xff,
0xff, 0x0f, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0xe0,
0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x0f, 0x00,
0x00, 0xe0, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff,
0x0f, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0xfc,
0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x0f, 0x00, 0x00,
0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x0f,
0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
0xe0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08 };
typedef TQValueList<MetaTranslatorMessage> TML;
static const int ErrorMS = 600000; // for error messages
static const int MessageMS = 2500;
TQPixmap * TrWindow::pxOn = 0;
TQPixmap * TrWindow::pxOff = 0;
TQPixmap * TrWindow::pxObsolete = 0;
TQPixmap * TrWindow::pxDanger = 0;
enum Ending { End_None, End_FullStop, End_Interrobang, End_Colon,
End_Ellipsis };
static Ending ending( TQString str )
{
str = str.simplifyWhiteSpace();
int ch = 0;
if ( !str.isEmpty() )
ch = str.right( 1 )[0].unicode();
switch ( ch ) {
case 0x002e: // full stop
if ( str.endsWith(TQString("...")) )
return End_Ellipsis;
else
return End_FullStop;
case 0x0589: // armenian full stop
case 0x06d4: // arabic full stop
case 0x3002: // ideographic full stop
return End_FullStop;
case 0x0021: // exclamation mark
case 0x003f: // question mark
case 0x00a1: // inverted exclamation mark
case 0x00bf: // inverted question mark
case 0x01c3: // latin letter retroflex click
case 0x037e: // greek question mark
case 0x061f: // arabic question mark
case 0x203c: // double exclamation mark
case 0x203d: // interrobang
case 0x2048: // question exclamation mark
case 0x2049: // exclamation question mark
case 0x2762: // heavy exclamation mark ornament
return End_Interrobang;
case 0x003a: // colon
return End_Colon;
case 0x2026: // horizontal ellipsis
return End_Ellipsis;
default:
return End_None;
}
}
class Action : public TQAction
{
public:
Action( TQPopupMenu *pop, const TQString& menuText, TQObject *receiver,
const char *member, const TQString &imageName = TQString::null,
int accel = 0, bool toggle = FALSE );
Action( TQPopupMenu *pop, const TQString& menuText, int accel = 0,
bool toggle = FALSE );
virtual void setWhatsThis( const TQString& whatsThis );
bool addToToolbar( TQToolBar *tb, const TQString& text );
};
Action::Action( TQPopupMenu *pop, const TQString& menuText, TQObject *receiver,
const char *member, const TQString &imageName, int accel,
bool toggle )
: TQAction( pop->parent(), (const char *) 0, toggle )
{
setMenuText( menuText );
setAccel( accel );
if ( !imageName.isEmpty() ) {
TQPixmap enabledPix = TQPixmap::fromMimeSource( imageName );
TQIconSet s( enabledPix );
if ( imageName != "whatsthis.xpm" ) {
TQPixmap disabledPix = TQPixmap::fromMimeSource( "d_" + imageName );
s.setPixmap( disabledPix, TQIconSet::Small, TQIconSet::Disabled );
}
setIconSet( s );
}
TQAction::addTo( pop );
connect( this, SIGNAL(activated()), receiver, member );
}
Action::Action( TQPopupMenu *pop, const TQString& menuText, int accel,
bool toggle )
: TQAction( pop->parent(), (const char *) 0, toggle )
{
TQAction::addTo( pop );
setMenuText( menuText );
setAccel( accel );
}
void Action::setWhatsThis( const TQString& whatsThis )
{
TQAction::setWhatsThis( whatsThis );
setStatusTip( whatsThis );
}
bool Action::addToToolbar( TQToolBar *tb, const TQString& text )
{
setText( text );
return TQAction::addTo( tb );
}
const TQPixmap TrWindow::pageCurl()
{
TQPixmap pixmap;
pixmap = TQPixmap::fromMimeSource( "pagecurl.png" );
if ( !pixmap.isNull() ) {
TQBitmap pageCurlMask( pagecurl_mask_width, pagecurl_mask_height,
pagecurl_mask_bits, TRUE );
pixmap.setMask( pageCurlMask );
}
return pixmap;
}
TrWindow::TrWindow()
: TQMainWindow( 0, "translation window", WType_TopLevel | WDestructiveClose )
{
#ifndef Q_WS_MACX
setIcon( TQPixmap::fromMimeSource( "appicon.png" ) );
#endif
// Create the application global listview symbols
pxOn = new TQPixmap( TQPixmap::fromMimeSource( "s_check_on.png" ) );
pxOff = new TQPixmap( TQPixmap::fromMimeSource( "s_check_off.png" ) );
pxObsolete = new TQPixmap( TQPixmap::fromMimeSource( "d_s_check_obs.png" ) );
pxDanger = new TQPixmap( TQPixmap::fromMimeSource( "s_check_danger.png" ) );
// Set up the Scope dock window
TQDockWindow * dwScope = new TQDockWindow( TQDockWindow::InDock, this,
"context");
dwScope->setResizeEnabled( TRUE );
dwScope->setCloseMode( TQDockWindow::Always );
addDockWindow( dwScope, tr("Context"), TQt::DockLeft );
dwScope->setCaption( tr("Context") );
dwScope->setFixedExtentWidth( 200 );
lv = new TQListView( dwScope, "context list view" );
lv->setShowSortIndicator( TRUE );
lv->setAllColumnsShowFocus( TRUE );
lv->header()->setStretchEnabled( TRUE, 1 );
TQFontMetrics fm( font() );
lv->addColumn( tr("Done"), fm.width( tr("Done") ) + 10 );
lv->addColumn( tr("Context") );
lv->addColumn( tr("Items"), 55 );
lv->setColumnAlignment( 0, TQt::AlignCenter );
lv->setColumnAlignment( 2, TQt::AlignRight );
lv->setSorting( 0 );
lv->setHScrollBarMode( TQScrollView::AlwaysOff );
dwScope->setWidget( lv );
messageIsShown = FALSE;
me = new MessageEditor( &tor, this, "message editor" );
setCentralWidget( me );
slv = me->sourceTextList();
plv = me->phraseList();
setupMenuBar();
setupToolBars();
progress = new TQLabel( statusBar(), "progress" );
statusBar()->addWidget( progress, 0, TRUE );
modified = new TQLabel( TQString(" %1 ").arg(tr("MOD")), statusBar(),
"modified?" );
statusBar()->addWidget( modified, 0, TRUE );
dirtyItem = -1;
numFinished = 0;
numNonobsolete = 0;
numMessages = 0;
updateProgress();
dirty = FALSE;
updateCaption();
phraseBooks.setAutoDelete( TRUE );
f = new FindDialog( FALSE, this, "find", FALSE );
f->setCaption( tr("TQt Linguist") );
h = new FindDialog( TRUE, this, "replace", FALSE );
h->setCaption( tr("TQt Linguist") );
findMatchCase = FALSE;
findWhere = 0;
foundItem = 0;
foundScope = 0;
foundWhere = 0;
foundOffset = 0;
connect( lv, SIGNAL(selectionChanged(TQListViewItem *)),
this, SLOT(showNewScope(TQListViewItem *)) );
connect( slv, SIGNAL(currentChanged(TQListViewItem *)),
this, SLOT(showNewCurrent(TQListViewItem *)) );
connect( slv, SIGNAL(clicked(TQListViewItem *, const TQPoint&, int)),
this, SLOT(showNewCurrent(TQListViewItem *)) );
connect( slv, SIGNAL(clicked(TQListViewItem *, const TQPoint&, int)),
this, SLOT(toggleFinished(TQListViewItem *, const TQPoint&, int)) );
connect( me, SIGNAL(translationChanged(const TQString&)),
this, SLOT(updateTranslation(const TQString&)) );
connect( me, SIGNAL(finished(bool)), this, SLOT(updateFinished(bool)) );
connect( me, SIGNAL(prevUnfinished()), this, SLOT(prevUnfinished()) );
connect( me, SIGNAL(nextUnfinished()), this, SLOT(nextUnfinished()) );
connect( me, SIGNAL(focusSourceList()), this, SLOT(focusSourceList()) );
connect( me, SIGNAL(focusPhraseList()), this, SLOT(focusPhraseList()) );
connect( f, SIGNAL(findNext(const TQString&, int, bool)),
this, SLOT(findNext(const TQString&, int, bool)) );
TQWhatsThis::add( lv, tr("This panel lists the source contexts.") );
TQWhatsThis::add( slv, tr("This panel lists the source texts. "
"Items that violate validation rules "
"are marked with a warning.") );
showNewCurrent( 0 );
TQSize as( tqApp->desktop()->size() );
as -= TQSize( 30, 30 );
resize( TQSize( 1000, 800 ).boundedTo( as ) );
readConfig();
stats = 0;
srcWords = 0;
srcChars = 0;
srcCharsSpc = 0;
}
TrWindow::~TrWindow()
{
writeConfig();
delete stats;
}
void TrWindow::openFile( const TQString& name )
{
if ( !name.isEmpty() ) {
statusBar()->message( tr("Loading...") );
tqApp->processEvents();
tor.clear();
if ( tor.load(name) ) {
slv->clear();
slv->repaint();
slv->viewport()->repaint();
slv->setUpdatesEnabled( FALSE );
slv->viewport()->setUpdatesEnabled( FALSE );
lv->clear();
lv->repaint();
lv->viewport()->repaint();
lv->setUpdatesEnabled( FALSE );
lv->viewport()->setUpdatesEnabled( FALSE );
setEnabled( FALSE );
numFinished = 0;
numNonobsolete = 0;
numMessages = 0;
foundScope = 0;
TML all = tor.messages();
TML::Iterator it;
TQDict<ContextLVI> contexts( 1009 );
srcWords = 0;
srcChars = 0;
srcCharsSpc = 0;
for ( it = all.begin(); it != all.end(); ++it ) {
tqApp->processEvents();
ContextLVI *c = contexts.find( TQString((*it).context()) );
if ( c == 0 ) {
c = new ContextLVI( lv, tor.toUnicode((*it).context(),
(*it).utf8()) );
contexts.insert( TQString((*it).context()), c );
}
if ( TQCString((*it).sourceText()) == ContextComment ) {
c->appendToComment( tor.toUnicode((*it).comment(),
(*it).utf8()) );
} else {
MessageLVI * tmp = new MessageLVI( slv, *it,
tor.toUnicode((*it).sourceText(),
(*it).utf8()),
tor.toUnicode((*it).comment(),
(*it).utf8()), c );
tmp->setDanger( danger(tmp->sourceText(),
tmp->translation()) &&
tmp->message().type() ==
MetaTranslatorMessage::Finished );
c->instantiateMessageItem( slv, tmp );
if ( (*it).type() != MetaTranslatorMessage::Obsolete ) {
numNonobsolete++;
if ( (*it).type() == MetaTranslatorMessage::Finished )
numFinished++;
doCharCounting( tmp->sourceText(), srcWords, srcChars, srcCharsSpc );
} else {
c->incrementObsoleteCount();
}
numMessages++;
}
c->updateStatus();
}
slv->viewport()->setUpdatesEnabled( TRUE );
slv->setUpdatesEnabled( TRUE );
lv->viewport()->setUpdatesEnabled( TRUE );
lv->setUpdatesEnabled( TRUE );
setEnabled( TRUE );
slv->repaint();
slv->viewport()->repaint();
lv->triggerUpdate();
updateProgress();
filename = name;
dirty = FALSE;
updateCaption();
me->showNothing();
doneAndNextAct->setEnabled( FALSE );
doneAndNextAlt->setEnabled( FALSE );
messageIsShown = FALSE;
statusBar()->message(
tr("%1 source phrase(s) loaded.").arg(numMessages),
MessageMS );
foundItem = 0;
foundWhere = 0;
foundOffset = 0;
if ( lv->childCount() > 0 ) {
findAct->setEnabled( TRUE );
findAgainAct->setEnabled( FALSE );
#ifdef notyet
replaceAct->setEnabled( TRUE );
#endif
lv->setCurrentItem( lv->firstChild() );
}
addRecentlyOpenedFile( name, recentFiles );
updateStatistics();
} else {
statusBar()->clear();
TQMessageBox::warning( this, tr("TQt Linguist"),
tr("Cannot open '%1'.").arg(name) );
}
}
}
void TrWindow::open()
{
if ( maybeSave() ) {
TQString newFilename = TQFileDialog::getOpenFileName( filename,
tr("TQt translation source (*.ts)\n"
"All files (*)"),
this, "open" );
openFile( newFilename );
}
}
void TrWindow::save()
{
if ( filename.isEmpty() )
return;
if ( tor.save(filename) ) {
dirty = FALSE;
updateCaption();
statusBar()->message( tr("File saved."), MessageMS );
} else {
TQMessageBox::warning( this, tr("TQt Linguist"), tr("Cannot save '%1'.")
.arg(filename) );
}
}
void TrWindow::saveAs()
{
TQString newFilename = TQFileDialog::getSaveFileName( filename,
tr( "TQt translation source (*.ts)\n"
"All files (*)"),
this, "save_as" );
if ( !newFilename.isEmpty() ) {
filename = newFilename;
save();
updateCaption();
}
}
void TrWindow::release()
{
TQString newFilename = filename;
newFilename.replace( TQRegExp(".ts$"), "" );
newFilename += TQString( ".qm" );
newFilename = TQFileDialog::getSaveFileName( newFilename,
tr("TQt message files for released applications (*.qm)\n"
"All files (*)"),
this, "release",
tr("Release") );
if ( !newFilename.isEmpty() ) {
if ( tor.release(newFilename) )
statusBar()->message( tr("File created."), MessageMS );
else
TQMessageBox::warning( this, tr("TQt Linguist"),
tr("Cannot save '%1'.").arg(newFilename) );
}
}
void TrWindow::print()
{
int pageNum = 0;
if ( printer.setup(this) ) {
TQApplication::setOverrideCursor( WaitCursor );
printer.setDocName( filename );
statusBar()->message( tr("Printing...") );
PrintOut pout( &printer );
ContextLVI *c = (ContextLVI *) lv->firstChild();
while ( c != 0 ) {
setCurrentContextItem( c );
pout.vskip();
pout.setRule( PrintOut::ThickRule );
pout.setGuide( c->context() );
pout.addBox( 100, tr("Context: %1").arg(c->context()),
PrintOut::Strong );
pout.flushLine();
pout.addBox( 4 );
pout.addBox( 92, c->comment(), PrintOut::Emphasis );
pout.flushLine();
pout.setRule( PrintOut::ThickRule );
MessageLVI *m = (MessageLVI *) slv->firstChild();
while ( m != 0 ) {
pout.setRule( PrintOut::ThinRule );
TQString type;
switch ( m->message().type() ) {
case MetaTranslatorMessage::Finished:
type = tr( "finished" );
break;
case MetaTranslatorMessage::Unfinished:
type = m->danger() ? tr( "unresolved" ) : TQString( "unfinished" );
break;
case MetaTranslatorMessage::Obsolete:
type = tr( "obsolete" );
break;
default:
type = TQString( "" );
}
pout.addBox( 40, m->sourceText() );
pout.addBox( 4 );
pout.addBox( 40, m->translation() );
pout.addBox( 4 );
pout.addBox( 12, type, PrintOut::Normal, TQt::AlignRight );
if ( !m->comment().isEmpty() ) {
pout.flushLine();
pout.addBox( 4 );
pout.addBox( 92, m->comment(), PrintOut::Emphasis );
}
pout.flushLine( TRUE );
if ( pout.pageNum() != pageNum ) {
pageNum = pout.pageNum();
statusBar()->message( tr("Printing... (page %1)")
.arg(pageNum) );
}
m = (MessageLVI *) m->nextSibling();
}
c = (ContextLVI *) c->nextSibling();
}
pout.flushLine( TRUE );
TQApplication::restoreOverrideCursor();
statusBar()->message( tr("Printing completed"), MessageMS );
} else {
statusBar()->message( tr("Printing aborted"), MessageMS );
}
}
void TrWindow::find()
{
h->hide();
f->show();
f->setActiveWindow();
f->raise();
}
void TrWindow::findAgain()
{
int pass = 0;
int oldItemNo = itemToIndex( slv, slv->currentItem() );
TQString delayedMsg;
TQListViewItem * j = foundScope;
TQListViewItem * k = indexToItem( slv, foundItem );
TQListViewItem * oldScope = lv->currentItem();
if ( lv->childCount() == 0 )
return;
#if 1
/*
As long as we don't implement highlighting of the text in the TQTextView,
we may have only one match per message.
*/
foundOffset = (int) 0x7fffffff;
#else
foundOffset++;
#endif
slv->setUpdatesEnabled( FALSE );
do {
// Iterate through every item in all contexts
if ( j == 0 ) {
j = lv->firstChild();
setCurrentContextItem( j );
if ( foundScope != 0 )
delayedMsg = tr("Search wrapped.");
}
if ( k == 0 )
k = slv->firstChild();
while ( k ) {
MessageLVI * m = (MessageLVI *) k;
switch ( foundWhere ) {
case 0:
foundWhere = FindDialog::SourceText;
foundOffset = 0;
// fall-through
case FindDialog::SourceText:
if ( searchItem( m->sourceText(), j, k ) ) {
f->hide();
if ( !delayedMsg.isEmpty() )
statusBar()->message( delayedMsg, MessageMS );
return;
}
foundWhere = FindDialog::Translations;
foundOffset = 0;
// fall-through
case FindDialog::Translations:
if ( searchItem( m->translation(), j, k ) ) {
f->hide();
if ( !delayedMsg.isEmpty() )
statusBar()->message( delayedMsg, MessageMS );
return;
}
foundWhere = FindDialog::Comments;
foundOffset = 0;
// fall-through
case FindDialog::Comments:
if ( searchItem( ((ContextLVI *) j)->fullContext(), j, k) ) {
f->hide();
if ( !delayedMsg.isEmpty() )
statusBar()->message( delayedMsg, MessageMS );
return;
}
foundWhere = 0;
foundOffset = 0;
}
k = k->nextSibling();
}
j = j->nextSibling();
if ( j ) {
setCurrentContextItem( j );
k = slv->firstChild();
}
} while ( pass++ != lv->childCount() );
// This is just to keep the current scope and source text item
// selected after a search failed.
if ( oldScope ) {
setCurrentContextItem( oldScope );
TQListViewItem * tmp = indexToItem( slv, oldItemNo );
if( tmp )
setCurrentMessageItem( tmp );
} else {
if( lv->firstChild() )
setCurrentContextItem( lv->firstChild() );
if( slv->firstChild() )
setCurrentMessageItem( slv->firstChild() );
}
slv->setUpdatesEnabled( TRUE );
slv->triggerUpdate();
tqApp->beep();
TQMessageBox::warning( this, tr("TQt Linguist"),
TQString( tr("Cannot find the string '%1'.") ).arg(findText) );
foundItem = 0;
foundWhere = 0;
foundOffset = 0;
}
void TrWindow::replace()
{
f->hide();
h->show();
h->setActiveWindow();
h->raise();
}
int TrWindow::itemToIndex( TQListView * view, TQListViewItem * item )
{
int no = 0;
TQListViewItem * tmp;
if( view && item ){
if( (tmp = view->firstChild()) != 0 )
do {
no++;
tmp = tmp->nextSibling();
} while( tmp && (tmp != item) );
}
return no;
}
TQListViewItem * TrWindow::indexToItem( TQListView * view, int index )
{
TQListViewItem * item = 0;
if ( view && index > 0 ) {
item = view->firstChild();
while( item && index-- > 0 )
item = item->nextSibling();
}
return item;
}
bool TrWindow::searchItem( const TQString & searchWhat, TQListViewItem * j,
TQListViewItem * k )
{
if ( (findWhere & foundWhere) != 0 ) {
foundOffset = searchWhat.find( findText, foundOffset, findMatchCase );
if ( foundOffset >= 0 ) {
foundItem = itemToIndex( slv, k );
foundScope = j;
setCurrentMessageItem( k );
slv->setUpdatesEnabled( TRUE );
slv->triggerUpdate();
return TRUE;
}
}
foundOffset = 0;
return FALSE;
}
void TrWindow::newPhraseBook()
{
TQString name;
for (;;) {
name = TQFileDialog::getSaveFileName( TQString::null,
tr("TQt phrase books (*.qph)\n"
"All files (*)"),
this, "new_phrasebook",
tr("Create New Phrase Book") );
if ( !TQFile::exists(name) )
break;
TQMessageBox::warning( this, tr("TQt Linguist"),
tr("A file called '%1' already exists."
" Please choose another name.").arg(name) );
}
if ( !name.isEmpty() ) {
PhraseBook pb;
if ( savePhraseBook(name, pb) ) {
if ( openPhraseBook(name) )
statusBar()->message( tr("Phrase book created."), MessageMS );
}
}
}
void TrWindow::openPhraseBook()
{
TQString phrasebooks( qInstallPathData() );
TQString name = TQFileDialog::getOpenFileName( phrasebooks + "/phrasebooks",
tr("TQt phrase books (*.qph)\n"
"All files (*)"),
this, "open_phrasebook",
tr("Open Phrase Book") );
if ( !name.isEmpty() && !phraseBookNames.contains(name) ) {
if ( openPhraseBook(name) ) {
int n = (int)(phraseBooks.at( phraseBooks.count() - 1 )->count());
statusBar()->message( tr("%1 phrase(s) loaded.").arg(n),
MessageMS );
}
}
}
void TrWindow::closePhraseBook( int id )
{
int index = closePhraseBookp->indexOf( id );
phraseBooks.remove( index );
phraseBookNames.remove( phraseBookNames.at(index) );
updatePhraseDict();
dirtyItem = index; // remove the item next time the menu is opened
editPhraseBookp->removeItem( editPhraseBookp->idAt(index) );
printPhraseBookp->removeItem( printPhraseBookp->idAt(index) );
}
void TrWindow::editPhraseBook( int id )
{
int index = editPhraseBookp->indexOf( id );
PhraseBookBox box( phraseBookNames[index], *phraseBooks.at(index), this,
"phrase book box", TRUE );
box.setCaption( tr("%1 - %2").arg(tr("TQt Linguist"))
.arg(friendlyPhraseBookName(index)) );
box.resize( 500, 300 );
box.exec();
*phraseBooks.at( index ) = box.phraseBook();
updatePhraseDict();
}
void TrWindow::printPhraseBook( int id )
{
int index = printPhraseBookp->indexOf( id );
int pageNum = 0;
if ( printer.setup(this) ) {
printer.setDocName( phraseBookNames[index] );
statusBar()->message( tr("Printing...") );
PrintOut pout( &printer );
PhraseBook *phraseBook = phraseBooks.at( index );
PhraseBook::Iterator p;
pout.setRule( PrintOut::ThinRule );
for ( p = phraseBook->begin(); p != phraseBook->end(); ++p ) {
pout.setGuide( (*p).source() );
pout.addBox( 29, (*p).source() );
pout.addBox( 4 );
pout.addBox( 29, (*p).target() );
pout.addBox( 4 );
pout.addBox( 34, (*p).definition(), PrintOut::Emphasis );
if ( pout.pageNum() != pageNum ) {
pageNum = pout.pageNum();
statusBar()->message( tr("Printing... (page %1)")
.arg(pageNum) );
}
pout.setRule( PrintOut::NoRule );
pout.flushLine( TRUE );
}
pout.flushLine( TRUE );
statusBar()->message( tr("Printing completed"), MessageMS );
} else {
statusBar()->message( tr("Printing aborted"), MessageMS );
}
}
void TrWindow::revertSorting()
{
lv->setSorting( 0 );
slv->setSorting( 0 );
}
void TrWindow::manual()
{
TQAssistantClient *ac = new TQAssistantClient( qInstallPathBins(), this );
ac->showPage( TQString( qInstallPathDocs() ) + "/html/linguist-manual.html" );
}
void TrWindow::about()
{
AboutDialog about( this, 0, TRUE );
about.versionLabel->setText( tr("Version %1").arg(TQT_VERSION_STR) );
about.exec();
}
void TrWindow::aboutTQt()
{
TQMessageBox::aboutTQt( this, tr("TQt Linguist") );
}
void TrWindow::setupPhrase()
{
bool enabled = !phraseBooks.isEmpty();
phrasep->setItemEnabled( closePhraseBookId, enabled );
phrasep->setItemEnabled( editPhraseBookId, enabled );
phrasep->setItemEnabled( printPhraseBookId, enabled );
}
void TrWindow::closeEvent( TQCloseEvent *e )
{
if ( maybeSave() )
e->accept();
else
e->ignore();
}
bool TrWindow::maybeSave()
{
if ( dirty ) {
switch ( TQMessageBox::information(this, tr("TQt Linguist"),
tr("Do you want to save '%1'?")
.arg(filename),
TQMessageBox::Yes | TQMessageBox::Default,
TQMessageBox::No,
TQMessageBox::Cancel | TQMessageBox::Escape ) )
{
case TQMessageBox::Cancel:
return FALSE;
case TQMessageBox::Yes:
save();
return !dirty;
case TQMessageBox::No:
break;
}
}
return TRUE;
}
void TrWindow::updateCaption()
{
TQString cap;
bool enable = !filename.isEmpty();
saveAct->setEnabled( enable );
saveAsAct->setEnabled( enable );
releaseAct->setEnabled( enable );
printAct->setEnabled( enable );
acceleratorsAct->setEnabled( enable );
endingPunctuationAct->setEnabled( enable );
phraseMatchesAct->setEnabled( enable );
revertSortingAct->setEnabled( enable );
if ( filename.isEmpty() )
cap = tr( "TQt Linguist by Trolltech" );
else
cap = tr( "%1 - %2" ).arg( tr("TQt Linguist by Trolltech") )
.arg( filename );
setCaption( cap );
modified->setEnabled( dirty );
}
//
// New scope selected - build a new list of source text items
// for that scope.
//
void TrWindow::showNewScope( TQListViewItem *item )
{
static ContextLVI * oldContext = 0;
if( item != 0 ) {
ContextLVI * c = (ContextLVI *) item;
bool upe = slv->isUpdatesEnabled();
slv->setUpdatesEnabled( FALSE );
slv->viewport()->setUpdatesEnabled( FALSE );
if ( oldContext != 0 ) {
MessageLVI * tmp;
slv->blockSignals( TRUE );
while ( (tmp = (MessageLVI *) slv->firstChild()) != 0 )
oldContext->appendMessageItem( slv, tmp );
slv->blockSignals( FALSE );
}
MessageLVI * tmp;
while ( c->messageItemsInList() ) {
tmp = c->takeMessageItem( c->messageItemsInList() - 1);
slv->insertItem( tmp );
tmp->updateTranslationText();
}
// Make sure that we update the source text and translation text. Use the first message in the new scope.
setCurrentMessageItem(slv->firstChild());
// This must be explicitly called since the signal is not emitted if the context only contains one item
showNewCurrent(slv->firstChild());
slv->viewport()->setUpdatesEnabled( upe );
slv->setUpdatesEnabled( upe );
if( upe )
slv->triggerUpdate();
oldContext = (ContextLVI *) item;
statusBar()->clear();
}
}
void TrWindow::showNewCurrent( TQListViewItem *item )
{
messageIsShown = (item != 0);
MessageLVI *m = (MessageLVI *) item;
ContextLVI *c = (ContextLVI *) m ? m->contextLVI() : 0;
if ( messageIsShown ) {
me->showMessage( m->sourceText(), m->comment(), c->fullContext(),
m->translation(), m->message().type(),
getPhrases(m->sourceText()) );
if ( (m->message().type() != MetaTranslatorMessage::Finished) &&
m->danger() )
danger( m->sourceText(), m->translation(), TRUE );
else
statusBar()->clear();
doneAndNextAct->setEnabled( m->message().type() !=
MetaTranslatorMessage::Obsolete );
} else {
if ( item == 0 )
me->showNothing();
else
me->showContext( c->fullContext(), c->finished() );
doneAndNextAct->setEnabled( FALSE );
}
doneAndNextAlt->setEnabled( doneAndNextAct->isEnabled() );
selectAllAct->setEnabled( messageIsShown );
}
void TrWindow::updateTranslation( const TQString& translation )
{
TQListViewItem *item = slv->currentItem();
if ( item != 0 ) {
MessageLVI *m = (MessageLVI *) item;
if ( translation != m->translation() ) {
bool dngr;
m->setTranslation( translation );
if ( m->finished() &&
(dngr = danger( m->sourceText(), m->translation(), TRUE )) ) {
numFinished -= 1;
m->setDanger( dngr );
m->setFinished( FALSE );
m->contextLVI()->updateStatus();
updateProgress();
}
tor.insert( m->message() );
if ( !dirty ) {
dirty = TRUE;
updateCaption();
}
m->updateTranslationText();
}
}
}
void TrWindow::updateFinished( bool finished )
{
TQListViewItem *item = slv->currentItem();
if ( item != 0 ) {
MessageLVI *m = (MessageLVI *) item;
if ( finished != m->finished() ) {
numFinished += finished ? +1 : -1;
updateProgress();
m->setFinished( finished );
bool oldDanger = m->danger();
m->setDanger( /*m->finished() &&*/
danger(m->sourceText(), m->translation(),
!oldDanger) );
if ( !oldDanger && m->danger() )
tqApp->beep();
tor.insert( m->message() );
if ( !dirty ) {
dirty = TRUE;
updateCaption();
}
}
}
}
void TrWindow::doneAndNext()
{
MessageLVI * m = (MessageLVI *) slv->currentItem();
bool dngr = FALSE;
if ( !m ) return;
dngr = danger( m->sourceText(), m->translation(), TRUE );
if ( !dngr ) {
me->finishAndNext();
m->contextLVI()->updateStatus();
} else {
if ( m->danger() != dngr )
m->setDanger( dngr );
tor.insert( m->message() );
if ( !dirty ) {
dirty = TRUE;
updateCaption();
}
tqApp->beep();
}
updateStatistics();
}
void TrWindow::toggleFinished( TQListViewItem *item, const TQPoint& /* p */,
int column )
{
if ( item != 0 && column == 0 ) {
MessageLVI *m = (MessageLVI *) item;
bool dngr = FALSE;
if ( m->message().type() == MetaTranslatorMessage::Unfinished ) {
dngr = danger( m->sourceText(), m->translation(), TRUE );
}
if ( !dngr && m->message().type() != MetaTranslatorMessage::Obsolete) {
setCurrentMessageItem( m );
me->setFinished( !m->finished() );
m->contextLVI()->updateStatus();
} else {
bool oldDanger = m->danger();
m->setDanger( danger(m->sourceText(), m->translation(),
!oldDanger) );
if ( !oldDanger && m->danger() )
tqApp->beep();
tor.insert( m->message() );
if ( !dirty ) {
dirty = TRUE;
updateCaption();
}
}
updateStatistics();
}
}
void TrWindow::nextUnfinished()
{
if ( nextUnfinishedAct->isEnabled() ) {
// Select a message to translate, grab the first available if
// there are no current selection.
TQListViewItem * cItem = lv->currentItem(); // context item
TQListViewItem * mItem = slv->currentItem(); // message item
// Make sure an item is selected from both the context and the
// message list.
if( (mItem == 0) && !(mItem = slv->firstChild()) ) {
if( (cItem == 0) && !(cItem = lv->firstChild()) ) {
statusBar()->message( tr("No phrase to translate."),
MessageMS );
tqApp->beep();
return;
} else {
showNewScope( cItem );
while( cItem && !(mItem = slv->firstChild()) ) {
// no children in this node - try next one
cItem = cItem->nextSibling();
showNewScope( cItem );
}
setCurrentContextItem( cItem );
if( mItem ) {
setCurrentMessageItem( mItem );
} else {
statusBar()->message( tr("No phrase to translate."),
MessageMS );
tqApp->beep();
return;
}
}
} else {
setCurrentMessageItem( mItem );
}
MessageLVI * m = (MessageLVI *) mItem;
MessageLVI * n;
ContextLVI * p = (ContextLVI *) cItem;
ContextLVI * q;
// Find the next Unfinished sibling within the same context.
m = (MessageLVI *) mItem->nextSibling();
n = m;
do {
if ( n == 0 )
break;
if ( n && !n->finished() && n != mItem ) {
setCurrentMessageItem( n );
return;
}
n = (MessageLVI *) n->nextSibling();
} while ( n != m );
// If all siblings are Finished or Obsolete, look in the first
// Unfinished context.
p = (ContextLVI *) p->nextSibling();
q = p;
do {
if ( q == 0 )
q = (ContextLVI *) lv->firstChild();
if ( q && !q->finished() ) {
showNewScope( q );
setCurrentContextItem( q );
n = (MessageLVI *) slv->firstChild();
while ( n && n->finished() )
n = (MessageLVI *) n->nextSibling();
if ( n && q ) {
setCurrentMessageItem( n );
showNewCurrent( n );
return;
}
}
q = (ContextLVI *) q->nextSibling();
} while ( q != p );
}
// If no Unfinished message is left, the user has finished the job. We
// congratulate on a job well done with this ringing bell.
statusBar()->message( tr("No untranslated phrases left."), MessageMS );
tqApp->beep();
}
static TQListViewItem * lastChild( TQListView * view )
{
if ( view ) {
TQListViewItem * ret, * tmp;
ret = view->firstChild();
while ( ret ) {
tmp = ret->nextSibling();
if ( tmp == 0 )
return ret;
ret = tmp;
}
}
return 0;
}
void TrWindow::prevUnfinished()
{
if ( prevUnfinishedAct->isEnabled() ) {
// Select a message to translate, grab the first available if
// there are no current selection.
TQListViewItem * cItem = lv->currentItem(); // context item
TQListViewItem * mItem = slv->currentItem(); // message item
// Make sure an item is selected from both the context and the
// message list.
if( (mItem == 0) && !(mItem = slv->firstChild()) ) {
if( (cItem == 0) && !(cItem = lv->firstChild()) ) {
statusBar()->message( tr("No phrase to translate."),
MessageMS );
tqApp->beep();
return;
} else {
showNewScope( cItem );
while( cItem && !(mItem = slv->firstChild()) ) {
// no children in this node - try next one
cItem = cItem->nextSibling();
showNewScope( cItem );
}
setCurrentContextItem( cItem );
if( mItem ) {
setCurrentMessageItem( cItem );
} else {
statusBar()->message( tr("No phrase to translate."),
MessageMS );
tqApp->beep();
return;
}
}
} else {
setCurrentMessageItem( mItem );
}
MessageLVI * m = (MessageLVI *) mItem;
MessageLVI * n;
ContextLVI * p = (ContextLVI *) cItem;
ContextLVI * q;
// Find the next Unfinished sibling within the same context.
n = m;
do {
n = (MessageLVI * ) n->itemAbove();
if ( n == 0 )
break;
if ( n && !n->finished() ) {
setCurrentMessageItem( n );
return;
}
} while ( !((ContextLVI *) cItem)->finished() && n != 0 );
// If all siblings are Finished or Obsolete, look in the prev
// Unfinished context.
q = p;
do {
q = (ContextLVI *) q->itemAbove();
if ( q == 0 )
q = (ContextLVI *) lastChild( lv );
if ( q && !q->finished() ) {
showNewScope( q );
setCurrentContextItem( q );
n = (MessageLVI *) lastChild( slv );
while ( n && n->finished() )
n = (MessageLVI *) n->itemAbove();
if ( n && q ) {
setCurrentMessageItem( n );
return;
}
}
} while ( q != 0 );
}
statusBar()->message( tr("No untranslated phrases left."), MessageMS );
tqApp->beep();
}
void TrWindow::prev()
{
TQListViewItem * cItem = lv->currentItem(); // context item
TQListViewItem * mItem = slv->currentItem(); // message item
TQListViewItem * tmp;
if ( !cItem ) {
cItem = lv->firstChild();
if ( !cItem ) return;
setCurrentContextItem( cItem );
}
if ( !mItem ) {
mItem = lastChild( slv );
if ( !mItem ) return;
setCurrentMessageItem( mItem );
} else {
if ( (tmp = mItem->itemAbove()) != 0 ) {
setCurrentMessageItem( tmp );
return;
} else {
if ( (tmp = cItem->itemAbove()) == 0 ) {
tmp = lastChild( lv );
}
if ( !tmp ) return;
setCurrentContextItem( tmp );
setCurrentMessageItem( lastChild( slv ) );
}
}
}
void TrWindow::next()
{
TQListViewItem * cItem = lv->currentItem(); // context item
TQListViewItem * mItem = slv->currentItem(); // message item
TQListViewItem * tmp;
if ( !cItem ) {
cItem = lv->firstChild();
if ( !cItem ) return;
setCurrentContextItem( cItem );
}
if ( !mItem ) {
mItem = slv->firstChild();
if ( !mItem ) return;
setCurrentMessageItem( mItem );
} else {
if ( (tmp = mItem->nextSibling()) != 0 ) {
setCurrentMessageItem( tmp );
return;
} else {
if ( (tmp = cItem->nextSibling()) == 0 ) {
tmp = lv->firstChild();
}
if ( !tmp ) return;
setCurrentContextItem( tmp );
setCurrentMessageItem( slv->firstChild() );
}
}
}
void TrWindow::findNext( const TQString& text, int where, bool matchCase )
{
findText = text;
if ( findText.isEmpty() )
findText = TQString( "magicwordthatyoushouldavoid" );
findWhere = where;
findMatchCase = matchCase;
findAgainAct->setEnabled( TRUE );
findAgain();
}
void TrWindow::revalidate()
{
ContextLVI *c = (ContextLVI *) lv->firstChild();
TQListViewItem * oldScope = lv->currentItem();
int oldItemNo = itemToIndex( slv, slv->currentItem() );
slv->setUpdatesEnabled( FALSE );
while ( c != 0 ) {
showNewScope( c );
MessageLVI *m = (MessageLVI *) slv->firstChild();
while ( m != 0 ) {
m->setDanger( danger(m->sourceText(), m->translation()) &&
m->message().type() == MetaTranslatorMessage::Finished );
m = (MessageLVI *) m->nextSibling();
}
c = (ContextLVI *) c->nextSibling();
}
if ( oldScope ){
showNewScope( oldScope );
TQListViewItem * tmp = indexToItem( slv, oldItemNo );
if( tmp )
setCurrentMessageItem( tmp );
}
slv->setUpdatesEnabled( TRUE );
slv->triggerUpdate();
}
TQString TrWindow::friendlyString( const TQString& str )
{
TQString f = str.lower();
f.replace( TQRegExp(TQString("[.,:;!?()-]")), TQString(" ") );
f.replace( "&", TQString("") );
f = f.simplifyWhiteSpace();
f = f.lower();
return f;
}
void TrWindow::setupMenuBar()
{
TQMenuBar * m = menuBar();
TQPopupMenu * filep = new TQPopupMenu( this );
TQPopupMenu * editp = new TQPopupMenu( this );
TQPopupMenu * translationp = new TQPopupMenu( this );
TQPopupMenu * validationp = new TQPopupMenu( this );
validationp->setCheckable( TRUE );
phrasep = new TQPopupMenu( this );
closePhraseBookp = new TQPopupMenu( this );
editPhraseBookp = new TQPopupMenu( this );
printPhraseBookp = new TQPopupMenu( this );
TQPopupMenu * viewp = new TQPopupMenu( this );
viewp->setCheckable( TRUE );
TQPopupMenu * helpp = new TQPopupMenu( this );
m->insertItem( tr("&File"), filep );
m->insertItem( tr("&Edit"), editp );
m->insertItem( tr("&Translation"), translationp );
m->insertItem( tr("V&alidation"), validationp );
m->insertItem( tr("&Phrases"), phrasep );
m->insertItem( tr("&View"), viewp );
m->insertSeparator();
m->insertItem( tr("&Help"), helpp );
connect( closePhraseBookp, SIGNAL(activated(int)),
this, SLOT(closePhraseBook(int)) );
connect( closePhraseBookp, SIGNAL(aboutToShow()),
this, SLOT(updateClosePhraseBook()) );
connect( editPhraseBookp, SIGNAL(activated(int)),
this, SLOT(editPhraseBook(int)) );
connect( printPhraseBookp, SIGNAL(activated(int)),
this, SLOT(printPhraseBook(int)) );
// File menu
openAct = new Action( filep, tr("&Open..."), this, SLOT(open()),
"fileopen.png", TQAccel::stringToKey(tr("Ctrl+O")) );
filep->insertSeparator();
saveAct = new Action( filep, tr("&Save"), this, SLOT(save()),
"filesave.png", TQAccel::stringToKey(tr("Ctrl+S")) );
saveAsAct = new Action( filep, tr("Save &As..."), this, SLOT(saveAs()) );
releaseAct = new Action( filep, tr("&Release..."), this, SLOT(release()) );
filep->insertSeparator();
printAct = new Action( filep, tr("&Print..."), this, SLOT(print()),
"print.png", TQAccel::stringToKey(tr("Ctrl+P")) );
filep->insertSeparator();
recentFilesMenu = new TQPopupMenu( this );
filep->insertItem( tr("Re&cently opened files"), recentFilesMenu );
connect( recentFilesMenu, SIGNAL(aboutToShow()), this,
SLOT(setupRecentFilesMenu()) );
connect( recentFilesMenu, SIGNAL(activated( int )), this,
SLOT(recentFileActivated( int )) );
filep->insertSeparator();
exitAct = new Action( filep, tr("E&xit"), this, SLOT(close()),
TQString::null, TQAccel::stringToKey(tr("Ctrl+Q")) );
// Edit menu
undoAct = new Action( editp, tr("&Undo"), me, SLOT(undo()),
"undo.png", TQAccel::stringToKey(tr("Ctrl+Z")) );
undoAct->setEnabled( FALSE );
connect( me, SIGNAL(undoAvailable(bool)), undoAct, SLOT(setEnabled(bool)) );
redoAct = new Action( editp, tr("&Redo"), me, SLOT(redo()),
"redo.png", TQAccel::stringToKey(tr("Ctrl+Y")) );
redoAct->setEnabled( FALSE );
connect( me, SIGNAL(redoAvailable(bool)), redoAct, SLOT(setEnabled(bool)) );
editp->insertSeparator();
cutAct = new Action( editp, tr("Cu&t"), me, SLOT(cut()),
"editcut.png", TQAccel::stringToKey(tr("Ctrl+X")) );
cutAct->setEnabled( FALSE );
connect( me, SIGNAL(cutAvailable(bool)), cutAct, SLOT(setEnabled(bool)) );
copyAct = new Action( editp, tr("&Copy"), me, SLOT(copy()),
"editcopy.png", TQAccel::stringToKey(tr("Ctrl+C")) );
copyAct->setEnabled( FALSE );
connect( me, SIGNAL(copyAvailable(bool)), copyAct, SLOT(setEnabled(bool)) );
pasteAct = new Action( editp, tr("&Paste"), me, SLOT(paste()),
"editpaste.png", TQAccel::stringToKey(tr("Ctrl+V")) );
pasteAct->setEnabled( FALSE );
connect( me, SIGNAL(pasteAvailable(bool)),
pasteAct, SLOT(setEnabled(bool)) );
selectAllAct = new Action( editp, tr("Select &All"), me, SLOT(selectAll()),
TQString::null, TQAccel::stringToKey(tr("Ctrl+A")) );
selectAllAct->setEnabled( FALSE );
editp->insertSeparator();
findAct = new Action( editp, tr("&Find..."), this, SLOT(find()),
"searchfind.png", TQAccel::stringToKey(tr("Ctrl+F")) );
findAct->setEnabled( FALSE );
findAgainAct = new Action( editp, tr("Find &Next"),
this, SLOT(findAgain()), TQString::null, Key_F3 );
findAgainAct->setEnabled( FALSE );
#ifdef notyet
replaceAct = new Action( editp, tr("&Replace..."), this, SLOT(replace()),
TQAccel::stringToKey(tr("Ctrl+H")) );
replaceAct->setEnabled( FALSE );
#endif
// Translation menu
// when updating the accelerators, remember the status bar
prevUnfinishedAct = new Action( translationp, tr("&Prev Unfinished"),
this, SLOT(prevUnfinished()),
"prevunfinished.png", TQAccel::stringToKey(tr("Ctrl+K")) );
nextUnfinishedAct = new Action( translationp, tr("&Next Unfinished"),
this, SLOT(nextUnfinished()),
"nextunfinished.png", TQAccel::stringToKey(tr("Ctrl+L")) );
prevAct = new Action( translationp, tr("P&rev"),
this, SLOT(prev()), "prev.png",
TQAccel::stringToKey(tr("Ctrl+Shift+K")) );
nextAct = new Action( translationp, tr("Ne&xt"),
this, SLOT(next()), "next.png",
TQAccel::stringToKey(tr("Ctrl+Shift+L")) );
doneAndNextAct = new Action( translationp, tr("Done and &Next"),
this, SLOT(doneAndNext()), "doneandnext.png",
TQAccel::stringToKey(tr("Ctrl+Enter")) );
doneAndNextAlt = new TQAction( this );
doneAndNextAlt->setAccel( TQAccel::stringToKey(tr("Ctrl+Return")) );
connect( doneAndNextAlt, SIGNAL(activated()), this, SLOT(doneAndNext()) );
beginFromSourceAct = new Action( translationp, tr("&Begin from Source"),
me, SLOT(beginFromSource()),
TQString::null, TQAccel::stringToKey(tr("Ctrl+B")) );
connect( me, SIGNAL(updateActions(bool)), beginFromSourceAct,
SLOT(setEnabled(bool)) );
// Phrasebook menu
newPhraseBookAct = new Action( phrasep, tr("&New Phrase Book..."),
this, SLOT(newPhraseBook()),
TQString::null, TQAccel::stringToKey(tr("Ctrl+N")) );
openPhraseBookAct = new Action( phrasep, tr("&Open Phrase Book..."),
this, SLOT(openPhraseBook()),
"book.png", TQAccel::stringToKey(tr("Ctrl+H")) );
closePhraseBookId = phrasep->insertItem( tr("&Close Phrase Book"),
closePhraseBookp );
phrasep->insertSeparator();
editPhraseBookId = phrasep->insertItem( tr("&Edit Phrase Book..."),
editPhraseBookp );
printPhraseBookId = phrasep->insertItem( tr("&Print Phrase Book..."),
printPhraseBookp );
connect( phrasep, SIGNAL(aboutToShow()), this, SLOT(setupPhrase()) );
// Validation menu
acceleratorsAct = new Action( validationp, tr("&Accelerators"),
this, SLOT(revalidate()), "accelerator.png", 0, TRUE );
acceleratorsAct->setOn( TRUE );
endingPunctuationAct = new Action( validationp, tr("&Ending Punctuation"),
this, SLOT(revalidate()), "punctuation.png", 0, TRUE );
endingPunctuationAct->setOn( TRUE );
phraseMatchesAct = new Action( validationp, tr("&Phrase Matches"),
this, SLOT(revalidate()), "phrase.png", 0, TRUE );
phraseMatchesAct->setOn( TRUE );
// View menu
revertSortingAct = new Action( viewp, tr("&Revert Sorting"),
this, SLOT(revertSorting()) );
doGuessesAct = new Action( viewp, tr("&Display guesses"),
this, SLOT(toggleGuessing()) );
doGuessesAct->setToggleAction( TRUE );
doGuessesAct->setOn( TRUE );
toggleStats = new Action( viewp, tr("&Statistics"), this, SLOT(toggleStatistics()) );
toggleStats->setToggleAction( TRUE );
viewp->insertSeparator();
viewp->insertItem( tr("Vie&ws"), createDockWindowMenu( NoToolBars ) );
viewp->insertItem( tr("&Toolbars"), createDockWindowMenu( OnlyToolBars ) );
// Help
manualAct = new Action( helpp, tr("&Manual"), this, SLOT(manual()), 0,
Key_F1 );
helpp->insertSeparator();
aboutAct = new Action( helpp, tr("&About"), this, SLOT(about()) );
aboutTQtAct = new Action( helpp, tr("About &TQt"), this, SLOT(aboutTQt()) );
helpp->insertSeparator();
whatsThisAct = new Action( helpp, tr("&What's This?"),
this, SLOT(whatsThis()), "whatsthis.xpm", SHIFT + Key_F1 );
openAct->setWhatsThis( tr("Open a TQt translation source file (TS file) for"
" editing.") );
saveAct->setWhatsThis( tr("Save changes made to this TQt translation "
"source file.") );
saveAsAct->setWhatsThis( tr("Save changes made to this TQt translation"
"source file into a new file.") );
releaseAct->setWhatsThis( tr("Create a TQt message file suitable for"
" released applications"
" from the current message file.") );
printAct->setWhatsThis( tr("Print a list of all the phrases in the current"
" TQt translation source file.") );
exitAct->setWhatsThis( tr("Close this window and exit.") );
undoAct->setWhatsThis( tr("Undo the last editing operation performed on the"
" translation.") );
redoAct->setWhatsThis( tr("Redo an undone editing operation performed on"
" the translation.") );
cutAct->setWhatsThis( tr("Copy the selected translation text to the"
" clipboard and deletes it.") );
copyAct->setWhatsThis( tr("Copy the selected translation text to the"
" clipboard.") );
pasteAct->setWhatsThis( tr("Paste the clipboard text into the"
" translation.") );
selectAllAct->setWhatsThis( tr("Select the whole translation text.") );
findAct->setWhatsThis( tr("Search for some text in the translation "
"source file.") );
findAgainAct->setWhatsThis( tr("Continue the search where it was left.") );
#ifdef notyet
replaceAct->setWhatsThis( tr("Search for some text in the translation"
" source file and replace it by another"
" text.") );
#endif
newPhraseBookAct->setWhatsThis( tr("Create a new phrase book.") );
openPhraseBookAct->setWhatsThis( tr("Open a phrase book to assist"
" translation.") );
acceleratorsAct->setWhatsThis( tr("Toggle validity checks of"
" accelerators.") );
endingPunctuationAct->setWhatsThis( tr("Toggle validity checks"
" of ending punctuation.") );
phraseMatchesAct->setWhatsThis( tr("Toggle checking that phrase"
" suggestions are used.") );
revertSortingAct->setWhatsThis( tr("Sort the items back in the same order"
" as in the message file.") );
doGuessesAct->setWhatsThis( tr("Set whether or not to display translation guesses.") );
manualAct->setWhatsThis( tr("Display the manual for %1.")
.arg(tr("TQt Linguist")) );
aboutAct->setWhatsThis( tr("Display information about %1.")
.arg(tr("TQt Linguist")) );
aboutTQtAct->setWhatsThis( tr("Display information about the TQt toolkit by"
" Trolltech.") );
whatsThisAct->setWhatsThis( tr("Enter What's This? mode.") );
beginFromSourceAct->setWhatsThis( tr("Copies the source text into"
" the translation field.") );
nextAct->setWhatsThis( tr("Moves to the next item.") );
prevAct->setWhatsThis( tr("Moves to the previous item.") );
nextUnfinishedAct->setWhatsThis( tr("Moves to the next unfinished item.") );
prevUnfinishedAct->setWhatsThis( tr("Moves to the previous unfinished item.") );
doneAndNextAct->setWhatsThis( tr("Marks this item as done and moves to the"
" next unfinished item.") );
doneAndNextAlt->setWhatsThis( doneAndNextAct->whatsThis() );
}
void TrWindow::setupToolBars()
{
TQToolBar *filet = new TQToolBar( tr("File"), this );
TQToolBar *editt = new TQToolBar( tr("Edit"), this );
TQToolBar *translationst = new TQToolBar( tr("Translation"), this );
TQToolBar *validationt = new TQToolBar( tr("Validation"), this );
TQToolBar *helpt = new TQToolBar( tr("Help"), this );
openAct->addToToolbar( filet, tr("Open") );
saveAct->addToToolbar( filet, tr("Save") );
printAct->addToToolbar( filet, tr("Print") );
filet->addSeparator();
openPhraseBookAct->addToToolbar( filet, tr("Open Phrase Book") );
undoAct->addToToolbar( editt, tr("Undo") );
redoAct->addToToolbar( editt, tr("Redo") );
editt->addSeparator();
cutAct->addToToolbar( editt, tr("Cut") );
copyAct->addToToolbar( editt, tr("Copy") );
pasteAct->addToToolbar( editt, tr("Paste") );
editt->addSeparator();
findAct->addToToolbar( editt, tr("Find") );
#ifdef notyet
replaceAct->addToToolbar( editt, tr("Replace") );
#endif
// beginFromSourceAct->addToToolbar( translationst,
// tr("Begin from Source"), "searchfind" );
prevAct->addToToolbar( translationst, tr("Prev") );
nextAct->addToToolbar( translationst, tr("Next") );
prevUnfinishedAct->addToToolbar( translationst, tr("Prev Unfinished") );
nextUnfinishedAct->addToToolbar( translationst, tr("Next Unfinished") );
doneAndNextAct->addToToolbar( translationst, tr("Done and Next") );
acceleratorsAct->addToToolbar( validationt, tr("Accelerators") );
endingPunctuationAct->addToToolbar( validationt, tr("Punctuation") );
phraseMatchesAct->addToToolbar( validationt, tr("Phrases") );
whatsThisAct->addToToolbar( helpt, tr("What's This?") );
}
void TrWindow::setCurrentContextItem( TQListViewItem *item )
{
lv->ensureItemVisible( item );
lv->setSelected( item, TRUE );
}
void TrWindow::setCurrentMessageItem( TQListViewItem *item )
{
slv->ensureItemVisible( item );
slv->setSelected( item, TRUE );
}
TQString TrWindow::friendlyPhraseBookName( int k )
{
return TQFileInfo( phraseBookNames[k] ).fileName();
}
bool TrWindow::openPhraseBook( const TQString& name )
{
PhraseBook *pb = new PhraseBook;
if ( !pb->load(name) ) {
TQMessageBox::warning( this, tr("TQt Linguist"),
tr("Cannot read from phrase book '%1'.")
.arg(name) );
return FALSE;
}
int index = (int) phraseBooks.count();
phraseBooks.append( pb );
phraseBookNames.append( name );
int id = closePhraseBookp->insertItem( friendlyPhraseBookName(index) );
closePhraseBookp->setWhatsThis( id, tr("Close this phrase book.") );
id = editPhraseBookp->insertItem( friendlyPhraseBookName(index) );
editPhraseBookp->setWhatsThis( id, tr("Allow you to add, modify, or delete"
" phrases of this phrase book.") );
id = printPhraseBookp->insertItem( friendlyPhraseBookName(index) );
printPhraseBookp->setWhatsThis( id, tr("Print the entries of the phrase"
" book.") );
updatePhraseDict();
return TRUE;
}
bool TrWindow::savePhraseBook( TQString& name, const PhraseBook& pb )
{
if ( !name.contains( ".qph" ) && !name.contains(".") )
name += ".qph";
if ( !pb.save(name) ) {
TQMessageBox::warning( this, tr("TQt Linguist"),
tr("Cannot create phrase book '%1'.")
.arg(name) );
return FALSE;
}
return TRUE;
}
void TrWindow::updateProgress()
{
if ( numNonobsolete == 0 )
progress->setText( TQString(" " " ") );
else
progress->setText( TQString(" %1/%2 ").arg(numFinished)
.arg(numNonobsolete) );
prevUnfinishedAct->setEnabled( numFinished != numNonobsolete );
nextUnfinishedAct->setEnabled( numFinished != numNonobsolete );
prevAct->setEnabled( lv->firstChild() != 0 );
nextAct->setEnabled( lv->firstChild() != 0 );
}
void TrWindow::updatePhraseDict()
{
TQPtrListIterator<PhraseBook> pb = phraseBooks;
PhraseBook::Iterator p;
PhraseBook *ent;
phraseDict.clear();
while ( pb.current() != 0 ) {
for ( p = (*pb)->begin(); p != (*pb)->end(); ++p ) {
TQString f = friendlyString( (*p).source() );
if ( f.length() > 0 ) {
f = TQStringList::split( TQChar(' '), f ).first();
ent = phraseDict.find( f );
if ( ent == 0 ) {
ent = new PhraseBook;
phraseDict.insert( f, ent );
}
ent->append( *p );
}
}
++pb;
}
revalidate();
}
PhraseBook TrWindow::getPhrases( const TQString& source )
{
PhraseBook phrases;
TQString f = friendlyString( source );
TQStringList lookupWords = TQStringList::split( TQChar(' '), f );
TQStringList::Iterator w;
PhraseBook::Iterator p;
for ( w = lookupWords.begin(); w != lookupWords.end(); ++w ) {
PhraseBook *ent = phraseDict.find( *w );
if ( ent != 0 ) {
for ( p = ent->begin(); p != ent->end(); ++p ) {
if ( f.find(friendlyString((*p).source())) >= 0 )
phrases.append( *p );
}
}
}
return phrases;
}
bool TrWindow::danger( const TQString& source, const TQString& translation,
bool verbose )
{
if ( acceleratorsAct->isOn() ) {
int sk = TQAccel::shortcutKey( source );
int tk = TQAccel::shortcutKey( translation );
if ( sk == 0 && tk != 0 ) {
if ( verbose )
statusBar()->message( tr("Accelerator possibly superfluous in"
" translation."), ErrorMS );
return TRUE;
} else if ( sk != 0 && tk == 0 ) {
if ( verbose )
statusBar()->message( tr("Accelerator possibly missing in"
" translation."), ErrorMS );
return TRUE;
}
}
if ( endingPunctuationAct->isOn() ) {
if ( ending(source) != ending(translation) ) {
if ( verbose )
statusBar()->message( tr("Translation does not end with the"
" same punctuation as the source"
" text."), ErrorMS );
return TRUE;
}
}
if ( phraseMatchesAct->isOn() ) {
TQString fsource = friendlyString( source );
TQString ftranslation = friendlyString( translation );
TQStringList lookupWords = TQStringList::split( TQChar(' '), fsource );
TQStringList::Iterator w;
PhraseBook::Iterator p;
for ( w = lookupWords.begin(); w != lookupWords.end(); ++w ) {
PhraseBook *ent = phraseDict.find( *w );
if ( ent != 0 ) {
for ( p = ent->begin(); p != ent->end(); ++p ) {
if ( fsource.find(friendlyString((*p).source())) < 0 ||
ftranslation.find(friendlyString((*p).target())) >= 0 )
break;
}
if ( p == ent->end() ) {
if ( verbose )
statusBar()->message( tr("A phrase book suggestion for"
" '%1' was ignored.")
.arg(*w), ErrorMS );
return TRUE;
}
}
}
}
if ( verbose )
statusBar()->clear();
return FALSE;
}
void TrWindow::readConfig()
{
TQString keybase( "/TQt Linguist/" +
TQString::number( (TQT_VERSION >> 16) & 0xff ) +
"." + TQString::number( (TQT_VERSION >> 8) & 0xff ) + "/" );
TQSettings config;
config.insertSearchPath( TQSettings::Windows, "/Trolltech" );
TQRect r( pos(), size() );
recentFiles = config.readListEntry( keybase + "RecentlyOpenedFiles" );
if ( !config.readBoolEntry( keybase + "Geometry/MainwindowMaximized", FALSE ) ) {
r.setX( config.readNumEntry( keybase + "Geometry/MainwindowX", r.x() ) );
r.setY( config.readNumEntry( keybase + "Geometry/MainwindowY", r.y() ) );
r.setWidth( config.readNumEntry( keybase + "Geometry/MainwindowWidth", r.width() ) );
r.setHeight( config.readNumEntry( keybase + "Geometry/MainwindowHeight", r.height() ) );
TQRect desk = TQApplication::desktop()->geometry();
TQRect inter = desk.intersect( r );
resize( r.size() );
if ( inter.width() * inter.height() > ( r.width() * r.height() / 20 ) ) {
move( r.topLeft() );
}
}
TQDockWindow * dw;
dw = (TQDockWindow *) lv->parent();
int place;
place = config.readNumEntry( keybase + "Geometry/ContextwindowInDock" );
r.setX( config.readNumEntry( keybase + "Geometry/ContextwindowX" ) );
r.setY( config.readNumEntry( keybase + "Geometry/ContextwindowY" ) );
r.setWidth( config.readNumEntry( keybase +
"Geometry/ContextwindowWidth" ) );
r.setHeight( config.readNumEntry( keybase +
"Geometry/ContextwindowHeight" ) );
if ( place == TQDockWindow::OutsideDock ) {
dw->undock();
dw->show();
}
dw->setGeometry( r );
dw = (TQDockWindow *) slv->parent();
place = config.readNumEntry( keybase + "Geometry/SourcewindowInDock" );
r.setX( config.readNumEntry( keybase + "Geometry/SourcewindowX" ) );
r.setY( config.readNumEntry( keybase + "Geometry/SourcewindowY" ) );
r.setWidth( config.readNumEntry( keybase +
"Geometry/SourcewindowWidth" ) );
r.setHeight( config.readNumEntry( keybase +
"Geometry/SourcewindowHeight" ) );
if ( place == TQDockWindow::OutsideDock ) {
dw->undock();
dw->show();
}
dw->setGeometry( r );
dw = (TQDockWindow *) plv->parent()->parent();
place = config.readNumEntry( keybase + "Geometry/PhrasewindowInDock" );
r.setX( config.readNumEntry( keybase + "Geometry/PhrasewindowX" ) );
r.setY( config.readNumEntry( keybase + "Geometry/PhrasewindowY" ) );
r.setWidth( config.readNumEntry( keybase +
"Geometry/PhrasewindowWidth" ) );
r.setHeight( config.readNumEntry( keybase +
"Geometry/PhrasewindowHeight" ) );
if ( place == TQDockWindow::OutsideDock ) {
dw->undock();
dw->show();
}
dw->setGeometry( r );
TQApplication::sendPostedEvents();
}
void TrWindow::writeConfig()
{
TQString keybase( "/TQt Linguist/" +
TQString::number( (TQT_VERSION >> 16) & 0xff ) +
"." + TQString::number( (TQT_VERSION >> 8) & 0xff ) + "/" );
TQSettings config;
config.insertSearchPath( TQSettings::Windows, "/Trolltech" );
config.writeEntry( keybase + "RecentlyOpenedFiles", recentFiles );
config.writeEntry( keybase + "Geometry/MainwindowMaximized", isMaximized() );
config.writeEntry( keybase + "Geometry/MainwindowX", x() );
config.writeEntry( keybase + "Geometry/MainwindowY", y() );
config.writeEntry( keybase + "Geometry/MainwindowWidth", width() );
config.writeEntry( keybase + "Geometry/MainwindowHeight", height() );
TQDockWindow * dw =(TQDockWindow *) lv->parent();
config.writeEntry( keybase + "Geometry/ContextwindowInDock", dw->place() );
config.writeEntry( keybase + "Geometry/ContextwindowX", dw->x() );
config.writeEntry( keybase + "Geometry/ContextwindowY", dw->y() );
config.writeEntry( keybase + "Geometry/ContextwindowWidth", dw->width() );
config.writeEntry( keybase + "Geometry/ContextwindowHeight", dw->height() );
dw =(TQDockWindow *) slv->parent();
config.writeEntry( keybase + "Geometry/SourcewindowInDock",
dw->place() );
config.writeEntry( keybase + "Geometry/SourcewindowX", dw->geometry().x() );
config.writeEntry( keybase + "Geometry/SourcewindowY", dw->geometry().y() );
config.writeEntry( keybase + "Geometry/SourcewindowWidth", dw->width() );
config.writeEntry( keybase + "Geometry/SourcewindowHeight", dw->height() );
dw =(TQDockWindow *) plv->parent()->parent();
config.writeEntry( keybase + "Geometry/PhrasewindowInDock",
dw->place() );
config.writeEntry( keybase + "Geometry/PhrasewindowX", dw->geometry().x() );
config.writeEntry( keybase + "Geometry/PhrasewindowY", dw->geometry().y() );
config.writeEntry( keybase + "Geometry/PhrasewindowWidth", dw->width() );
config.writeEntry( keybase + "Geometry/PhrasewindowHeight", dw->height() );
}
void TrWindow::setupRecentFilesMenu()
{
recentFilesMenu->clear();
int id = 0;
TQStringList::Iterator it = recentFiles.begin();
for ( ; it != recentFiles.end(); ++it )
{
recentFilesMenu->insertItem( *it, id );
id++;
}
}
void TrWindow::recentFileActivated( int id )
{
if ( id != -1 ) {
if ( maybeSave() )
openFile( *recentFiles.at( id ) );
}
}
void TrWindow::addRecentlyOpenedFile( const TQString &fn, TQStringList &lst )
{
if ( lst.find( fn ) != lst.end() )
return;
if ( lst.count() >= 10 )
lst.remove( lst.begin() );
lst << fn;
}
void TrWindow::toggleGuessing()
{
me->toggleGuessing();
}
void TrWindow::focusSourceList()
{
slv->setFocus();
}
void TrWindow::focusPhraseList()
{
plv->setFocus();
}
void TrWindow::updateClosePhraseBook()
{
if ( dirtyItem != -1 ) {
closePhraseBookp->removeItem( closePhraseBookp->idAt(dirtyItem) );
dirtyItem = -1;
}
}
void TrWindow::toggleStatistics()
{
if ( toggleStats->isOn() ) {
if ( !stats ) {
stats = new Statistics( this, "linguist_stats" );
connect( this, SIGNAL(statsChanged(int,int,int,int,int,int)), stats,
SLOT(updateStats(int,int,int,int,int,int)) );
connect( stats, SIGNAL(closed()), toggleStats, SLOT(toggle()) );
}
updateStatistics();
stats->show();
} else if ( stats ) {
stats->close();
}
}
void TrWindow::updateStatistics()
{
TQListViewItem * ci = lv->firstChild();
int trW = 0;
int trC = 0;
int trCS = 0;
while ( ci ) {
countStats( ci, ((ContextLVI *)ci)->firstMessageItem(), trW, trC, trCS );
ci = ci->nextSibling();
}
// ..and the items in the source list
countStats( 0, slv->firstChild(), trW, trC, trCS );
emit statsChanged( srcWords, srcChars, srcCharsSpc, trW, trC, trCS );
}
void TrWindow::countStats( TQListViewItem* ci, TQListViewItem* mi, int& trW, int& trC, int& trCS )
{
MessageLVI * m;
while ( mi ) {
m = (MessageLVI *) mi;
if ( m->finished() && !(m->message().type() == MetaTranslatorMessage::Obsolete) )
doCharCounting( m->translation(), trW, trC, trCS );
if ( ci )
mi = ((ContextLVI *)ci)->nextMessageItem();
else
mi = mi->nextSibling();
}
}
void TrWindow::doCharCounting( const TQString& text, int& trW, int& trC, int& trCS )
{
trCS += text.length();
bool inWord = FALSE;
for ( int i = 0; i < (int) text.length(); i++ ) {
if ( text[i].isLetterOrNumber() || text[i] == TQChar('_') ) {
if ( !inWord ) {
trW++;
inWord = TRUE;
}
} else {
inWord = FALSE;
}
if ( !text[i].isSpace() )
trC++;
}
}