diff options
Diffstat (limited to 'tools/linguist/linguist')
76 files changed, 8322 insertions, 0 deletions
diff --git a/tools/linguist/linguist/about.ui b/tools/linguist/linguist/about.ui new file mode 100644 index 0000000..b2fb6b4 --- /dev/null +++ b/tools/linguist/linguist/about.ui @@ -0,0 +1,223 @@ +<!DOCTYPE UI><UI version="3.1" stdsetdef="1"> +<class>AboutDialog</class> +<comment>********************************************************************* +** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved. +** +** This file is part of Qt 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 Qt 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 Qt Commercial licenses may use this file in +** accordance with the Qt 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. +** +*********************************************************************</comment> +<widget class="QDialog"> + <property name="name"> + <cstring>AboutDialog</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>484</width> + <height>640</height> + </rect> + </property> + <property name="caption"> + <string>Qt Linguist</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>PixmapLabel1</cstring> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>Plain</enum> + </property> + <property name="pixmap"> + <pixmap>splash.png</pixmap> + </property> + <property name="scaledContents"> + <bool>false</bool> + </property> + <property name="alignment"> + <set>AlignCenter</set> + </property> + <property name="hAlign" stdset="0"> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>versionLabel</cstring> + </property> + <property name="alignment"> + <set>AlignCenter</set> + </property> + <property name="hAlign" stdset="0"> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>TextLabel1_2</cstring> + </property> + <property name="text"> + <string>Copyright (C) 2000-2008 Trolltech ASA. All Rights Reserved.</string> + </property> + <property name="alignment"> + <set>AlignCenter</set> + </property> + <property name="hAlign" stdset="0"> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>TextLabel1_3</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string><p>Qt Commercial Edition license holders: This program is licensed to you under the terms of the Qt Commercial License Agreement. For details, see the file LICENSE that came with this software distribution.</p><p></p><p>Qt Open Source Edition users: This program is licensed to you under the terms of the GNU General Public License Version 2. For details, see the file LICENSE.GPL that came with this software distribution.</p><p>The program is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.</p></string> + </property> + <property name="alignment"> + <set>WordBreak|AlignVCenter|AlignLeft</set> + </property> + <property name="wordwrap" stdset="0"> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer3</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>Layout1</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <spacer> + <property name="name"> + <cstring>Spacer2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QPushButton"> + <property name="name"> + <cstring>PushButton1</cstring> + </property> + <property name="text"> + <string>OK</string> + </property> + <property name="autoDefault"> + <bool>true</bool> + </property> + <property name="default"> + <bool>true</bool> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer1</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + </vbox> +</widget> +<connections> + <connection> + <sender>PushButton1</sender> + <signal>clicked()</signal> + <receiver>AboutDialog</receiver> + <slot>accept()</slot> + </connection> +</connections> +<slots> + <slot access="protected">init()</slot> + <slot access="protected">destroy()</slot> +</slots> +<pixmapinproject/> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/tools/linguist/linguist/finddialog.cpp b/tools/linguist/linguist/finddialog.cpp new file mode 100644 index 0000000..385bd31 --- /dev/null +++ b/tools/linguist/linguist/finddialog.cpp @@ -0,0 +1,183 @@ +/********************************************************************** +** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved. +** +** This file is part of Qt 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 Qt 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 Qt Commercial licenses may use this file in +** accordance with the Qt 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 FindDialog + + Choose Edit|Find from the menu bar or press Ctrl+F to pop up the + Find dialog +*/ + +#include "finddialog.h" + +#include <qcheckbox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qlineedit.h> +#include <qpushbutton.h> +#include <qwhatsthis.h> + +FindDialog::FindDialog( bool replace, QWidget *parent, const char *name, + bool modal ) + : QDialog( parent, name, modal ) +{ + sourceText = 0; + + led = new QLineEdit( this, "find line edit" ); + QLabel *findWhat = new QLabel( led, tr("Fi&nd what:"), this, "find what" ); + QLabel *replaceWith = 0; + QPushButton *findNxt = new QPushButton( tr("&Find Next"), this, + "find next" ); + findNxt->setDefault( TRUE ); + connect( findNxt, SIGNAL(clicked()), this, SLOT(emitFindNext()) ); + QPushButton *cancel = new QPushButton( tr("Cancel"), this, "cancel find" ); + connect( cancel, SIGNAL(clicked()), this, SLOT(reject()) ); + + QVBoxLayout *bl = new QVBoxLayout( 6, "find button layout" ); + bl->addWidget( findNxt ); + + matchCase = new QCheckBox( tr("&Match case"), this, "find match case" ); + matchCase->setChecked( FALSE ); + + if ( replace ) { + QWhatsThis::add( this, tr("This window allows you to search and replace" + " some text in the translations.") ); + + red = new QLineEdit( this, "replace line edit" ); + replaceWith = new QLabel( red, tr("Replace &with:"), this, + "replace with" ); + setTabOrder( led, red ); + + QPushButton *replace = new QPushButton( tr("&Replace"), this, + "replace" ); + connect( replace, SIGNAL(clicked()), this, SLOT(emitReplace()) ); + QPushButton *replaceAll = new QPushButton( tr("Replace &All"), this, + "replace all" ); + connect( replaceAll, SIGNAL(clicked()), this, SLOT(emitReplaceAll()) ); + setTabOrder( findNxt, replace ); + setTabOrder( replace, replaceAll ); + setTabOrder( replaceAll, cancel ); + + QWhatsThis::add( replace, tr("Click here to replace the next occurrence" + " of the text you typed in.") ); + QWhatsThis::add( replaceAll, tr("Click here to replace all occurrences" + " of the text you typed in.") ); + + bl->addWidget( replace ); + bl->addWidget( replaceAll ); + + QGridLayout *gl = new QGridLayout( this, 4, 3, 11, 11, + "find outer layout" ); + gl->addWidget( findWhat, 0, 0 ); + gl->addWidget( led, 0, 1 ); + gl->addWidget( replaceWith, 1, 0 ); + gl->addWidget( red, 1, 1 ); + gl->addMultiCellWidget( matchCase, 2, 2, 0, 1 ); + gl->addMultiCell( bl, 0, 3, 3, 3 ); + } else { + QWhatsThis::add( this, tr("This window allows you to search for some" + " text in the translation source file.") ); + + sourceText = new QCheckBox( tr("&Source texts"), this, + "find in source texts" ); + sourceText->setChecked( TRUE ); + translations = new QCheckBox( tr("&Translations"), this, + "find in translations" ); + translations->setChecked( TRUE ); + comments = new QCheckBox( tr("&Comments"), this, "find in comments" ); + comments->setChecked( TRUE ); + + QWhatsThis::add( sourceText, tr("Source texts are searched when" + " checked.") ); + QWhatsThis::add( translations, tr("Translations are searched when" + " checked.") ); + QWhatsThis::add( comments, tr("Comments and contexts are searched when" + " checked.") ); + + QVBoxLayout *cl = new QVBoxLayout( 6, "find checkbox layout" ); + + QGridLayout *gl = new QGridLayout( this, 3, 4, 11, 11, + "find outer layout" ); + gl->addWidget( findWhat, 0, 0 ); + gl->addMultiCellWidget( led, 0, 0, 1, 2 ); + gl->addWidget( matchCase, 1, 2 ); + gl->addMultiCell( bl, 0, 2, 3, 3 ); + gl->addMultiCell( cl, 1, 2, 0, 1 ); + gl->setColStretch( 0, 0 ); + gl->addColSpacing( 1, 40 ); + gl->setColStretch( 2, 1 ); + gl->setColStretch( 3, 0 ); + + cl->addWidget( sourceText ); + cl->addWidget( translations ); + cl->addWidget( comments ); + cl->addStretch( 1 ); + } + + QWhatsThis::add( led, tr("Type in the text to search for.") ); + + QWhatsThis::add( matchCase, tr("Texts such as 'TeX' and 'tex' are" + " considered as different when checked.") ); + QWhatsThis::add( findNxt, tr("Click here to find the next occurrence of the" + " text you typed in.") ); + QWhatsThis::add( cancel, tr("Click here to close this window.") ); + + bl->addWidget( cancel ); + bl->addStretch( 1 ); + + resize( 400, 1 ); + setMaximumHeight( height() ); + + led->setFocus(); +} + +void FindDialog::emitFindNext() +{ + int where; + if ( sourceText != 0 ) + where = ( sourceText->isChecked() ? SourceText : 0 ) | + ( translations->isChecked() ? Translations : 0 ) | + ( comments->isChecked() ? Comments : 0 ); + else + where = Translations; + emit findNext( led->text(), where, matchCase->isChecked() ); +} + +void FindDialog::emitReplace() +{ + emit replace( led->text(), red->text(), matchCase->isChecked(), FALSE ); +} + +void FindDialog::emitReplaceAll() +{ + emit replace( led->text(), red->text(), matchCase->isChecked(), TRUE ); +} diff --git a/tools/linguist/linguist/finddialog.h b/tools/linguist/linguist/finddialog.h new file mode 100644 index 0000000..5d06e8e --- /dev/null +++ b/tools/linguist/linguist/finddialog.h @@ -0,0 +1,68 @@ +/********************************************************************** +** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved. +** +** This file is part of Qt 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 Qt 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 Qt Commercial licenses may use this file in +** accordance with the Qt 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. +** +**********************************************************************/ + +#ifndef FINDDIALOG_H +#define FINDDIALOG_H + +#include <qdialog.h> + +class QCheckBox; +class QLineEdit; + +class FindDialog : public QDialog +{ + Q_OBJECT +public: + enum { SourceText = 0x1, Translations = 0x2, Comments = 0x4 }; + + FindDialog( bool replace, QWidget *parent = 0, const char *name = 0, bool modal = FALSE ); + +signals: + void findNext( const QString& text, int where, bool matchCase ); + void replace( const QString& before, const QString& after, bool matchCase, bool all ); + +private slots: + void emitFindNext(); + void emitReplace(); + void emitReplaceAll(); + +private: + QLineEdit *led; + QLineEdit *red; + QCheckBox *sourceText; + QCheckBox *translations; + QCheckBox *comments; + QCheckBox *matchCase; +}; + +#endif diff --git a/tools/linguist/linguist/images/accelerator.png b/tools/linguist/linguist/images/accelerator.png Binary files differnew file mode 100644 index 0000000..173adb4 --- /dev/null +++ b/tools/linguist/linguist/images/accelerator.png diff --git a/tools/linguist/linguist/images/appicon.png b/tools/linguist/linguist/images/appicon.png Binary files differnew file mode 100644 index 0000000..90e143b --- /dev/null +++ b/tools/linguist/linguist/images/appicon.png diff --git a/tools/linguist/linguist/images/book.png b/tools/linguist/linguist/images/book.png Binary files differnew file mode 100644 index 0000000..dd850ab --- /dev/null +++ b/tools/linguist/linguist/images/book.png diff --git a/tools/linguist/linguist/images/d_accelerator.png b/tools/linguist/linguist/images/d_accelerator.png Binary files differnew file mode 100644 index 0000000..eaa2be6 --- /dev/null +++ b/tools/linguist/linguist/images/d_accelerator.png diff --git a/tools/linguist/linguist/images/d_book.png b/tools/linguist/linguist/images/d_book.png Binary files differnew file mode 100644 index 0000000..b61d611 --- /dev/null +++ b/tools/linguist/linguist/images/d_book.png diff --git a/tools/linguist/linguist/images/d_doneandnext.png b/tools/linguist/linguist/images/d_doneandnext.png Binary files differnew file mode 100644 index 0000000..e3a3fe1 --- /dev/null +++ b/tools/linguist/linguist/images/d_doneandnext.png diff --git a/tools/linguist/linguist/images/d_editcopy.png b/tools/linguist/linguist/images/d_editcopy.png Binary files differnew file mode 100644 index 0000000..578b591 --- /dev/null +++ b/tools/linguist/linguist/images/d_editcopy.png diff --git a/tools/linguist/linguist/images/d_editcut.png b/tools/linguist/linguist/images/d_editcut.png Binary files differnew file mode 100644 index 0000000..8d50ae0 --- /dev/null +++ b/tools/linguist/linguist/images/d_editcut.png diff --git a/tools/linguist/linguist/images/d_editpaste.png b/tools/linguist/linguist/images/d_editpaste.png Binary files differnew file mode 100644 index 0000000..78cab10 --- /dev/null +++ b/tools/linguist/linguist/images/d_editpaste.png diff --git a/tools/linguist/linguist/images/d_fileopen.png b/tools/linguist/linguist/images/d_fileopen.png Binary files differnew file mode 100644 index 0000000..ddbd33d --- /dev/null +++ b/tools/linguist/linguist/images/d_fileopen.png diff --git a/tools/linguist/linguist/images/d_filesave.png b/tools/linguist/linguist/images/d_filesave.png Binary files differnew file mode 100644 index 0000000..5d1476d --- /dev/null +++ b/tools/linguist/linguist/images/d_filesave.png diff --git a/tools/linguist/linguist/images/d_next.png b/tools/linguist/linguist/images/d_next.png Binary files differnew file mode 100644 index 0000000..f455e1f --- /dev/null +++ b/tools/linguist/linguist/images/d_next.png diff --git a/tools/linguist/linguist/images/d_nextunfinished.png b/tools/linguist/linguist/images/d_nextunfinished.png Binary files differnew file mode 100644 index 0000000..c2b06ec --- /dev/null +++ b/tools/linguist/linguist/images/d_nextunfinished.png diff --git a/tools/linguist/linguist/images/d_phrase.png b/tools/linguist/linguist/images/d_phrase.png Binary files differnew file mode 100644 index 0000000..acdd253 --- /dev/null +++ b/tools/linguist/linguist/images/d_phrase.png diff --git a/tools/linguist/linguist/images/d_prev.png b/tools/linguist/linguist/images/d_prev.png Binary files differnew file mode 100644 index 0000000..a68fe54 --- /dev/null +++ b/tools/linguist/linguist/images/d_prev.png diff --git a/tools/linguist/linguist/images/d_prevunfinished.png b/tools/linguist/linguist/images/d_prevunfinished.png Binary files differnew file mode 100644 index 0000000..ce956a7 --- /dev/null +++ b/tools/linguist/linguist/images/d_prevunfinished.png diff --git a/tools/linguist/linguist/images/d_print.png b/tools/linguist/linguist/images/d_print.png Binary files differnew file mode 100644 index 0000000..b2791a7 --- /dev/null +++ b/tools/linguist/linguist/images/d_print.png diff --git a/tools/linguist/linguist/images/d_punctuation.png b/tools/linguist/linguist/images/d_punctuation.png Binary files differnew file mode 100644 index 0000000..8eebab8 --- /dev/null +++ b/tools/linguist/linguist/images/d_punctuation.png diff --git a/tools/linguist/linguist/images/d_redo.png b/tools/linguist/linguist/images/d_redo.png Binary files differnew file mode 100644 index 0000000..6e993cc --- /dev/null +++ b/tools/linguist/linguist/images/d_redo.png diff --git a/tools/linguist/linguist/images/d_s_check_danger.png b/tools/linguist/linguist/images/d_s_check_danger.png Binary files differnew file mode 100644 index 0000000..3fadeb1 --- /dev/null +++ b/tools/linguist/linguist/images/d_s_check_danger.png diff --git a/tools/linguist/linguist/images/d_s_check_obs.png b/tools/linguist/linguist/images/d_s_check_obs.png Binary files differnew file mode 100644 index 0000000..4836e2f --- /dev/null +++ b/tools/linguist/linguist/images/d_s_check_obs.png diff --git a/tools/linguist/linguist/images/d_s_check_off.png b/tools/linguist/linguist/images/d_s_check_off.png Binary files differnew file mode 100644 index 0000000..58f7fb6 --- /dev/null +++ b/tools/linguist/linguist/images/d_s_check_off.png diff --git a/tools/linguist/linguist/images/d_s_check_on.png b/tools/linguist/linguist/images/d_s_check_on.png Binary files differnew file mode 100644 index 0000000..4836e2f --- /dev/null +++ b/tools/linguist/linguist/images/d_s_check_on.png diff --git a/tools/linguist/linguist/images/d_searchfind.png b/tools/linguist/linguist/images/d_searchfind.png Binary files differnew file mode 100644 index 0000000..e85e33f --- /dev/null +++ b/tools/linguist/linguist/images/d_searchfind.png diff --git a/tools/linguist/linguist/images/d_undo.png b/tools/linguist/linguist/images/d_undo.png Binary files differnew file mode 100644 index 0000000..22ac97f --- /dev/null +++ b/tools/linguist/linguist/images/d_undo.png diff --git a/tools/linguist/linguist/images/doneandnext.png b/tools/linguist/linguist/images/doneandnext.png Binary files differnew file mode 100644 index 0000000..1cf8888 --- /dev/null +++ b/tools/linguist/linguist/images/doneandnext.png diff --git a/tools/linguist/linguist/images/editcopy.png b/tools/linguist/linguist/images/editcopy.png Binary files differnew file mode 100644 index 0000000..804c98c --- /dev/null +++ b/tools/linguist/linguist/images/editcopy.png diff --git a/tools/linguist/linguist/images/editcut.png b/tools/linguist/linguist/images/editcut.png Binary files differnew file mode 100644 index 0000000..a911482 --- /dev/null +++ b/tools/linguist/linguist/images/editcut.png diff --git a/tools/linguist/linguist/images/editpaste.png b/tools/linguist/linguist/images/editpaste.png Binary files differnew file mode 100644 index 0000000..1938141 --- /dev/null +++ b/tools/linguist/linguist/images/editpaste.png diff --git a/tools/linguist/linguist/images/fileopen.png b/tools/linguist/linguist/images/fileopen.png Binary files differnew file mode 100644 index 0000000..3005290 --- /dev/null +++ b/tools/linguist/linguist/images/fileopen.png diff --git a/tools/linguist/linguist/images/filesave.png b/tools/linguist/linguist/images/filesave.png Binary files differnew file mode 100644 index 0000000..c137165 --- /dev/null +++ b/tools/linguist/linguist/images/filesave.png diff --git a/tools/linguist/linguist/images/next.png b/tools/linguist/linguist/images/next.png Binary files differnew file mode 100644 index 0000000..4b29ff4 --- /dev/null +++ b/tools/linguist/linguist/images/next.png diff --git a/tools/linguist/linguist/images/nextunfinished.png b/tools/linguist/linguist/images/nextunfinished.png Binary files differnew file mode 100644 index 0000000..9892b65 --- /dev/null +++ b/tools/linguist/linguist/images/nextunfinished.png diff --git a/tools/linguist/linguist/images/pagecurl.png b/tools/linguist/linguist/images/pagecurl.png Binary files differnew file mode 100644 index 0000000..2d3f2ff --- /dev/null +++ b/tools/linguist/linguist/images/pagecurl.png diff --git a/tools/linguist/linguist/images/phrase.png b/tools/linguist/linguist/images/phrase.png Binary files differnew file mode 100644 index 0000000..d7dfcb5 --- /dev/null +++ b/tools/linguist/linguist/images/phrase.png diff --git a/tools/linguist/linguist/images/prev.png b/tools/linguist/linguist/images/prev.png Binary files differnew file mode 100644 index 0000000..4e3556c --- /dev/null +++ b/tools/linguist/linguist/images/prev.png diff --git a/tools/linguist/linguist/images/prevunfinished.png b/tools/linguist/linguist/images/prevunfinished.png Binary files differnew file mode 100644 index 0000000..a3bed54 --- /dev/null +++ b/tools/linguist/linguist/images/prevunfinished.png diff --git a/tools/linguist/linguist/images/print.png b/tools/linguist/linguist/images/print.png Binary files differnew file mode 100644 index 0000000..cc083ed --- /dev/null +++ b/tools/linguist/linguist/images/print.png diff --git a/tools/linguist/linguist/images/punctuation.png b/tools/linguist/linguist/images/punctuation.png Binary files differnew file mode 100644 index 0000000..849d4a9 --- /dev/null +++ b/tools/linguist/linguist/images/punctuation.png diff --git a/tools/linguist/linguist/images/redo.png b/tools/linguist/linguist/images/redo.png Binary files differnew file mode 100644 index 0000000..abdad26 --- /dev/null +++ b/tools/linguist/linguist/images/redo.png diff --git a/tools/linguist/linguist/images/s_check_danger.png b/tools/linguist/linguist/images/s_check_danger.png Binary files differnew file mode 100644 index 0000000..7005304 --- /dev/null +++ b/tools/linguist/linguist/images/s_check_danger.png diff --git a/tools/linguist/linguist/images/s_check_obs.png b/tools/linguist/linguist/images/s_check_obs.png Binary files differnew file mode 100644 index 0000000..b171b2a --- /dev/null +++ b/tools/linguist/linguist/images/s_check_obs.png diff --git a/tools/linguist/linguist/images/s_check_off.png b/tools/linguist/linguist/images/s_check_off.png Binary files differnew file mode 100644 index 0000000..cf45bc0 --- /dev/null +++ b/tools/linguist/linguist/images/s_check_off.png diff --git a/tools/linguist/linguist/images/s_check_on.png b/tools/linguist/linguist/images/s_check_on.png Binary files differnew file mode 100644 index 0000000..b5238f7 --- /dev/null +++ b/tools/linguist/linguist/images/s_check_on.png diff --git a/tools/linguist/linguist/images/searchfind.png b/tools/linguist/linguist/images/searchfind.png Binary files differnew file mode 100644 index 0000000..3f369fd --- /dev/null +++ b/tools/linguist/linguist/images/searchfind.png diff --git a/tools/linguist/linguist/images/splash.png b/tools/linguist/linguist/images/splash.png Binary files differnew file mode 100644 index 0000000..8e80718 --- /dev/null +++ b/tools/linguist/linguist/images/splash.png diff --git a/tools/linguist/linguist/images/undo.png b/tools/linguist/linguist/images/undo.png Binary files differnew file mode 100644 index 0000000..839a823 --- /dev/null +++ b/tools/linguist/linguist/images/undo.png diff --git a/tools/linguist/linguist/images/whatsthis.xpm b/tools/linguist/linguist/images/whatsthis.xpm new file mode 100644 index 0000000..e45dc26 --- /dev/null +++ b/tools/linguist/linguist/images/whatsthis.xpm @@ -0,0 +1,24 @@ +/* XPM */ +static char *magick[] = { +/* columns rows colors chars-per-pixel */ +"16 16 3 1", +" c None", +"o c #000000000000", +"a c #000000008000", +/* pixels */ +"o aaaaa ", +"oo aaa aaa ", +"ooo aaa aaa", +"oooo aa aa", +"ooooo aa aa", +"oooooo a aaa", +"ooooooo aaa ", +"oooooooo aaa ", +"ooooooooo aaa ", +"ooooo aaa ", +"oo ooo ", +"o ooo aaa ", +" ooo aaa ", +" ooo ", +" ooo ", +" ooo "}; diff --git a/tools/linguist/linguist/linguist.icns b/tools/linguist/linguist/linguist.icns Binary files differnew file mode 100644 index 0000000..f51565e --- /dev/null +++ b/tools/linguist/linguist/linguist.icns diff --git a/tools/linguist/linguist/linguist.ico b/tools/linguist/linguist/linguist.ico Binary files differnew file mode 100644 index 0000000..2816c7c --- /dev/null +++ b/tools/linguist/linguist/linguist.ico diff --git a/tools/linguist/linguist/linguist.pro b/tools/linguist/linguist/linguist.pro new file mode 100644 index 0000000..da4d782 --- /dev/null +++ b/tools/linguist/linguist/linguist.pro @@ -0,0 +1,109 @@ +TEMPLATE = app +LANGUAGE = C++ +CONFIG += qt warn_on + + +SOURCES += finddialog.cpp \ + main.cpp \ + msgedit.cpp \ + phrase.cpp \ + phrasebookbox.cpp \ + phraselv.cpp \ + printout.cpp \ + simtexth.cpp \ + trwindow.cpp \ + listviews.cpp \ + ../shared/metatranslator.cpp +HEADERS += finddialog.h \ + msgedit.h \ + phrase.h \ + phrasebookbox.h \ + phraselv.h \ + printout.h \ + trwindow.h \ + listviews.h \ + ../shared/metatranslator.h + + +TRANSLATIONS = linguist_de.ts \ + linguist_fr.ts + +DEFINES += QT_INTERNAL_XML +include( ../../../src/qt_professional.pri ) + +DESTDIR = ../../../bin +TARGET = linguist + + +LIBS += -L$$QT_BUILD_TREE/lib -lqassistantclient + +win32:RC_FILE = linguist.rc + +mac { + staticlib:CONFIG -= global_init_link_order #yuck + RC_FILE = linguist.icns +} + +PROJECTNAME = Qt Linguist + +target.path=$$bins.path +INSTALLS += target + +linguisttranslations.files = *.qm +linguisttranslations.path = $$translations.path +INSTALLS += linguisttranslations + +phrasebooks.path=$$data.path/phrasebooks +phrasebooks.files = ../phrasebooks/* +INSTALLS += phrasebooks +FORMS = about.ui \ + statistics.ui +IMAGES = images/accelerator.png \ + images/book.png \ + images/s_check_danger.png \ + images/s_check_obs.png \ + images/s_check_off.png \ + images/s_check_on.png \ + images/d_s_check_danger.png \ + images/d_s_check_obs.png \ + images/d_s_check_off.png \ + images/d_s_check_on.png \ + images/d_accelerator.png \ + images/d_book.png \ + images/d_doneandnext.png \ + images/d_editcopy.png \ + images/d_editcut.png \ + images/d_editpaste.png \ + images/d_fileopen.png \ + images/d_filesave.png \ + images/d_next.png \ + images/d_nextunfinished.png \ + images/d_prev.png \ + images/d_prevunfinished.png \ + images/d_phrase.png \ + images/d_print.png \ + images/d_punctuation.png \ + images/d_redo.png \ + images/d_searchfind.png \ + images/d_undo.png \ + images/doneandnext.png \ + images/editcopy.png \ + images/editcut.png \ + images/editpaste.png \ + images/punctuation.png \ + images/fileopen.png \ + images/filesave.png \ + images/appicon.png \ + images/next.png \ + images/nextunfinished.png \ + images/pagecurl.png \ + images/phrase.png \ + images/prev.png \ + images/prevunfinished.png \ + images/print.png \ + images/redo.png \ + images/searchfind.png \ + images/splash.png \ + images/undo.png \ + images/whatsthis.xpm +INCLUDEPATH += ../shared diff --git a/tools/linguist/linguist/linguist.rc b/tools/linguist/linguist/linguist.rc new file mode 100644 index 0000000..865e021 --- /dev/null +++ b/tools/linguist/linguist/linguist.rc @@ -0,0 +1 @@ +IDI_ICON1 ICON DISCARDABLE "linguist.ico" diff --git a/tools/linguist/linguist/linguist_de.ts b/tools/linguist/linguist/linguist_de.ts new file mode 100644 index 0000000..06d818b --- /dev/null +++ b/tools/linguist/linguist/linguist_de.ts @@ -0,0 +1,993 @@ +<!DOCTYPE TS><TS> +<context> + <name>AboutDialog</name> + <message> + <source>Qt Linguist</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Copyright (C) 2000-2008 Trolltech ASA. All Rights Reserved.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source><p>This program is licensed to you under the terms of the GNU General Public License Version 2 as published by the Free Software Foundation. This gives you legal permission to copy, distribute and/or modify this software under certain conditions. For details, see the file 'LICENSE.GPL' that came with this software distribution. If you did not get the file, send email to info@trolltech.com.</p> +<p>The program is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.</p></source> + <translation type="unfinished"></translation> + </message> + <message> + <source>OK</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>EditorPage</name> + <message> + <source>Source text</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Translation</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>FindDialog</name> + <comment>Choose Edit|Find from the menu bar or press Ctrl+F to pop up the Find dialog</comment> + <message> + <source>Fi&nd what:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Find Next</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Cancel</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Match case</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>This window allows you to search and replace some text in the translations.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Replace &with:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Replace</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Replace &All</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Click here to replace the next occurrence of the text you typed in.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Click here to replace all occurrences of the text you typed in.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>This window allows you to search for some text in the translation source file.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Source texts</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Translations</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Comments</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Source texts are searched when checked.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Translations are searched when checked.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Comments and contexts are searched when checked.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Type in the text to search for.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Texts such as 'TeX' and 'tex' are considered as different when checked.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Click here to find the next occurrence of the text you typed in.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Click here to close this window.</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>MessageEditor</name> + <message> + <source>bell</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>backspace</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>new page</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>new line</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>carriage return</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>tab</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Source text</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Done</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Translation</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Phrases</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Phrases and guesses:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>This whole panel allows you to view and edit the translation of some source text.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>This area shows the source text.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>This area shows a comment that may guide you, and the context in which the text occurs.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>This is where you can enter or modify the translation of some source text.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Guess</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Guess (%1)</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>PageCurl</name> + <message> + <source>Next unfinished phrase</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Previous unfinished phrase</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>PhraseBookBox</name> + <comment>Go to Phrase > Edit Phrase Book... The dialog that pops up is a PhraseBookBox.</comment> + <message> + <source>S&ource phrase:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Translation:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Definition:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&New Phrase</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Remove Phrase</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Save</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Close</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>This window allows you to add, modify, or delete phrases in a phrase book.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>This is the phrase in the source language.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>This is the phrase in the target language corresponding to the source phrase.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>This is a definition for the source phrase.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Click here to add the phrase to the phrase book.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Click here to remove the phrase from the phrase book.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Click here to save the changes made.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Click here to close this window.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Qt Linguist</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Cannot save phrase book '%1'.</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>PhraseLV</name> + <comment>The phrase list in the right panel of the main window (with Source phrase, Target phrase, and Definition in its header) is a PhraseLV object.</comment> + <message> + <source>(New Phrase)</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>This is a list of phrase entries relevant to the source text. Each phrase is supplemented with a suggested translation and a definition.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source><p><u>%1:</u>&nbsp;&nbsp;%2</p><p><u>%3:</u>&nbsp;&nbsp;%4</p><p><u>%5:</u>&nbsp;&nbsp;%6</p></source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Source phrase</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Translation</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Definition</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>QObject</name> + <message> + <source>Qt Linguist</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>TrWindow</name> + <comment>This is the application's main window.</comment> + <message> + <source>Context</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Done</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Items</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>MOD</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Qt Linguist</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>This panel lists the source contexts.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>This panel lists the source texts. Items that violate validation rules are marked with a warning.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Loading...</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>%1 source phrase(s) loaded.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Cannot open '%1'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Qt translation source (*.ts) +All files (*)</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>File saved.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Cannot save '%1'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Qt message files for released applications (*.qm) +All files (*)</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Release</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>File created.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Printing...</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Context: %1</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>finished</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>unresolved</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>obsolete</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Printing... (page %1)</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Printing completed</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Printing aborted</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Search wrapped.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Cannot find the string '%1'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Qt phrase books (*.qph) +All files (*)</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Create New Phrase Book</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>A file called '%1' already exists. Please choose another name.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Phrase book created.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>%1 phrase(s) loaded.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>%1 - %2</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Do you want to save '%1'?</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Qt Linguist by Trolltech</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>No phrase to translate.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>No untranslated phrases left.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&File</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Edit</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Translation</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>V&alidation</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Phrases</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&View</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Help</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Open...</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+O</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Save</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+S</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Save &As...</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Release...</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Print...</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+P</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Re&cently opened files</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>E&xit</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+Q</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Undo</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+Z</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Redo</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+Y</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Cu&t</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+X</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Copy</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+C</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Paste</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+V</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Select &All</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+A</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Find...</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+F</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Find &Next</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Replace...</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+H</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Prev Unfinished</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+K</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Next Unfinished</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+L</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>P&rev</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+Shift+K</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ne&xt</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+Shift+L</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Done and &Next</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+Enter</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+Return</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Begin from Source</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+B</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&New Phrase Book...</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+N</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Open Phrase Book...</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Close Phrase Book</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Edit Phrase Book...</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Print Phrase Book...</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Accelerators</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Ending Punctuation</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Phrase Matches</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Revert Sorting</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Display guesses</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Vie&ws</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Toolbars</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Manual</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&About</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>About &Qt</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&What's This?</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Open a Qt translation source file (TS file) for editing.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Save changes made to this Qt translation source file.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Save changes made to this Qt translationsource file into a new file.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Create a Qt message file suitable for released applications from the current message file.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Print a list of all the phrases in the current Qt translation source file.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Close this window and exit.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Undo the last editing operation performed on the translation.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Redo an undone editing operation performed on the translation.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Copy the selected translation text to the clipboard and deletes it.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Copy the selected translation text to the clipboard.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Paste the clipboard text into the translation.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Select the whole translation text.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Search for some text in the translation source file.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Continue the search where it was left.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Search for some text in the translation source file and replace it by another text.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Create a new phrase book.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Open a phrase book to assist translation.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Toggle validity checks of accelerators.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Toggle validity checks of ending punctuation.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Toggle checking that phrase suggestions are used.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Sort the items back in the same order as in the message file.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Set whether or not to display translation guesses.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Display the manual for %1.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Display information about %1.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Display information about the Qt toolkit by Trolltech.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Enter What's This? mode.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Copies the source text into the translation field.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Moves to the next item.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Moves to the previous item.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Moves to the next unfinished item.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Moves to the previous unfinished item.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Marks this item as done and moves to the next unfinished item.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>File</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Edit</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Translation</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Validation</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Help</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Open</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Save</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Print</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Open Phrase Book</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Undo</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Redo</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Cut</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Copy</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Paste</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Find</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Replace</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Prev</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Next</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Prev Unfinished</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Next Unfinished</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Done and Next</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Accelerators</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Punctuation</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Phrases</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>What's This?</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Cannot read from phrase book '%1'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Close this phrase book.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Allow you to add, modify, or delete phrases of this phrase book.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Print the entries of the phrase book.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Cannot create phrase book '%1'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Accelerator possibly superfluous in translation.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Accelerator possibly missing in translation.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Translation does not end with the same punctuation as the source text.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>A phrase book suggestion for '%1' was ignored.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>...</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Version %1</source> + <translation type="unfinished"></translation> + </message> +</context> +</TS> diff --git a/tools/linguist/linguist/linguist_fr.ts b/tools/linguist/linguist/linguist_fr.ts new file mode 100644 index 0000000..06d818b --- /dev/null +++ b/tools/linguist/linguist/linguist_fr.ts @@ -0,0 +1,993 @@ +<!DOCTYPE TS><TS> +<context> + <name>AboutDialog</name> + <message> + <source>Qt Linguist</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Copyright (C) 2000-2008 Trolltech ASA. All Rights Reserved.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source><p>This program is licensed to you under the terms of the GNU General Public License Version 2 as published by the Free Software Foundation. This gives you legal permission to copy, distribute and/or modify this software under certain conditions. For details, see the file 'LICENSE.GPL' that came with this software distribution. If you did not get the file, send email to info@trolltech.com.</p> +<p>The program is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.</p></source> + <translation type="unfinished"></translation> + </message> + <message> + <source>OK</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>EditorPage</name> + <message> + <source>Source text</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Translation</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>FindDialog</name> + <comment>Choose Edit|Find from the menu bar or press Ctrl+F to pop up the Find dialog</comment> + <message> + <source>Fi&nd what:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Find Next</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Cancel</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Match case</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>This window allows you to search and replace some text in the translations.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Replace &with:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Replace</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Replace &All</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Click here to replace the next occurrence of the text you typed in.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Click here to replace all occurrences of the text you typed in.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>This window allows you to search for some text in the translation source file.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Source texts</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Translations</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Comments</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Source texts are searched when checked.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Translations are searched when checked.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Comments and contexts are searched when checked.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Type in the text to search for.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Texts such as 'TeX' and 'tex' are considered as different when checked.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Click here to find the next occurrence of the text you typed in.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Click here to close this window.</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>MessageEditor</name> + <message> + <source>bell</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>backspace</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>new page</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>new line</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>carriage return</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>tab</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Source text</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Done</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Translation</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Phrases</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Phrases and guesses:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>This whole panel allows you to view and edit the translation of some source text.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>This area shows the source text.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>This area shows a comment that may guide you, and the context in which the text occurs.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>This is where you can enter or modify the translation of some source text.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Guess</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Guess (%1)</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>PageCurl</name> + <message> + <source>Next unfinished phrase</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Previous unfinished phrase</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>PhraseBookBox</name> + <comment>Go to Phrase > Edit Phrase Book... The dialog that pops up is a PhraseBookBox.</comment> + <message> + <source>S&ource phrase:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Translation:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Definition:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&New Phrase</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Remove Phrase</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Save</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Close</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>This window allows you to add, modify, or delete phrases in a phrase book.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>This is the phrase in the source language.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>This is the phrase in the target language corresponding to the source phrase.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>This is a definition for the source phrase.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Click here to add the phrase to the phrase book.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Click here to remove the phrase from the phrase book.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Click here to save the changes made.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Click here to close this window.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Qt Linguist</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Cannot save phrase book '%1'.</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>PhraseLV</name> + <comment>The phrase list in the right panel of the main window (with Source phrase, Target phrase, and Definition in its header) is a PhraseLV object.</comment> + <message> + <source>(New Phrase)</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>This is a list of phrase entries relevant to the source text. Each phrase is supplemented with a suggested translation and a definition.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source><p><u>%1:</u>&nbsp;&nbsp;%2</p><p><u>%3:</u>&nbsp;&nbsp;%4</p><p><u>%5:</u>&nbsp;&nbsp;%6</p></source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Source phrase</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Translation</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Definition</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>QObject</name> + <message> + <source>Qt Linguist</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>TrWindow</name> + <comment>This is the application's main window.</comment> + <message> + <source>Context</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Done</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Items</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>MOD</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Qt Linguist</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>This panel lists the source contexts.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>This panel lists the source texts. Items that violate validation rules are marked with a warning.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Loading...</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>%1 source phrase(s) loaded.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Cannot open '%1'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Qt translation source (*.ts) +All files (*)</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>File saved.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Cannot save '%1'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Qt message files for released applications (*.qm) +All files (*)</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Release</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>File created.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Printing...</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Context: %1</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>finished</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>unresolved</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>obsolete</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Printing... (page %1)</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Printing completed</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Printing aborted</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Search wrapped.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Cannot find the string '%1'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Qt phrase books (*.qph) +All files (*)</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Create New Phrase Book</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>A file called '%1' already exists. Please choose another name.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Phrase book created.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>%1 phrase(s) loaded.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>%1 - %2</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Do you want to save '%1'?</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Qt Linguist by Trolltech</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>No phrase to translate.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>No untranslated phrases left.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&File</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Edit</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Translation</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>V&alidation</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Phrases</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&View</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Help</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Open...</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+O</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Save</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+S</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Save &As...</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Release...</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Print...</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+P</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Re&cently opened files</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>E&xit</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+Q</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Undo</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+Z</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Redo</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+Y</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Cu&t</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+X</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Copy</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+C</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Paste</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+V</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Select &All</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+A</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Find...</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+F</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Find &Next</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Replace...</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+H</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Prev Unfinished</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+K</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Next Unfinished</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+L</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>P&rev</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+Shift+K</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ne&xt</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+Shift+L</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Done and &Next</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+Enter</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+Return</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Begin from Source</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+B</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&New Phrase Book...</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+N</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Open Phrase Book...</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Close Phrase Book</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Edit Phrase Book...</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Print Phrase Book...</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Accelerators</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Ending Punctuation</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Phrase Matches</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Revert Sorting</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Display guesses</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Vie&ws</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Toolbars</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Manual</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&About</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>About &Qt</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&What's This?</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Open a Qt translation source file (TS file) for editing.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Save changes made to this Qt translation source file.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Save changes made to this Qt translationsource file into a new file.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Create a Qt message file suitable for released applications from the current message file.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Print a list of all the phrases in the current Qt translation source file.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Close this window and exit.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Undo the last editing operation performed on the translation.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Redo an undone editing operation performed on the translation.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Copy the selected translation text to the clipboard and deletes it.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Copy the selected translation text to the clipboard.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Paste the clipboard text into the translation.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Select the whole translation text.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Search for some text in the translation source file.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Continue the search where it was left.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Search for some text in the translation source file and replace it by another text.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Create a new phrase book.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Open a phrase book to assist translation.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Toggle validity checks of accelerators.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Toggle validity checks of ending punctuation.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Toggle checking that phrase suggestions are used.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Sort the items back in the same order as in the message file.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Set whether or not to display translation guesses.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Display the manual for %1.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Display information about %1.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Display information about the Qt toolkit by Trolltech.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Enter What's This? mode.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Copies the source text into the translation field.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Moves to the next item.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Moves to the previous item.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Moves to the next unfinished item.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Moves to the previous unfinished item.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Marks this item as done and moves to the next unfinished item.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>File</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Edit</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Translation</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Validation</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Help</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Open</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Save</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Print</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Open Phrase Book</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Undo</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Redo</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Cut</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Copy</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Paste</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Find</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Replace</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Prev</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Next</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Prev Unfinished</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Next Unfinished</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Done and Next</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Accelerators</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Punctuation</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Phrases</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>What's This?</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Cannot read from phrase book '%1'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Close this phrase book.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Allow you to add, modify, or delete phrases of this phrase book.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Print the entries of the phrase book.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Cannot create phrase book '%1'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Accelerator possibly superfluous in translation.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Accelerator possibly missing in translation.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Translation does not end with the same punctuation as the source text.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>A phrase book suggestion for '%1' was ignored.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>...</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Version %1</source> + <translation type="unfinished"></translation> + </message> +</context> +</TS> diff --git a/tools/linguist/linguist/listviews.cpp b/tools/linguist/linguist/listviews.cpp new file mode 100644 index 0000000..6bf67fd --- /dev/null +++ b/tools/linguist/linguist/listviews.cpp @@ -0,0 +1,350 @@ +/********************************************************************** +** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved. +** +** This file is part of Qt 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 Qt 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 Qt Commercial licenses may use this file in +** accordance with the Qt 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. +** +**********************************************************************/ + +#include "listviews.h" + +#include <qpainter.h> + +static const int Text0MaxLen = 150; +static const int Text1MaxLen = 150; + +/* + LVI implementation +*/ + +static QString rho( int n ) +{ + QString s; + s.sprintf( "%.10d", n ); + return s; +} + +int LVI::count = 0; + +LVI::LVI( QListView * parent, QString text ) + : QListViewItem( parent, text ) +{ + setText( 0, rho(count++) ); +} + +LVI::LVI( QListViewItem * parent, QString text ) + : QListViewItem( parent, text ) +{ + setText( 0, rho(count++) ); +} + +/* + This is a cut-down version of QListViewItem::paintCell() - + it is needed to produce the effect we want on obsolete items + */ +void LVI::drawObsoleteText( QPainter * p, const QColorGroup & cg, int column, + int width, int align ) +{ + QListView * lv = listView(); + int marg = lv ? lv->itemMargin() : 1; + int r = marg; + p->fillRect( 0, 0, width, height(), cg.brush( QColorGroup::Base ) ); + if ( isSelected() && (column==0 || listView()->allColumnsShowFocus()) ) + p->fillRect( r - marg, 0, width - r + marg, height(), + cg.brush( QColorGroup::Highlight ) ); + + // Do the ellipsis thingy + QString t = text( column ); + QString tmp; + int i = 0; + if ( p->fontMetrics().width( t ) > width ) { + tmp = "..."; + while ( p->fontMetrics().width( tmp + t[i] ) < width ) + tmp += t[ i++ ]; + tmp.remove( (uint)0, 3 ); + if ( tmp.isEmpty() ) + tmp = t.left( 1 ); + tmp += "..."; + t = tmp; + } + if ( isSelected() ) + p->setPen( lv->palette().disabled().highlightedText() ); + else + p->setPen( lv->palette().disabled().text() ); + + if ( !t.isEmpty() ) { + p->drawText( r, 0, width-marg-r, height(), + align | AlignVCenter | SingleLine, t ); + } + +} + +int LVI::compare( QListViewItem *other, int column, bool ascending ) const +{ + QString thisKey = key( column, ascending ); + QString otherKey = other->key( column, ascending ); + + if ( thisKey.contains('&') || otherKey.contains('&') ) { + QString nicerThisKey = thisKey; + QString nicerOtherKey = otherKey; + + nicerThisKey.replace( "&", "" ); + nicerOtherKey.replace( "&", "" ); + + int delta = nicerThisKey.localeAwareCompare( nicerOtherKey ); + if ( delta != 0 ) + return delta; + } + return thisKey.localeAwareCompare( otherKey ); +} + +static QString fixEllipsis( const QString & str, int len ) +{ + QString shortened = str.simplifyWhiteSpace(); + if ( (int) shortened.length() > len ) { + QString dots = TrWindow::tr( "..." ); + shortened.truncate( len - dots.length() ); + shortened.append( dots ); + } + return shortened; +} + +/* + MessageLVI implementation +*/ +MessageLVI::MessageLVI( QListView *parent, + const MetaTranslatorMessage & message, + const QString& text, const QString& comment, + ContextLVI * c ) + : LVI( parent ), m( message ), tx( text ), com( comment ), ctxt( c ) +{ + if ( m.translation().isEmpty() ) { + QString t = ""; + m.setTranslation( t ); + } + setText( 1, fixEllipsis( text, Text0MaxLen ) ); + fini = TRUE; + d = FALSE; + + if( m.type() == MetaTranslatorMessage::Unfinished ) + setFinished( FALSE ); +} + +void MessageLVI::updateTranslationText() +{ + setText( 2, fixEllipsis( m.translation(), Text1MaxLen ) ); +} + +void MessageLVI::paintCell( QPainter * p, const QColorGroup & cg, int column, + int width, int align ) +{ + if ( column == 0 ) { + int x = (width/2) - TrWindow::pxOn->width()/2; + int y = (height()/2) - TrWindow::pxOn->height()/2; + + int marg = listView() ? listView()->itemMargin() : 1; + int r = marg; + + if ( isSelected() ) + p->fillRect( r - marg, 0, width - r + marg, height(), + cg.brush( QColorGroup::Highlight ) ); + else + p->fillRect( 0, 0, width, height(), + cg.brush( QColorGroup::Base ) ); + + if ( m.type() == MetaTranslatorMessage::Unfinished && danger() ) + p->drawPixmap( x, y, *TrWindow::pxDanger ); + else if ( m.type() == MetaTranslatorMessage::Finished ) + p->drawPixmap( x, y, *TrWindow::pxOn ); + else if ( m.type() == MetaTranslatorMessage::Unfinished ) + p->drawPixmap( x, y, *TrWindow::pxOff ); + else if ( m.type() == MetaTranslatorMessage::Obsolete ) + p->drawPixmap( x, y, *TrWindow::pxObsolete ); + } else { + if ( m.type() == MetaTranslatorMessage::Obsolete ) + drawObsoleteText( p, cg, column, width, align ); + else + QListViewItem::paintCell( p, cg, column, width, align ); + } +} + + +void MessageLVI::setTranslation( const QString& translation ) +{ + m.setTranslation( translation ); +} + +void MessageLVI::setFinished( bool finished ) +{ + if ( !fini && finished ) { + m.setType( MetaTranslatorMessage::Finished ); + repaint(); + ctxt->decrementUnfinishedCount(); + } else if ( fini && !finished ) { + m.setType( MetaTranslatorMessage::Unfinished ); + repaint(); + ctxt->incrementUnfinishedCount(); + } + fini = finished; +} + +void MessageLVI::setDanger( bool danger ) +{ + if ( !d && danger ) { + ctxt->incrementDangerCount(); + repaint(); + } else if ( d && !danger ) { + ctxt->decrementDangerCount(); + repaint(); + } + d = danger; +} + +QString MessageLVI::context() const +{ + return QString( m.context() ); +} + +MetaTranslatorMessage MessageLVI::message() const +{ + return m; +} + +/* + ContextLVI implementation +*/ +ContextLVI::ContextLVI( QListView *lv, const QString& context ) + : LVI( lv ), com( "" ) +{ + messageItems.setAutoDelete( TRUE ); + + unfinishedCount = 0; + dangerCount = 0; + obsoleteCount = 0; + itemCount = 0; + setText( 1, context ); +} + +void ContextLVI::instantiateMessageItem( QListView * lv, MessageLVI * i ) +{ + itemCount++; + appendMessageItem( lv, i ); +} + +void ContextLVI::appendMessageItem( QListView * lv, MessageLVI * i ) +{ + lv->takeItem( i ); + messageItems.append( i ); +} + +void ContextLVI::updateStatus() +{ + QString s; + s.sprintf( "%d/%d", itemCount - unfinishedCount - obsoleteCount, + itemCount - obsoleteCount ); + setText( 2, s ); +} + +void ContextLVI::paintCell( QPainter * p, const QColorGroup & cg, int column, + int width, int align ) +{ + if ( column == 0 ) { + int x = (width/2) - TrWindow::pxOn->width()/2; + int y = (height()/2) - TrWindow::pxOn->height()/2; + + int marg = listView() ? listView()->itemMargin() : 1; + int r = marg; + + if ( isSelected() ) + p->fillRect( r - marg, 0, width - r + marg, height(), + cg.brush( QColorGroup::Highlight ) ); + else + p->fillRect( 0, 0, width, height(), + cg.brush( QColorGroup::Base ) ); + + if ( isContextObsolete() ) + p->drawPixmap( x, y, *TrWindow::pxObsolete ); + else if ( unfinishedCount == 0 ) + p->drawPixmap( x, y, *TrWindow::pxOn ); + else + p->drawPixmap( x, y, *TrWindow::pxOff ); + + } else { + if ( isContextObsolete() ) + drawObsoleteText( p, cg, column, width, align ); + else + QListViewItem::paintCell( p, cg, column, width, align ); + } +} + +void ContextLVI::appendToComment( const QString& x ) +{ + if ( !com.isEmpty() ) + com += QString( "\n\n" ); + com += x; +} + +void ContextLVI::incrementUnfinishedCount() +{ + if ( unfinishedCount++ == 0 ) + repaint(); +} + +void ContextLVI::decrementUnfinishedCount() +{ + if ( --unfinishedCount == 0 ) + repaint(); +} + +void ContextLVI::incrementDangerCount() +{ + if ( dangerCount++ == 0 ) + repaint(); +} + +void ContextLVI::decrementDangerCount() +{ + if ( --dangerCount == 0 ) + repaint(); +} + +void ContextLVI::incrementObsoleteCount() +{ + if ( obsoleteCount++ == 0 ) + repaint(); +} + +bool ContextLVI::isContextObsolete() +{ + return (obsoleteCount == itemCount); +} + +QString ContextLVI::fullContext() const +{ + return comment().stripWhiteSpace(); +} diff --git a/tools/linguist/linguist/listviews.h b/tools/linguist/linguist/listviews.h new file mode 100644 index 0000000..f843aa3 --- /dev/null +++ b/tools/linguist/linguist/listviews.h @@ -0,0 +1,135 @@ +/********************************************************************** +** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved. +** +** This file is part of Qt 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 Qt 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 Qt Commercial licenses may use this file in +** accordance with the Qt 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. +** +**********************************************************************/ + +#ifndef LISTVIEWS_H +#define LISTVIEWS_H + +#include "msgedit.h" + +#include <qstring.h> +#include <qptrlist.h> +#include <qregexp.h> +#include <qlistview.h> + +class LVI : public QListViewItem +{ +public: + LVI( QListView *parent, QString text = QString::null ); + LVI( QListViewItem *parent, QString text = QString::null ); + virtual int compare( QListViewItem *other, int column, + bool ascending ) const; + virtual bool danger() const { return FALSE; } + +protected: + void drawObsoleteText( QPainter * p, const QColorGroup & cg, int column, + int width, int align ); + +private: + static int count; +}; + +class MessageLVI; +class ContextLVI : public LVI +{ +public: + ContextLVI( QListView *lv, const QString& context ); + + virtual bool danger() const { return dangerCount > 0; } + + void appendToComment( const QString& x ); + void incrementUnfinishedCount(); + void decrementUnfinishedCount(); + void incrementDangerCount(); + void decrementDangerCount(); + void incrementObsoleteCount(); + bool isContextObsolete(); + void updateStatus(); + + QString context() const { return text( 1 ); } + QString comment() const { return com; } + QString fullContext() const; + bool finished() const { return unfinishedCount == 0; } + + MessageLVI * firstMessageItem() { return messageItems.first(); } + MessageLVI * nextMessageItem() { return messageItems.next(); } + MessageLVI * takeMessageItem( int i ) { return messageItems.take( i ); } + void appendMessageItem( QListView * lv, MessageLVI * i ); + void instantiateMessageItem( QListView * lv, MessageLVI * i ); + int messageItemsInList() { return messageItems.count(); } + + void paintCell( QPainter * p, const QColorGroup & cg, int column, + int width, int align ); +private: + QPtrList<MessageLVI> messageItems; + QString com; + int unfinishedCount; + int dangerCount; + int obsoleteCount; + int itemCount; +}; + +class MessageLVI : public LVI +{ +public: + MessageLVI( QListView *parent, const MetaTranslatorMessage & message, + const QString& text, const QString& comment, ContextLVI * c ); + + virtual bool danger() const { return d; } + + void setTranslation( const QString& translation ); + void setFinished( bool finished ); + void setDanger( bool danger ); + + void setContextLVI( ContextLVI * c ) { ctxt = c; } + ContextLVI * contextLVI() const { return ctxt; } + void updateTranslationText(); + + QString context() const; + QString sourceText() const { return tx; } + QString comment() const { return com; } + QString translation() const { return m.translation(); } + bool finished() const { return fini; } + MetaTranslatorMessage message() const; + + void paintCell( QPainter * p, const QColorGroup & cg, int column, + int width, int align ); +private: + MetaTranslatorMessage m; + QString tx; + QString com; + bool fini; + bool d; + ContextLVI * ctxt; +}; + +#endif diff --git a/tools/linguist/linguist/main.cpp b/tools/linguist/linguist/main.cpp new file mode 100644 index 0000000..e9490af --- /dev/null +++ b/tools/linguist/linguist/main.cpp @@ -0,0 +1,89 @@ +/********************************************************************** +** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved. +** +** This file is part of Qt 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 Qt 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 Qt Commercial licenses may use this file in +** accordance with the Qt 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. +** +**********************************************************************/ + +#include "trwindow.h" + +#include <qapplication.h> +#include <qlabel.h> +#include <qpixmap.h> +#include <qtimer.h> +#include <qtextcodec.h> +#include <qtranslator.h> +#include <qsettings.h> +#include <qsplashscreen.h> + +int main( int argc, char **argv ) +{ + QApplication app( argc, argv ); + QApplication::setOverrideCursor( Qt::waitCursor ); + + + QTranslator translator( 0 ); + translator.load( QString( "linguist_" ) + QTextCodec::locale(), "." ); + app.installTranslator( &translator ); + + bool showSplash = TRUE; + + QString keybase("/Qt Linguist/3.1/"); + QSettings config; + config.insertSearchPath( QSettings::Windows, "/Trolltech" ); + + QRect r( QApplication::desktop()->screenGeometry() ); + 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() ) ); + + QSplashScreen *splash = 0; + if ( showSplash ) { + splash = new QSplashScreen( QPixmap::fromMimeSource("splash.png"), + Qt::WDestructiveClose ); + splash->show(); + } + + TrWindow *tw = new TrWindow; + app.setMainWidget( tw ); + + if ( app.argc() > 1 ) + tw->openFile( QString(app.argv()[app.argc() - 1]) ); + + if ( config.readBoolEntry( keybase + "Geometry/MainwindowMaximized", FALSE ) ) + tw->showMaximized(); + else + tw->show(); + if ( splash ) + splash->finish( tw ); + QApplication::restoreOverrideCursor(); + + return app.exec(); +} diff --git a/tools/linguist/linguist/msgedit.cpp b/tools/linguist/linguist/msgedit.cpp new file mode 100644 index 0000000..09e60a1 --- /dev/null +++ b/tools/linguist/linguist/msgedit.cpp @@ -0,0 +1,834 @@ +/********************************************************************** +** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved. +** +** This file is part of Qt 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 Qt 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 Qt Commercial licenses may use this file in +** accordance with the Qt 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 MsgEdit + + This is the right panel of the main window. +*/ + +#include "msgedit.h" + +#include "trwindow.h" +#include "phraselv.h" +#include "simtexth.h" + +#include <qapplication.h> +#include <qcheckbox.h> +#include <qclipboard.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qtextedit.h> +#include <qpalette.h> +#include <qpushbutton.h> +#include <qstring.h> +#include <qtextview.h> +#include <qwhatsthis.h> +#include <qvbox.h> +#include <qmainwindow.h> +#include <qheader.h> +#include <qregexp.h> +#include <qdockarea.h> +#include <qdockwindow.h> +#include <qscrollview.h> +#include <qfont.h> +#include <qaccel.h> +#include <private/qrichtext_p.h> + +static const int MaxCandidates = 5; + +class MED : public QTextEdit +{ +public: + MED( QWidget *parent, const char *name = 0 ) + : QTextEdit( parent, name ) {} + + int cursorX() const { return textCursor()->x(); } + int cursorY() const { return textCursor()->paragraph()->rect().y() + + textCursor()->y(); } +}; + + +QString richMeta( const QString& text ) +{ + return QString( "<small><font color=blue>(" ) + text + + QString( ")</font></small>" ); +} + +QString richText( const QString& text ) +{ + const char backTab[] = "\a\b\f\n\r\t"; + const char * const friendlyBackTab[] = { + QT_TRANSLATE_NOOP( "MessageEditor", "bell" ), + QT_TRANSLATE_NOOP( "MessageEditor", "backspace" ), + QT_TRANSLATE_NOOP( "MessageEditor", "new page" ), + QT_TRANSLATE_NOOP( "MessageEditor", "new line" ), + QT_TRANSLATE_NOOP( "MessageEditor", "carriage return" ), + QT_TRANSLATE_NOOP( "MessageEditor", "tab" ) + }; + QString rich; + + for ( int i = 0; i < (int) text.length(); i++ ) { + int ch = text[i].unicode(); + + if ( ch < 0x20 ) { + const char *p = strchr( backTab, ch ); + if ( p == 0 ) + rich += richMeta( QString::number(ch, 16) ); + else + rich += richMeta( MessageEditor::tr(friendlyBackTab[p - backTab]) ); + } else if ( ch == '<' ) { + rich += QString( "<" ); + } else if ( ch == '>' ) { + rich += QString( ">" ); + } else if ( ch == '&' ) { + rich += QString( "&" ); + } else if ( ch == ' ' ) { + if ( i == 0 || i == (text.length()-1) || text[i - 1] == ' ' || text[i + 1] == ' ' ) { + rich += richMeta( MessageEditor::tr("sp") ); + } else { + rich += ' '; + } + } else { + rich += QChar( ch ); + } + if ( ch == '\n' ) + rich += QString( "<br>" ); + } + return rich; +} + +/* + ShadowWidget class impl. + + Used to create a shadow like effect for a widget +*/ +ShadowWidget::ShadowWidget( QWidget * parent, const char * name ) + : QWidget( parent, name ), sWidth( 10 ), wMargin( 3 ), childWgt( 0 ) +{ +} + +ShadowWidget::ShadowWidget( QWidget * child, QWidget * parent, + const char * name ) + : QWidget( parent, name ), sWidth( 10 ), wMargin( 3 ), childWgt( 0 ) +{ + setWidget( child ); +} + +void ShadowWidget::setWidget( QWidget * child ) +{ + childWgt = child; + if ( childWgt && childWgt->parent() != this ) { + childWgt->reparent( this, QPoint( 0, 0 ), TRUE ); + } +} + +void ShadowWidget::resizeEvent( QResizeEvent * ) +{ + if( childWgt ) { + childWgt->move( wMargin, wMargin ); + childWgt->resize( width() - sWidth - wMargin, height() - sWidth - + wMargin ); + } +} + +void ShadowWidget::paintEvent( QPaintEvent * e ) +{ + QPainter p; + int w = width() - sWidth; + int h = height() - sWidth; + + + if ( !((w > 0) && (h > 0)) ) + return; + + if ( p.begin( this ) ) { + p.setPen( colorGroup().shadow() ); + + p.drawPoint( w + 5, 6 ); + p.drawLine( w + 3, 6, w + 5, 8 ); + p.drawLine( w + 1, 6, w + 5, 10 ); + int i; + for( i=7; i < h; i += 2 ) + p.drawLine( w, i, w + 5, i + 5 ); + for( i = w - i + h; i > 6; i -= 2 ) + p.drawLine( i, h, i + 5, h + 5 ); + for( ; i > 0 ; i -= 2 ) + p.drawLine( 6, h + 6 - i, i + 5, h + 5 ); + +// p.eraseRect( w, 0, sWidth, 45 ); // Cheap hack for the page curl.. + p.end(); + } + QWidget::paintEvent( e ); +} + +/* + EditorPage class impl. + + A frame that contains the source text, translated text and any + source code comments and hints. +*/ +EditorPage::EditorPage( QWidget * parent, const char * name ) + : QFrame( parent, name ) +{ + setLineWidth( 1 ); + setFrameStyle( QFrame::Box | QFrame::Plain ); + + // Use white explicitly as the background color for the editor page. + QPalette p = palette(); + p.setColor( QPalette::Active, QColorGroup::Base, QColor( white ) ); + p.setColor( QPalette::Inactive, QColorGroup::Base, QColor( white ) ); + p.setColor( QPalette::Disabled, QColorGroup::Base, QColor( white ) ); + p.setColor( QPalette::Active, QColorGroup::Background, + p.active().color( QColorGroup::Base ) ); + p.setColor( QPalette::Inactive, QColorGroup::Background, + p.inactive().color( QColorGroup::Base ) ); + p.setColor( QPalette::Disabled, QColorGroup::Background, + p.disabled().color( QColorGroup::Base ) ); + setPalette( p ); + + srcTextLbl = new QLabel( tr("Source text"), this, "source text label" ); + transLbl = new QLabel( tr("Translation"), this, "translation label" ); + + QFont fnt = font(); + fnt.setBold( TRUE ); + srcTextLbl->setFont( fnt ); + transLbl->setFont( fnt ); + + srcText = new QTextView( this, "source text view" ); + srcText->setFrameStyle( QFrame::NoFrame ); + srcText->setSizePolicy( QSizePolicy( QSizePolicy::MinimumExpanding, + QSizePolicy::Minimum ) ); + srcText->setResizePolicy( QScrollView::AutoOne ); + srcText->setHScrollBarMode( QScrollView::AlwaysOff ); + srcText->setVScrollBarMode( QScrollView::AlwaysOff ); + p = srcText->palette(); + p.setColor( QPalette::Disabled, QColorGroup::Base, p.active().base() ); + srcText->setPalette( p ); + connect( srcText, SIGNAL(textChanged()), SLOT(handleSourceChanges()) ); + + cmtText = new QTextView( this, "comment/context view" ); + cmtText->setFrameStyle( QFrame::NoFrame ); + cmtText->setSizePolicy( QSizePolicy( QSizePolicy::MinimumExpanding, + QSizePolicy::Minimum ) ); + cmtText->setResizePolicy( QScrollView::AutoOne ); + cmtText->setHScrollBarMode( QScrollView::AlwaysOff ); + cmtText->setVScrollBarMode( QScrollView::AlwaysOff ); + p = cmtText->palette(); + p.setColor( QPalette::Active, QColorGroup::Base, QColor( 236,245,255 ) ); + p.setColor( QPalette::Inactive, QColorGroup::Base, QColor( 236,245,255 ) ); + cmtText->setPalette( p ); + connect( cmtText, SIGNAL(textChanged()), SLOT(handleCommentChanges()) ); + + translationMed = new MED( this, "translation editor" ); + translationMed->setFrameStyle( QFrame::NoFrame ); + translationMed->setSizePolicy( QSizePolicy( QSizePolicy::MinimumExpanding, + QSizePolicy::MinimumExpanding ) ); + translationMed->setHScrollBarMode( QScrollView::AlwaysOff ); + translationMed->setVScrollBarMode( QScrollView::AlwaysOff ); + translationMed->setResizePolicy( QScrollView::AutoOne ); + translationMed->setWrapPolicy( QTextView::AtWhiteSpace ); + translationMed->setWordWrap( QTextView::WidgetWidth ); + translationMed->setTextFormat( QTextView::PlainText ); + p = translationMed->palette(); + p.setColor( QPalette::Disabled, QColorGroup::Base, p.active().base() ); + translationMed->setPalette( p ); + connect( translationMed, SIGNAL(textChanged()), + SLOT(handleTranslationChanges()) ); + + pageCurl = new PageCurl( this, "page curl" ); + + // Focus + setFocusPolicy( StrongFocus ); + transLbl->setFocusProxy( translationMed ); + srcTextLbl->setFocusProxy( translationMed ); + cmtText->setFocusProxy( translationMed ); + srcText->setFocusProxy( translationMed ); + setFocusProxy( translationMed ); + + updateCommentField(); +} + +/* + Don't show the comment field if there are no comments. +*/ +void EditorPage::updateCommentField() +{ + if( cmtText->text().isEmpty() ) + cmtText->hide(); + else + cmtText->show(); + + layoutWidgets(); +} + +/* + Handle the widget layout manually +*/ +void EditorPage::layoutWidgets() + { + int margin = 6; + int space = 2; + int w = width(); + + pageCurl->move( width() - pageCurl->width(), 0 ); + + QFontMetrics fm( srcTextLbl->font() ); + srcTextLbl->move( margin, margin ); + srcTextLbl->resize( fm.width( srcTextLbl->text() ), srcTextLbl->height() ); + + srcText->move( margin, srcTextLbl->y() + srcTextLbl->height() + space ); + srcText->resize( w - margin*2, srcText->height() ); + + cmtText->move( margin, srcText->y() + srcText->height() + space ); + cmtText->resize( w - margin*2, cmtText->height() ); + + if( cmtText->isHidden() ) + transLbl->move( margin, srcText->y() + srcText->height() + space ); + else + transLbl->move( margin, cmtText->y() + cmtText->height() + space ); + transLbl->resize( w - margin*2, transLbl->height() ); + + translationMed->move( margin, transLbl->y() + transLbl->height() + space ); + translationMed->resize( w - margin*2, translationMed->height() ); + + // Calculate the total height for the editor page - emit a signal + // if the actual page size is larger/smaller + int totHeight = margin + srcTextLbl->height() + + srcText->height() + space + + transLbl->height() + space + + translationMed->height() + space + + frameWidth()*lineWidth()*2 + space * 3; + + if( !cmtText->isHidden() ) + totHeight += cmtText->height() + space; + + if( height() != totHeight ) + emit pageHeightUpdated( totHeight ); +} + +void EditorPage::resizeEvent( QResizeEvent * ) +{ + handleTranslationChanges(); + handleSourceChanges(); + handleCommentChanges(); + layoutWidgets(); +} + +void EditorPage::handleTranslationChanges() +{ + calculateFieldHeight( (QTextView *) translationMed ); +} + +void EditorPage::handleSourceChanges() +{ + calculateFieldHeight( srcText ); +} + +void EditorPage::handleCommentChanges() +{ + calculateFieldHeight( cmtText ); +} + +/* + Check if the translation text field is big enough to show all text + that has been entered. If it isn't, resize it. +*/ +void EditorPage::calculateFieldHeight( QTextView * field ) +{ + field->sync(); // make sure the text formatting is done! + int contentsHeight = field->contentsHeight(); + + if( contentsHeight != field->height() ) { + int oldHeight = field->height(); + if( contentsHeight < 30 ) + contentsHeight = 30; + field->resize( field->width(), contentsHeight ); + emit pageHeightUpdated( height() + (field->height() - oldHeight) ); + } +} + +void EditorPage::fontChange( const QFont & ) +{ + QFont fnt = font(); + + fnt.setBold( TRUE ); + QFontMetrics fm( fnt ); + srcTextLbl->setFont( fnt ); + srcTextLbl->resize( fm.width( srcTextLbl->text() ), srcTextLbl->height() ); + transLbl->setFont( fnt ); + transLbl->resize( fm.width( transLbl->text() ), transLbl->height() ); + update(); +} + +/* + MessageEditor class impl. + + Handle layout of dock windows and the editor page. +*/ +MessageEditor::MessageEditor( MetaTranslator * t, QWidget * parent, + const char * name ) + : QWidget( parent, name ), + tor( t ) +{ + doGuesses = TRUE; + v = new QVBoxLayout( this ); + topDock = new QDockArea( Qt::Horizontal, QDockArea::Normal, this, + "top dock area" ); + topDock->setMinimumHeight( 10 ); + topDock->setSizePolicy( QSizePolicy( QSizePolicy::Minimum, + QSizePolicy::Minimum) ); + + topDockWnd = new QDockWindow( QDockWindow::InDock, topDock, + "top dock window" ); + QMainWindow *mw = (QMainWindow*)topLevelWidget(); + if ( mw ) { + mw->setDockEnabled( topDockWnd, Qt::DockTop, TRUE ); + mw->setDockEnabled( topDockWnd, Qt::DockLeft, TRUE ); + mw->setDockEnabled( topDockWnd, Qt::DockRight, TRUE ); + mw->setDockEnabled( topDockWnd, Qt::DockBottom, TRUE ); + } + + topDockWnd->setCaption( tr("Source text") ); + topDockWnd->setCloseMode( QDockWindow::Always ); + topDockWnd->setResizeEnabled( TRUE ); + topDockWnd->setFixedExtentHeight( 110 ); + + srcTextList = new QListView( topDockWnd, "source text list view" ); + srcTextList->setShowSortIndicator( TRUE ); + srcTextList->setAllColumnsShowFocus( TRUE ); + srcTextList->setSorting( 0 ); + QFontMetrics fm( font() ); + srcTextList->addColumn( tr("Done"), fm.width( tr("Done") ) + 10 ); + srcTextList->addColumn( tr("Source text") ); + srcTextList->addColumn( tr("Translation"), 300 ); + srcTextList->setColumnAlignment( 0, Qt::AlignCenter ); + srcTextList->setColumnWidthMode( 1, QListView::Manual ); + srcTextList->header()->setStretchEnabled( TRUE, 1 ); + srcTextList->setMinimumSize( QSize( 50, 50 ) ); + srcTextList->setHScrollBarMode( QScrollView::AlwaysOff ); + srcTextList->installEventFilter( this ); + topDockWnd->setWidget( srcTextList ); + + sv = new QScrollView( this, "scroll view" ); + sv->setHScrollBarMode( QScrollView::AlwaysOff ); + sv->viewport()->setBackgroundMode( PaletteBackground ); + + editorPage = new EditorPage( sv, "editor page" ); + connect( editorPage, SIGNAL(pageHeightUpdated(int)), + SLOT(updatePageHeight(int)) ); + + editorPage->translationMed->installEventFilter( this ); + + sw = new ShadowWidget( editorPage, sv, "editor page shadow" ); + sw->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, + QSizePolicy::Expanding) ); + sw->setMinimumSize( QSize( 100, 150 ) ); + sv->addChild( sw ); + + bottomDock = new QDockArea( Qt::Horizontal, QDockArea::Reverse, + this, "bottom dock area" ); + bottomDock->setMinimumHeight( 10 ); + bottomDock->setSizePolicy( QSizePolicy( QSizePolicy::Minimum, + QSizePolicy::Minimum) ); + bottomDockWnd = new QDockWindow( QDockWindow::InDock, bottomDock, + "bottom dock window" ); + if ( mw ) { + mw->setDockEnabled( bottomDockWnd, Qt::DockTop, TRUE ); + mw->setDockEnabled( bottomDockWnd, Qt::DockLeft, TRUE ); + mw->setDockEnabled( bottomDockWnd, Qt::DockRight, TRUE ); + mw->setDockEnabled( bottomDockWnd, Qt::DockBottom, TRUE ); + } + bottomDockWnd->setCaption( tr("Phrases") ); + bottomDockWnd->setCloseMode( QDockWindow::Always ); + bottomDockWnd->setResizeEnabled( TRUE ); + + QWidget * w = new QWidget( bottomDockWnd ); + w->setSizePolicy( QSizePolicy( QSizePolicy::Minimum, + QSizePolicy::Minimum ) ); + QHBoxLayout *hl = new QHBoxLayout( w, 6 ); + QVBoxLayout *vl = new QVBoxLayout( 6 ); + + phraseLbl = new QLabel( tr("Phrases and guesses:"), w ); + phraseLv = new PhraseLV( w, "phrase list view" ); + phraseLv->setSorting( PhraseLVI::DefinitionText ); + phraseLv->installEventFilter( this ); + hl->addLayout( vl ); + vl->addWidget( phraseLbl ); + vl->addWidget( phraseLv ); + + accel = new QAccel( this, "accel" ); + connect( accel, SIGNAL(activated(int)), this, SLOT(guessActivated(int)) ); + for ( int i = 0; i < 9; i++ ) + accel->insertItem( CTRL + (Key_1 + i), i + 1 ); + + bottomDockWnd->setWidget( w ); + + v->addWidget( topDock ); + v->addWidget( sv ); + v->addWidget( bottomDock ); + + // Signals + connect( editorPage->pageCurl, SIGNAL(nextPage()), + SIGNAL(nextUnfinished()) ); + connect( editorPage->pageCurl, SIGNAL(prevPage()), + SIGNAL(prevUnfinished()) ); + + connect( editorPage->translationMed, SIGNAL(textChanged()), + this, SLOT(emitTranslationChanged()) ); + connect( editorPage->translationMed, SIGNAL(textChanged()), + this, SLOT(updateButtons()) ); + connect( editorPage->translationMed, SIGNAL(undoAvailable(bool)), + this, SIGNAL(undoAvailable(bool)) ); + connect( editorPage->translationMed, SIGNAL(redoAvailable(bool)), + this, SIGNAL(redoAvailable(bool)) ); + connect( editorPage->translationMed, SIGNAL(copyAvailable(bool)), + this, SIGNAL(cutAvailable(bool)) ); + connect( editorPage->translationMed, SIGNAL(copyAvailable(bool)), + this, SIGNAL(copyAvailable(bool)) ); + connect( qApp->clipboard(), SIGNAL(dataChanged()), + this, SLOT(updateCanPaste()) ); + connect( phraseLv, SIGNAL(doubleClicked(QListViewItem *)), + this, SLOT(insertPhraseInTranslation(QListViewItem *)) ); + connect( phraseLv, SIGNAL(returnPressed(QListViewItem *)), + this, SLOT(insertPhraseInTranslationAndLeave(QListViewItem *)) ); + + // What's this + QWhatsThis::add( this, tr("This whole panel allows you to view and edit " + "the translation of some source text.") ); + QWhatsThis::add( editorPage->srcText, + tr("This area shows the source text.") ); + QWhatsThis::add( editorPage->cmtText, tr("This area shows a comment that" + " may guide you, and the context in which the text" + " occurs.") ); + QWhatsThis::add( editorPage->translationMed, + tr("This is where you can enter or modify" + " the translation of some source text.") ); +} + +void MessageEditor::toggleFinished() +{ + if ( itemFinished ) + itemFinished = FALSE; + else + itemFinished = TRUE; + emit finished( itemFinished ); +} + +bool MessageEditor::eventFilter( QObject *o, QEvent *e ) +{ + // Handle keypresses in the message editor - scroll the view if the current + // line is hidden. + if ( e->type() == QEvent::KeyPress || e->type() == QEvent::KeyRelease ) { + QKeyEvent * ke = (QKeyEvent*)e; + const int k = ke->key(); + + if ( ::qt_cast<QTextEdit*>(o) ) { + if ( e->type() == QEvent::KeyPress ) { + // Hardcode the Tab key to do focus changes when pressed + // inside the editor + if ( k == Key_BackTab ) { + emit focusSourceList(); + return TRUE; + } + } else if ( e->type() == QEvent::KeyRelease ) { + MED * ed = (MED *) o; + switch( k ) { + case Key_Up: + if (ed->cursorY() < 10) + sv->verticalScrollBar()->subtractLine(); + break; + + case Key_Down: + if (ed->cursorY() >= ed->height() - 20) + sv->verticalScrollBar()->addLine(); + break; + + case Key_PageUp: + if (ed->cursorY() < 10) + sv->verticalScrollBar()->subtractPage(); + break; + + case Key_PageDown: + if (ed->cursorY() >= ed->height() - 50) + sv->verticalScrollBar()->addPage(); + break; + default: + sv->ensureVisible( sw->margin() + ed->x() + ed->cursorX(), + sw->margin() + ed->y() + ed->cursorY() ); + break; + } + } + } else if ( ::qt_cast<QListView*>(o) ) { + // handle the ESC key in the list views + if ( e->type() == QEvent::KeyRelease && k == Key_Escape ) + editorPage->translationMed->setFocus(); + } + } + return QWidget::eventFilter( o, e ); +} + +void MessageEditor::updatePageHeight( int height ) +{ + sw->resize( sw->width(), height + sw->margin() + sw->shadowWidth() ); +} + +void MessageEditor::resizeEvent( QResizeEvent * ) +{ + sw->resize( sv->viewport()->width(), sw->height() ); +} + +QListView * MessageEditor::sourceTextList() const +{ + return srcTextList; +} + +QListView * MessageEditor::phraseList() const +{ + return phraseLv; +} + +void MessageEditor::showNothing() +{ + editorPage->srcText->setText( "" ); + showContext( QString(""), FALSE ); +} + +void MessageEditor::showContext( const QString& context, bool finished ) +{ + setEditionEnabled( FALSE ); + sourceText = QString::null; + guesses.clear(); + + if( context.isEmpty() ) + editorPage->cmtText->setText(""); + else + editorPage->cmtText->setText( richText(context.simplifyWhiteSpace()) ); + setTranslation( QString(""), FALSE ); + setFinished( finished ); + phraseLv->clear(); + editorPage->handleSourceChanges(); + editorPage->handleCommentChanges(); + editorPage->handleTranslationChanges(); + editorPage->updateCommentField(); +} + +void MessageEditor::showMessage( const QString& text, + const QString& comment, + const QString& fullContext, + const QString& translation, + MetaTranslatorMessage::Type type, + const QValueList<Phrase>& phrases ) +{ + bool obsolete = ( type == MetaTranslatorMessage::Obsolete ); + setEditionEnabled( !obsolete ); + sourceText = text; + guesses.clear(); + + editorPage->srcText->setText( QString("<p>") + richText( text ) + + QString("</p>") ); + + if ( !fullContext.isEmpty() && !comment.isEmpty() ) + editorPage->cmtText->setText( richText(fullContext.simplifyWhiteSpace()) + + "\n" + richText(comment.simplifyWhiteSpace()) ); + else if ( !fullContext.isEmpty() && comment.isEmpty() ) + editorPage->cmtText->setText(richText(fullContext.simplifyWhiteSpace() ) ); + else if ( fullContext.isEmpty() && !comment.isEmpty() ) + editorPage->cmtText->setText( richText(comment.simplifyWhiteSpace() ) ); + else + editorPage->cmtText->setText( "" ); + + setTranslation( translation, FALSE ); + setFinished( type != MetaTranslatorMessage::Unfinished ); + QValueList<Phrase>::ConstIterator p; + phraseLv->clear(); + for ( p = phrases.begin(); p != phrases.end(); ++p ) + (void) new PhraseLVI( phraseLv, *p ); + + if ( doGuesses && !sourceText.isEmpty() ) { + CandidateList cl = similarTextHeuristicCandidates( tor, + sourceText.latin1(), + MaxCandidates ); + int n = 0; + QValueList<Candidate>::Iterator it = cl.begin(); + while ( it != cl.end() ) { + QString def; + if ( n < 9 ) + def = tr( "Guess (%1)" ).arg( QString(QKeySequence(CTRL | (Key_0 + (n + 1)))) ); + else + def = tr( "Guess" ); + (void) new PhraseLVI( phraseLv, + Phrase((*it).source, (*it).target, def), + n + 1 ); + n++; + ++it; + } + } + editorPage->handleSourceChanges(); + editorPage->handleCommentChanges(); + editorPage->handleTranslationChanges(); + editorPage->updateCommentField(); +} + +void MessageEditor::setTranslation( const QString& translation, bool emitt ) +{ + // Block signals so that 'textChanged()' is not emitted when + // for example a new source text item is selected and *not* + // the actual translation. + editorPage->translationMed->blockSignals( !emitt ); + editorPage->translationMed->setText( translation ); + editorPage->translationMed->blockSignals( FALSE ); + if ( !emitt ) + updateButtons(); + emit cutAvailable( FALSE ); + emit copyAvailable( FALSE ); +} + +void MessageEditor::setEditionEnabled( bool enabled ) +{ + editorPage->transLbl->setEnabled( enabled ); + editorPage->translationMed->setReadOnly( !enabled ); + + phraseLbl->setEnabled( enabled ); + phraseLv->setEnabled( enabled ); + updateCanPaste(); +} + +void MessageEditor::undo() +{ + editorPage->translationMed->undo(); +} + +void MessageEditor::redo() +{ + editorPage->translationMed->redo(); +} + +void MessageEditor::cut() +{ + editorPage->translationMed->cut(); +} + +void MessageEditor::copy() +{ + editorPage->translationMed->copy(); +} + +void MessageEditor::paste() +{ + editorPage->translationMed->paste(); +} + +void MessageEditor::del() +{ + editorPage->translationMed->del(); +} + +void MessageEditor::selectAll() +{ + editorPage->translationMed->selectAll(); +} + +void MessageEditor::emitTranslationChanged() +{ + emit translationChanged( editorPage->translationMed->text() ); +} + +void MessageEditor::guessActivated( int accelKey ) +{ + QListViewItem *item = phraseLv->firstChild(); + while ( item != 0 && ((PhraseLVI *) item)->accelKey() != accelKey ) + item = item->nextSibling(); + if ( item != 0 ) + insertPhraseInTranslation( item ); +} + +void MessageEditor::insertPhraseInTranslation( QListViewItem *item ) +{ + editorPage->translationMed->insert(((PhraseLVI *) item)->phrase().target()); + emit translationChanged( editorPage->translationMed->text() ); +} + +void MessageEditor::insertPhraseInTranslationAndLeave( QListViewItem *item ) +{ + editorPage->translationMed->insert(((PhraseLVI *) item)->phrase().target()); + emit translationChanged( editorPage->translationMed->text() ); + editorPage->translationMed->setFocus(); +} + +void MessageEditor::updateButtons() +{ + bool overwrite = ( !editorPage->translationMed->isReadOnly() && + (editorPage->translationMed->text().stripWhiteSpace().isEmpty() || + mayOverwriteTranslation) ); + mayOverwriteTranslation = FALSE; + emit updateActions( overwrite ); +} + +void MessageEditor::beginFromSource() +{ + mayOverwriteTranslation = TRUE; + setTranslation( sourceText, TRUE ); + if ( !editorPage->hasFocus() ) + editorPage->setFocus(); +} + +void MessageEditor::finishAndNext() +{ + setFinished( TRUE ); + emit nextUnfinished(); + if ( !editorPage->hasFocus() ) + editorPage->setFocus(); +} + +void MessageEditor::updateCanPaste() +{ + bool oldCanPaste = canPaste; + canPaste = ( !editorPage->translationMed->isReadOnly() && + !qApp->clipboard()->text().isNull() ); + if ( canPaste != oldCanPaste ) + emit pasteAvailable( canPaste ); +} + +void MessageEditor::setFinished( bool finished ) +{ + if ( !finished != !itemFinished ) + toggleFinished(); +} + +void MessageEditor::toggleGuessing() +{ + doGuesses = !doGuesses; + if ( !doGuesses ) { + phraseLv->clear(); + } +} diff --git a/tools/linguist/linguist/msgedit.h b/tools/linguist/linguist/msgedit.h new file mode 100644 index 0000000..bf73483 --- /dev/null +++ b/tools/linguist/linguist/msgedit.h @@ -0,0 +1,244 @@ +/********************************************************************** +** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved. +** +** This file is part of Qt 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 Qt 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 Qt Commercial licenses may use this file in +** accordance with the Qt 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. +** +**********************************************************************/ + +#ifndef MSGEDIT_H +#define MSGEDIT_H + +#include "trwindow.h" +#include "phrase.h" + +#include <metatranslator.h> + +#include <qsplitter.h> +#include <qstring.h> +#include <qstringlist.h> +#include <qvaluelist.h> +#include <qscrollview.h> +#include <qpixmap.h> +#include <qbitmap.h> +#include <qtooltip.h> + +class QAccel; +class QDockArea; +class QDockWindow; +class QLabel; +class QListView; +class QListViewItem; +class QTextView; +class QVBoxLayout; + +class EditorPage; +class MED; +class PhraseLV; + +class PageCurl : public QWidget +{ + Q_OBJECT +public: + PageCurl( QWidget * parent = 0, const char * name = 0, + WFlags f = 0 ) + : QWidget( parent, name, f ) + { + QPixmap px = TrWindow::pageCurl(); + if ( px.mask() ) { + setMask( *px.mask() ); + } + setBackgroundPixmap( px ); + setFixedSize( px.size() ); + + QRect r( 34, 0, width()-34, 19 ); + QToolTip::add( this, r, tr("Next unfinished phrase") ); + r.setSize( QSize(width()-34, height()-20) ); + r.setX( 0 ); + r.setY( 20 ); + QToolTip::add( this, r, tr("Previous unfinished phrase") ); + } + +protected: + void mouseReleaseEvent( QMouseEvent * e ) + { + int x = e->pos().x() - 14; + int y = e->pos().y() - 8; + + if ( y <= x ) + emit nextPage(); + else + emit prevPage(); + } + +signals: + void prevPage(); + void nextPage(); +}; + +class ShadowWidget : public QWidget +{ +public: + ShadowWidget( QWidget * parent = 0, const char * name = 0 ); + ShadowWidget( QWidget * child, QWidget * parent = 0, const char * name = 0 ); + + void setShadowWidth( int width ) { sWidth = width; } + int shadowWidth() const { return sWidth; } + void setMargin( int margin ){ wMargin = margin; } + int margin() const { return wMargin; } + void setWidget( QWidget * child); + +protected: + void resizeEvent( QResizeEvent * e ); + void paintEvent( QPaintEvent * e ); + +private: + int sWidth; + int wMargin; + QWidget * childWgt; +}; + +class EditorPage : public QFrame +{ + Q_OBJECT +public: + EditorPage( QWidget * parent = 0, const char * name = 0 ); + +protected: + void resizeEvent( QResizeEvent * ); + void layoutWidgets(); + void updateCommentField(); + void calculateFieldHeight( QTextView * field ); + void fontChange( const QFont & ); + +private: + PageCurl * pageCurl; + QLabel * srcTextLbl; + QLabel * transLbl; + QTextView * srcText; + QTextView * cmtText; + MED * translationMed; + + friend class MessageEditor; + +private slots: + void handleTranslationChanges(); + void handleSourceChanges(); + void handleCommentChanges(); + +signals: + void pageHeightUpdated( int height ); +}; + +class MessageEditor : public QWidget +{ + Q_OBJECT +public: + MessageEditor( MetaTranslator * t, QWidget * parent = 0, + const char * name = 0 ); + QListView * sourceTextList() const; + QListView * phraseList() const; + + void showNothing(); + void showContext( const QString& context, bool finished ); + void showMessage( const QString& text, const QString& comment, + const QString& fullContext, const QString& translation, + MetaTranslatorMessage::Type type, + const QValueList<Phrase>& phrases ); + void setFinished( bool finished ); + bool eventFilter( QObject *, QEvent * ); + +signals: + void translationChanged( const QString& translation ); + void finished( bool finished ); + void prevUnfinished(); + void nextUnfinished(); + void updateActions( bool enable ); + + void undoAvailable( bool avail ); + void redoAvailable( bool avail ); + void cutAvailable( bool avail ); + void copyAvailable( bool avail ); + void pasteAvailable( bool avail ); + + void focusSourceList(); + void focusPhraseList(); + +public slots: + void undo(); + void redo(); + void cut(); + void copy(); + void paste(); + void del(); + void selectAll(); + void beginFromSource(); + void toggleGuessing(); + void finishAndNext(); + +private slots: + void emitTranslationChanged(); + void guessActivated( int accelKey ); + void insertPhraseInTranslation( QListViewItem *item ); + void insertPhraseInTranslationAndLeave( QListViewItem *item ); + void updateButtons(); + void updateCanPaste(); + void toggleFinished(); + + void updatePageHeight( int height ); + +protected: + void resizeEvent( QResizeEvent * ); + +private: + void setTranslation( const QString& translation, bool emitt ); + void setEditionEnabled( bool enabled ); + + QListView * srcTextList; + QDockArea * topDock, * bottomDock; + QDockWindow * topDockWnd, *bottomDockWnd; + EditorPage * editorPage; + QVBoxLayout * v; + + QLabel * phraseLbl; + PhraseLV * phraseLv; + QAccel * accel; + bool itemFinished; + + ShadowWidget * sw; + QScrollView * sv; + + MetaTranslator *tor; + QString sourceText; + QStringList guesses; + bool mayOverwriteTranslation; + bool canPaste; + bool doGuesses; +}; + +#endif diff --git a/tools/linguist/linguist/phrase.cpp b/tools/linguist/linguist/phrase.cpp new file mode 100644 index 0000000..da702a5 --- /dev/null +++ b/tools/linguist/linguist/phrase.cpp @@ -0,0 +1,189 @@ +/********************************************************************** +** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved. +** +** This file is part of Qt 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 Qt 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 Qt Commercial licenses may use this file in +** accordance with the Qt 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. +** +**********************************************************************/ + +#include "phrase.h" + +#include <qapplication.h> +#include <qcstring.h> +#include <qfile.h> +#include <qmessagebox.h> +#include <qregexp.h> +#include <qtextstream.h> +#include <qxml.h> + +static QString protect( const QString& str ) +{ + QString p = str; + p.replace( "&", "&" ); + p.replace( "\"", """ ); + p.replace( ">", ">" ); + p.replace( "<", "<" ); + p.replace( "'", "'" ); + return p; +} + +Phrase::Phrase( const QString& source, const QString& target, + const QString& definition ) + : s( source ), t( target ), d( definition ) +{ +} + +bool operator==( const Phrase& p, const Phrase& q ) +{ + return p.source() == q.source() && p.target() == q.target() && + p.definition() == q.definition(); +} + +class QphHandler : public QXmlDefaultHandler +{ +public: + QphHandler( PhraseBook *phraseBook ) + : pb( phraseBook ), ferrorCount( 0 ) { } + + virtual bool startElement( const QString& namespaceURI, + const QString& localName, const QString& qName, + const QXmlAttributes& atts ); + virtual bool endElement( const QString& namespaceURI, + const QString& localName, const QString& qName ); + virtual bool characters( const QString& ch ); + virtual bool fatalError( const QXmlParseException& exception ); + +private: + PhraseBook *pb; + QString source; + QString target; + QString definition; + + QString accum; + int ferrorCount; +}; + +bool QphHandler::startElement( const QString& /* namespaceURI */, + const QString& /* localName */, + const QString& qName, + const QXmlAttributes& /* atts */ ) +{ + if ( qName == QString("phrase") ) { + source.truncate( 0 ); + target.truncate( 0 ); + definition.truncate( 0 ); + } + accum.truncate( 0 ); + return TRUE; +} + +bool QphHandler::endElement( const QString& /* namespaceURI */, + const QString& /* localName */, + const QString& qName ) +{ + if ( qName == QString("source") ) + source = accum; + else if ( qName == QString("target") ) + target = accum; + else if ( qName == QString("definition") ) + definition = accum; + else if ( qName == QString("phrase") ) + pb->append( Phrase(source, target, definition) ); + return TRUE; +} + +bool QphHandler::characters( const QString& ch ) +{ + accum += ch; + return TRUE; +} + +bool QphHandler::fatalError( const QXmlParseException& exception ) +{ + if ( ferrorCount++ == 0 ) { + QString msg; + msg.sprintf( "Parse error at line %d, column %d (%s).", + exception.lineNumber(), exception.columnNumber(), + exception.message().latin1() ); + QMessageBox::information( qApp->mainWidget(), + QObject::tr("Qt Linguist"), msg ); + } + return FALSE; +} + +bool PhraseBook::load( const QString& filename ) +{ + QFile f( filename ); + if ( !f.open(IO_ReadOnly) ) + return FALSE; + + QTextStream t( &f ); + QXmlInputSource in( t ); + QXmlSimpleReader reader; + // don't click on these! + reader.setFeature( "http://xml.org/sax/features/namespaces", FALSE ); + reader.setFeature( "http://xml.org/sax/features/namespace-prefixes", TRUE ); + reader.setFeature( "http://trolltech.com/xml/features/report-whitespace" + "-only-CharData", FALSE ); + QXmlDefaultHandler *hand = new QphHandler( this ); + reader.setContentHandler( hand ); + reader.setErrorHandler( hand ); + + bool ok = reader.parse( in ); + reader.setContentHandler( 0 ); + reader.setErrorHandler( 0 ); + delete hand; + f.close(); + if ( !ok ) + clear(); + return ok; +} + +bool PhraseBook::save( const QString& filename ) const +{ + QFile f( filename ); + if ( !f.open(IO_WriteOnly) ) + return FALSE; + + QTextStream t( &f ); + t.setEncoding(QTextStream::UnicodeUTF8); + t << "<!DOCTYPE QPH><QPH>\n"; + ConstIterator p; + for ( p = begin(); p != end(); ++p ) { + t << "<phrase>\n"; + t << " <source>" << protect( (*p).source() ) << "</source>\n"; + t << " <target>" << protect( (*p).target() ) << "</target>\n"; + if ( !(*p).definition().isEmpty() ) + t << " <definition>" << protect( (*p).definition() ) + << "</definition>\n"; + t << "</phrase>\n"; + } + t << "</QPH>\n"; + f.close(); + return TRUE; +} diff --git a/tools/linguist/linguist/phrase.h b/tools/linguist/linguist/phrase.h new file mode 100644 index 0000000..8b32a0c --- /dev/null +++ b/tools/linguist/linguist/phrase.h @@ -0,0 +1,74 @@ +/********************************************************************** +** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved. +** +** This file is part of Qt 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 Qt 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 Qt Commercial licenses may use this file in +** accordance with the Qt 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. +** +**********************************************************************/ + +#ifndef PHRASE_H +#define PHRASE_H + +#include <qstring.h> +#include <qvaluelist.h> + +class Phrase +{ +public: + Phrase() { } + Phrase( const QString& source, const QString& target, + const QString& definition ); + + QString source() const { return s; } + void setSource( const QString& ns ) { s = ns; } + QString target() const { return t; } + void setTarget( const QString& nt ) { t = nt; } + QString definition() const { return d; } + void setDefinition ( const QString& nd ) { d = nd; } + +private: + QString s; + QString t; + QString d; +}; + +bool operator==( const Phrase& p, const Phrase& q ); +inline bool operator!=( const Phrase& p, const Phrase& q ) { + return !( p == q ); +} + +class PhraseBook : public QValueList<Phrase> +{ +public: + PhraseBook() { } + + bool load( const QString& filename ); + bool save( const QString& filename ) const; +}; + +#endif diff --git a/tools/linguist/linguist/phrasebookbox.cpp b/tools/linguist/linguist/phrasebookbox.cpp new file mode 100644 index 0000000..b8c6fab --- /dev/null +++ b/tools/linguist/linguist/phrasebookbox.cpp @@ -0,0 +1,244 @@ +/********************************************************************** +** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved. +** +** This file is part of Qt 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 Qt 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 Qt Commercial licenses may use this file in +** accordance with the Qt 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 PhraseBookBox + + Go to Phrase > Edit Phrase Book... The dialog that pops up is a + PhraseBookBox. +*/ + +#include "phrasebookbox.h" +#include "phraselv.h" + +#include <qapplication.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qlineedit.h> +#include <qmessagebox.h> +#include <qpushbutton.h> +#include <qwhatsthis.h> + +PhraseBookBox::PhraseBookBox( const QString& filename, + const PhraseBook& phraseBook, QWidget *parent, + const char *name, bool modal ) + : QDialog( parent, name, modal ), fn( filename ), pb( phraseBook ) +{ + QGridLayout *gl = new QGridLayout( this, 4, 3, 11, 11, + "phrase book outer layout" ); + QVBoxLayout *bl = new QVBoxLayout( 6, "phrase book button layout" ); + + sourceLed = new QLineEdit( this, "source line edit" ); + QLabel *source = new QLabel( sourceLed, tr("S&ource phrase:"), this, + "source label" ); + targetLed = new QLineEdit( this, "target line edit" ); + QLabel *target = new QLabel( targetLed, tr("&Translation:"), this, + "target label" ); + definitionLed = new QLineEdit( this, "definition line edit" ); + QLabel *definition = new QLabel( definitionLed, tr("&Definition:"), this, + "target label" ); + lv = new PhraseLV( this, "phrase book list view" ); + + newBut = new QPushButton( tr("&New Phrase"), this ); + newBut->setDefault( TRUE ); + + removeBut = new QPushButton( tr("&Remove Phrase"), this ); + removeBut->setEnabled( FALSE ); + QPushButton *saveBut = new QPushButton( tr("&Save"), this ); + QPushButton *closeBut = new QPushButton( tr("Close"), this ); + + gl->addWidget( source, 0, 0 ); + gl->addWidget( sourceLed, 0, 1 ); + gl->addWidget( target, 1, 0 ); + gl->addWidget( targetLed, 1, 1 ); + gl->addWidget( definition, 2, 0 ); + gl->addWidget( definitionLed, 2, 1 ); + gl->addMultiCellWidget( lv, 3, 3, 0, 1 ); + gl->addMultiCell( bl, 0, 3, 2, 2 ); + + bl->addWidget( newBut ); + bl->addWidget( removeBut ); + bl->addWidget( saveBut ); + bl->addWidget( closeBut ); + bl->addStretch( 1 ); + + connect( sourceLed, SIGNAL(textChanged(const QString&)), + this, SLOT(sourceChanged(const QString&)) ); + connect( targetLed, SIGNAL(textChanged(const QString&)), + this, SLOT(targetChanged(const QString&)) ); + connect( definitionLed, SIGNAL(textChanged(const QString&)), + this, SLOT(definitionChanged(const QString&)) ); + connect( lv, SIGNAL(selectionChanged(QListViewItem *)), + this, SLOT(selectionChanged(QListViewItem *)) ); + connect( newBut, SIGNAL(clicked()), this, SLOT(newPhrase()) ); + connect( removeBut, SIGNAL(clicked()), this, SLOT(removePhrase()) ); + connect( saveBut, SIGNAL(clicked()), this, SLOT(save()) ); + connect( closeBut, SIGNAL(clicked()), this, SLOT(accept()) ); + + PhraseBook::ConstIterator it; + for ( it = phraseBook.begin(); it != phraseBook.end(); ++it ) + (void) new PhraseLVI( lv, (*it) ); + enableDisable(); + + QWhatsThis::add( this, tr("This window allows you to add, modify, or delete" + " phrases in a phrase book.") ); + QWhatsThis::add( sourceLed, tr("This is the phrase in the source" + " language.") ); + QWhatsThis::add( targetLed, tr("This is the phrase in the target language" + " corresponding to the source phrase.") ); + QWhatsThis::add( definitionLed, tr("This is a definition for the source" + " phrase.") ); + QWhatsThis::add( newBut, tr("Click here to add the phrase to the phrase" + " book.") ); + QWhatsThis::add( removeBut, tr("Click here to remove the phrase from the" + " phrase book.") ); + QWhatsThis::add( saveBut, tr("Click here to save the changes made.") ); + QWhatsThis::add( closeBut, tr("Click here to close this window.") ); +} + +void PhraseBookBox::keyPressEvent( QKeyEvent *ev ) +{ + if ( ev->key() == Key_Down || ev->key() == Key_Up || + ev->key() == Key_Next || ev->key() == Key_Prior ) + QApplication::sendEvent( lv, + new QKeyEvent(ev->type(), ev->key(), ev->ascii(), ev->state(), + ev->text(), ev->isAutoRepeat(), ev->count()) ); + else + QDialog::keyPressEvent( ev ); +} + +void PhraseBookBox::newPhrase() +{ + Phrase ph; + ph.setSource( NewPhrase ); + QListViewItem *item = new PhraseLVI( lv, ph ); + selectItem( item ); +} + +void PhraseBookBox::removePhrase() +{ + QListViewItem *item = lv->currentItem(); + QListViewItem *next = item->itemBelow() != 0 ? item->itemBelow() + : item->itemAbove(); + delete item; + if ( next != 0 ) + selectItem( next ); + enableDisable(); +} + +void PhraseBookBox::save() +{ + pb.clear(); + QListViewItem *item = lv->firstChild(); + while ( item != 0 ) { + if ( !item->text(PhraseLVI::SourceTextShown).isEmpty() && + item->text(PhraseLVI::SourceTextShown) != NewPhrase ) + pb.append( Phrase(((PhraseLVI *) item)->phrase()) ); + item = item->nextSibling(); + } + if ( !pb.save( fn ) ) + QMessageBox::warning( this, tr("Qt Linguist"), + tr("Cannot save phrase book '%1'.").arg(fn) ); +} + +void PhraseBookBox::sourceChanged( const QString& source ) +{ + if ( lv->currentItem() != 0 ) { + lv->currentItem()->setText( PhraseLVI::SourceTextShown, + source.stripWhiteSpace() ); + lv->currentItem()->setText( PhraseLVI::SourceTextOriginal, source ); + lv->sort(); + lv->ensureItemVisible( lv->currentItem() ); + } +} + +void PhraseBookBox::targetChanged( const QString& target ) +{ + if ( lv->currentItem() != 0 ) { + lv->currentItem()->setText( PhraseLVI::TargetTextShown, + target.stripWhiteSpace() ); + lv->currentItem()->setText( PhraseLVI::TargetTextOriginal, target ); + lv->sort(); + lv->ensureItemVisible( lv->currentItem() ); + } +} + +void PhraseBookBox::definitionChanged( const QString& definition ) +{ + if ( lv->currentItem() != 0 ) { + lv->currentItem()->setText( PhraseLVI::DefinitionText, definition ); + lv->sort(); + lv->ensureItemVisible( lv->currentItem() ); + } +} + +void PhraseBookBox::selectionChanged( QListViewItem * /* item */ ) +{ + enableDisable(); +} + +void PhraseBookBox::selectItem( QListViewItem *item ) +{ + lv->setSelected( item, TRUE ); + lv->ensureItemVisible( item ); +} + +void PhraseBookBox::enableDisable() +{ + QListViewItem *item = lv->currentItem(); + + sourceLed->blockSignals( TRUE ); + targetLed->blockSignals( TRUE ); + definitionLed->blockSignals( TRUE ); + + if ( item == 0 ) { + sourceLed->setText( QString::null ); + targetLed->setText( QString::null ); + definitionLed->setText( QString::null ); + } else { + sourceLed->setText( item->text(0) ); + targetLed->setText( item->text(1) ); + definitionLed->setText( item->text(2) ); + } + sourceLed->setEnabled( item != 0 ); + targetLed->setEnabled( item != 0 ); + definitionLed->setEnabled( item != 0 ); + removeBut->setEnabled( item != 0 ); + + sourceLed->blockSignals( FALSE ); + targetLed->blockSignals( FALSE ); + definitionLed->blockSignals( FALSE ); + + QLineEdit *led = ( sourceLed->text() == NewPhrase ? sourceLed : targetLed ); + led->setFocus(); + led->selectAll(); +} diff --git a/tools/linguist/linguist/phrasebookbox.h b/tools/linguist/linguist/phrasebookbox.h new file mode 100644 index 0000000..0f922b1 --- /dev/null +++ b/tools/linguist/linguist/phrasebookbox.h @@ -0,0 +1,84 @@ +/********************************************************************** +** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved. +** +** This file is part of Qt 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 Qt 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 Qt Commercial licenses may use this file in +** accordance with the Qt 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. +** +**********************************************************************/ + +#ifndef PHRASEBOOKBOX_H +#define PHRASEBOOKBOX_H + +#include "phrase.h" + +#include <qdialog.h> +#include <qvaluelist.h> + +class QLineEdit; +class QPushButton; +class QListViewItem; + +class PhraseLV; + +class PhraseBookBox : public QDialog +{ + Q_OBJECT +public: + PhraseBookBox( const QString& filename, const PhraseBook& phraseBook, + QWidget *parent = 0, const char *name = 0, + bool modal = FALSE ); + + const PhraseBook& phraseBook() const { return pb; } + +protected: + virtual void keyPressEvent( QKeyEvent *ev ); + +private slots: + void newPhrase(); + void removePhrase(); + void save(); + void sourceChanged( const QString& source ); + void targetChanged( const QString& target ); + void definitionChanged( const QString& definition ); + void selectionChanged( QListViewItem *item ); + +private: + void selectItem( QListViewItem *item ); + void enableDisable(); + + QLineEdit *sourceLed; + QLineEdit *targetLed; + QLineEdit *definitionLed; + QPushButton *newBut; + QPushButton *removeBut; + PhraseLV *lv; + QString fn; + PhraseBook pb; +}; + +#endif diff --git a/tools/linguist/linguist/phraselv.cpp b/tools/linguist/linguist/phraselv.cpp new file mode 100644 index 0000000..fa454f8 --- /dev/null +++ b/tools/linguist/linguist/phraselv.cpp @@ -0,0 +1,171 @@ +/********************************************************************** +** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved. +** +** This file is part of Qt 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 Qt 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 Qt Commercial licenses may use this file in +** accordance with the Qt 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 PhraseLV + + The phrase list in the right panel of the main window (with Source phrase, + Target phrase, and Definition in its header) is a PhraseLV object. +*/ + +#include "phraselv.h" + +#include <qregexp.h> +#include <qwhatsthis.h> +#include <qheader.h> + +class WhatPhrase : public QWhatsThis +{ +public: + WhatPhrase( PhraseLV *w ); + + virtual QString text( const QPoint& p ); + +private: + PhraseLV *parent; +}; + +WhatPhrase::WhatPhrase( PhraseLV *w ) + : QWhatsThis( w ) +{ + parent = w; +} + +QString WhatPhrase::text( const QPoint& p ) +{ + QListViewItem *item = parent->itemAt( p ); + if ( item == 0 ) + return PhraseLV::tr( "This is a list of phrase entries relevant to the" + " source text. Each phrase is supplemented with a suggested" + " translation and a definition." ); + else + return QString( PhraseLV::tr("<p><u>%1:</u> %2</p>" + "<p><u>%3:</u> %4</p>" + "<p><u>%5:</u> %6</p>") ) + .arg( parent->columnText(PhraseLVI::SourceTextShown) ) + .arg( item->text(PhraseLVI::SourceTextShown) ) + .arg( parent->columnText(PhraseLVI::TargetTextShown) ) + .arg( item->text(PhraseLVI::TargetTextShown) ) + .arg( parent->columnText(PhraseLVI::DefinitionText) ) + .arg( item->text(PhraseLVI::DefinitionText) ); +} + +PhraseLVI::PhraseLVI( PhraseLV *parent, const Phrase& phrase, int accelKey ) + : QListViewItem( parent ), + akey( accelKey ) +{ + setPhrase( phrase ); +} + +QString PhraseLVI::key( int column, bool ascending ) const +{ + if ( column == SourceTextShown ) { + if ( sourceTextKey.isEmpty() ) { + if ( ascending ) { + return ""; + } else { + return QString::null; + } + } else { + return sourceTextKey; + } + } else if ( column == TargetTextShown ) { + return targetTextKey; + } else { + return QChar( '0' + akey ) + text( column ); + } +} + +void PhraseLVI::setText( int column, const QString& text ) +{ + if ( column == SourceTextShown ) { + sourceTextKey = makeKey( text ); + } else if ( column == TargetTextShown ) { + targetTextKey = makeKey( text ); + } + QListViewItem::setText( column, text ); +} + +void PhraseLVI::setPhrase( const Phrase& phrase ) +{ + setText( SourceTextShown, phrase.source().simplifyWhiteSpace() ); + setText( TargetTextShown, phrase.target().simplifyWhiteSpace() ); + setText( DefinitionText, phrase.definition() ); + setText( SourceTextOriginal, phrase.source() ); + setText( TargetTextOriginal, phrase.target() ); +} + +Phrase PhraseLVI::phrase() const +{ + return Phrase( text(SourceTextOriginal), text(TargetTextOriginal), + text(DefinitionText) ); +} + +QString PhraseLVI::makeKey( const QString& text ) const +{ + if ( text == NewPhrase ) + return QString::null; + + QString key; + for ( int i = 0; i < (int) text.length(); i++ ) { + if ( text[i] != QChar('&') ) + key += text[i].lower(); + } + // see Section 5, Exercise 4 of The Art of Computer Programming + key += QChar::null; + key += text; + return key; +} + +PhraseLV::PhraseLV( QWidget *parent, const char *name ) + : QListView( parent, name ) +{ + setAllColumnsShowFocus( TRUE ); + setShowSortIndicator( TRUE ); + for ( int i = 0; i < 3; i++ ) + addColumn( QString::null, 120 ); + setColumnText( PhraseLVI::SourceTextShown, tr("Source phrase") ); + setColumnText( PhraseLVI::TargetTextShown, tr("Translation") ); + setColumnText( PhraseLVI::DefinitionText, tr("Definition") ); + header()->setStretchEnabled( TRUE, -1 ); + what = new WhatPhrase( this ); +} + +PhraseLV::~PhraseLV() +{ +// delete what; +} + +QSize PhraseLV::sizeHint() const +{ + return QSize( QListView::sizeHint().width(), 50 ); +} diff --git a/tools/linguist/linguist/phraselv.h b/tools/linguist/linguist/phraselv.h new file mode 100644 index 0000000..cb06090 --- /dev/null +++ b/tools/linguist/linguist/phraselv.h @@ -0,0 +1,83 @@ +/********************************************************************** +** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved. +** +** This file is part of Qt 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 Qt 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 Qt Commercial licenses may use this file in +** accordance with the Qt 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. +** +**********************************************************************/ + +#ifndef PHRASELV_H +#define PHRASELV_H + +#include "phrase.h" + +#include <qlistview.h> + +class QWhatsThis; + +class PhraseLV; + +#define NewPhrase PhraseLV::tr( "(New Phrase)" ) + +class PhraseLVI : public QListViewItem +{ +public: + enum { SourceTextShown, TargetTextShown, DefinitionText, SourceTextOriginal, + TargetTextOriginal }; + + PhraseLVI( PhraseLV *parent, const Phrase& phrase, int accelKey = 0 ); + + virtual void setText( int column, const QString& text ); + virtual QString key( int column, bool ascending ) const; + + void setPhrase( const Phrase& phrase ); + Phrase phrase() const; + int accelKey() const { return akey; } + +private: + QString makeKey( const QString& text ) const; + + int akey; + QString sourceTextKey; + QString targetTextKey; +}; + +class PhraseLV : public QListView +{ + Q_OBJECT +public: + PhraseLV( QWidget *parent, const char *name ); + ~PhraseLV(); + + virtual QSize sizeHint() const; + +private: + QWhatsThis *what; +}; + +#endif diff --git a/tools/linguist/linguist/printout.cpp b/tools/linguist/linguist/printout.cpp new file mode 100644 index 0000000..53d944a --- /dev/null +++ b/tools/linguist/linguist/printout.cpp @@ -0,0 +1,182 @@ +/********************************************************************** +** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved. +** +** This file is part of Qt 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 Qt 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 Qt Commercial licenses may use this file in +** accordance with the Qt 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. +** +**********************************************************************/ + +#include "printout.h" + +#include <qprinter.h> +#include <qfontmetrics.h> + +PrintOut::PrintOut( QPrinter *printer ) + : pr( printer ), pdmetrics( printer ), nextRule( NoRule ), page( 0 ) +{ + p.begin( pr ); + QFont f( "Arial" ); + f8 = f; + f8.setPointSize( 8 ); + f10 = f; + f10.setPointSize( 10 ); + p.setFont( f10 ); + fmetrics = new QFontMetrics( p.fontMetrics() ); + hmargin = 5 * pdmetrics.width() / pdmetrics.widthMM(); // 5 mm + vmargin = 5 * pdmetrics.height() / pdmetrics.heightMM(); // 5 mm + hsize = pdmetrics.width() - 2 * hmargin; + vsize = pdmetrics.height() - vmargin; + dateTime = QDateTime::currentDateTime(); + breakPage(); + vsize -= voffset; + cp = Paragraph( QPoint(hmargin, voffset) ); +} + +PrintOut::~PrintOut() +{ + flushLine(); + delete fmetrics; + p.end(); +} + +void PrintOut::setRule( Rule rule ) +{ + if ( (int) nextRule < (int) rule ) + nextRule = rule; +} + +void PrintOut::setGuide( const QString& guide ) +{ + g = guide; +} + +void PrintOut::vskip() +{ + if ( !firstParagraph ) + voffset += 14; +} + +void PrintOut::flushLine( bool /* mayBreak */ ) +{ + if ( voffset + cp.rect.height() > vsize ) + breakPage(); + else if ( !firstParagraph ) + drawRule( nextRule ); + + for ( int i = 0; i < (int) cp.boxes.count(); i++ ) { + Box b = cp.boxes[i]; + b.rect.moveBy( 0, voffset ); + QRect r = b.rect; + p.setFont( b.font ); + p.drawText( r, b.align, b.text ); + } + voffset += cp.rect.height(); + + nextRule = NoRule; + cp = Paragraph( QPoint(hmargin, voffset) ); + firstParagraph = FALSE; +} + +void PrintOut::addBox( int percent, const QString& text, Style style, + int halign ) +{ + int align = halign | Qt::AlignTop; + QFont f = f10; + if ( style == Strong ) + f.setBold( TRUE ); + else if ( style == Emphasis ) + f.setItalic( TRUE ); + int wd = hsize * percent / 100; + QRect r( cp.rect.x() + cp.rect.width(), 0, wd, vsize ); + int ht = p.boundingRect( r, align, text ).height(); + + Box b( r, text, f, align ); + cp.boxes.append( b ); + cp.rect.setSize( QSize(cp.rect.width() + wd, QMAX(cp.rect.height(), ht)) ); +} + +void PrintOut::breakPage() +{ + static const int LeftAlign = Qt::AlignLeft | Qt::AlignTop; + static const int RightAlign = Qt::AlignRight | Qt::AlignTop; + QRect r1, r2; + int h1 = 0; + int h2 = 0; + + if ( page++ > 0 ) + pr->newPage(); + voffset = 0; + + p.setFont( f10 ); + r1 = QRect( hmargin, voffset, 3 * hsize / 4, vsize ); + r2 = QRect( r1.x() + r1.width(), voffset, hsize - r1.width(), vsize ); + h1 = p.boundingRect( r1, LeftAlign, pr->docName() ).height(); + p.drawText( r1, LeftAlign, pr->docName() ); + h2 = p.boundingRect( r2, RightAlign, QString::number(page) ).height(); + p.drawText( r2, RightAlign, QString::number(page) ); + voffset += QMAX( h1, h2 ); + + r1 = QRect( hmargin, voffset, hsize / 2, LeftAlign ); + p.setFont( f8 ); + h1 = p.boundingRect( r1, LeftAlign, dateTime.toString() ).height(); + p.drawText( r1, LeftAlign, dateTime.toString() ); + p.setFont( f10 ); + voffset += QMAX( h1, h2 ); + + voffset += 4; + p.drawLine( QPoint(hmargin, voffset), QPoint(hmargin + hsize, voffset) ); + voffset += 14; + firstParagraph = TRUE; +} + +void PrintOut::drawRule( Rule rule ) +{ + QPen pen; + + switch ( rule ) { + case NoRule: + voffset += 5; + break; + case ThinRule: + pen.setColor( QColor(192, 192, 192) ); + pen.setStyle( QPen::DotLine ); + pen.setWidth( 0 ); + p.setPen( pen ); + voffset += 5; + p.drawLine( QPoint(hmargin, voffset), + QPoint(hmargin + hsize, voffset) ); + p.setPen( QPen() ); + voffset += 2; + break; + case ThickRule: + voffset += 7; + p.drawLine( QPoint(hmargin, voffset), + QPoint(hmargin + hsize, voffset) ); + voffset += 4; + } +} diff --git a/tools/linguist/linguist/printout.h b/tools/linguist/linguist/printout.h new file mode 100644 index 0000000..d67191c --- /dev/null +++ b/tools/linguist/linguist/printout.h @@ -0,0 +1,126 @@ +/********************************************************************** +** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved. +** +** This file is part of Qt 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 Qt 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 Qt Commercial licenses may use this file in +** accordance with the Qt 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. +** +**********************************************************************/ + +#ifndef PRINTOUT_H +#define PRINTOUT_H + +#include <qfont.h> +#include <qpaintdevicemetrics.h> +#include <qpainter.h> +#include <qrect.h> +#include <qvaluelist.h> +#include <qdatetime.h> + +class QPrinter; +class QFontMetrics; + +class PrintOut +{ +public: + enum Rule { NoRule, ThinRule, ThickRule }; + enum Style { Normal, Strong, Emphasis }; + + PrintOut( QPrinter *printer ); + ~PrintOut(); + + void setRule( Rule rule ); + void setGuide( const QString& guide ); + void vskip(); + void flushLine( bool mayBreak = FALSE ); + void addBox( int percent, const QString& text = QString::null, + Style style = Normal, + int halign = Qt::AlignLeft | Qt::WordBreak ); + + int pageNum() const { return page; } + + struct Box + { + QRect rect; + QString text; + QFont font; + int align; + + Box() : align( 0 ) { } + Box( const QRect& r, const QString& t, const QFont& f, int a ) + : rect( r ), text( t ), font( f ), align( a ) { } + Box( const Box& b ) + : rect( b.rect ), text( b.text ), font( b.font ), + align( b.align ) { } + + Box& operator=( const Box& b ) { + rect = b.rect; + text = b.text; + font = b.font; + align = b.align; + return *this; + } + + bool operator==( const Box& b ) const { + return rect == b.rect && text == b.text && font == b.font && + align == b.align; + } + }; + +private: + void breakPage(); + void drawRule( Rule rule ); + + struct Paragraph { + QRect rect; + QValueList<Box> boxes; + + Paragraph() { } + Paragraph( QPoint p ) : rect( p, QSize(0, 0) ) { } + }; + + QPrinter *pr; + QPainter p; + QFont f8; + QFont f10; + QFontMetrics *fmetrics; + QPaintDeviceMetrics pdmetrics; + Rule nextRule; + Paragraph cp; + int page; + bool firstParagraph; + QString g; + QDateTime dateTime; + + int hmargin; + int vmargin; + int voffset; + int hsize; + int vsize; +}; + +#endif diff --git a/tools/linguist/linguist/simtexth.cpp b/tools/linguist/linguist/simtexth.cpp new file mode 100644 index 0000000..8bed388 --- /dev/null +++ b/tools/linguist/linguist/simtexth.cpp @@ -0,0 +1,239 @@ +/********************************************************************** +** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved. +** +** This file is part of Qt 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 Qt 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 Qt Commercial licenses may use this file in +** accordance with the Qt 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. +** +**********************************************************************/ + +#include "simtexth.h" + +#include <metatranslator.h> + +#include <qcstring.h> +#include <qdict.h> +#include <qmap.h> +#include <qstring.h> +#include <qstringlist.h> +#include <qvaluelist.h> + +#include <string.h> + +typedef QValueList<MetaTranslatorMessage> TML; + +/* + How similar are two texts? The approach used here relies on co-occurrence + matrices and is very efficient. + + Let's see with an example: how similar are "here" and "hither"? The + co-occurrence matrix M for "here" is M[h,e] = 1, M[e,r] = 1, M[r,e] = 1, and 0 + elsewhere; the matrix N for "hither" is N[h,i] = 1, N[i,t] = 1, ..., + N[h,e] = 1, N[e,r] = 1, and 0 elsewhere. The union U of both matrices is the + matrix U[i,j] = max { M[i,j], N[i,j] }, and the intersection V is + V[i,j] = min { M[i,j], N[i,j] }. The score for a pair of texts is + + score = (sum of V[i,j] over all i, j) / (sum of U[i,j] over all i, j), + + a formula suggested by Arnt Gulbrandsen. Here we have + + score = 2 / 6, + + or one third. + + The implementation differs from this in a few details. Most importantly, + repetitions are ignored; for input "xxx", M[x,x] equals 1, not 2. +*/ + +/* + Every character is assigned to one of 20 buckets so that the co-occurrence + matrix requires only 20 * 20 = 400 bits, not 256 * 256 = 65536 bits or even + more if we want the whole Unicode. Which character falls in which bucket is + arbitrary. + + The second half of the table is a replica of the first half, because of + laziness. +*/ +static const int indexOf[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +// ! " # $ % & ' ( ) * + , - . / + 0, 2, 6, 7, 10, 12, 15, 19, 2, 6, 7, 10, 12, 15, 19, 0, +// 0 1 2 3 4 5 6 7 8 9 : ; < = > ? + 1, 3, 4, 5, 8, 9, 11, 13, 14, 16, 2, 6, 7, 10, 12, 15, +// @ A B C D E F G H I J K L M N O + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 6, 10, 11, 12, 13, 14, +// P Q R S T U V W X Y Z [ \ ] ^ _ + 15, 12, 16, 17, 18, 19, 2, 10, 15, 7, 19, 2, 6, 7, 10, 0, +// ` a b c d e f g h i j k l m n o + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 6, 10, 11, 12, 13, 14, +// p q r s t u v w x y z { | } ~ + 15, 12, 16, 17, 18, 19, 2, 10, 15, 7, 19, 2, 6, 7, 10, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 6, 7, 10, 12, 15, 19, 2, 6, 7, 10, 12, 15, 19, 0, + 1, 3, 4, 5, 8, 9, 11, 13, 14, 16, 2, 6, 7, 10, 12, 15, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 6, 10, 11, 12, 13, 14, + 15, 12, 16, 17, 18, 19, 2, 10, 15, 7, 19, 2, 6, 7, 10, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 6, 10, 11, 12, 13, 14, + 15, 12, 16, 17, 18, 19, 2, 10, 15, 7, 19, 2, 6, 7, 10, 0 +}; + +/* + The entry bitCount[i] (for i between 0 and 255) is the number of bits used to + represent i in binary. +*/ +static const int bitCount[256] = { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 +}; + +struct CoMatrix +{ + /* + The matrix has 20 * 20 = 400 entries. This requires 50 bytes, or 13 + words. Some operations are performed on words for more efficiency. + */ + union { + Q_UINT8 b[52]; + Q_UINT32 w[13]; + }; + + CoMatrix() { memset( b, 0, 52 ); } + CoMatrix( const char *text ) { + char c = '\0', d; + memset( b, 0, 52 ); + /* + The Knuth books are not in the office only for show; they help make + loops 30% faster and 20% as readable. + */ + while ( (d = *text) != '\0' ) { + setCoocc( c, d ); + if ( (c = *++text) != '\0' ) { + setCoocc( d, c ); + text++; + } + } + } + + void setCoocc( char c, char d ) { + int k = indexOf[(uchar) c] + 20 * indexOf[(uchar) d]; + b[k >> 3] |= k & 0x7; + } + + int worth() const { + int w = 0; + for ( int i = 0; i < 50; i++ ) + w += bitCount[b[i]]; + return w; + } +}; + +static inline CoMatrix reunion( const CoMatrix& m, const CoMatrix& n ) +{ + CoMatrix p; + for ( int i = 0; i < 13; i++ ) + p.w[i] = m.w[i] | n.w[i]; + return p; +} + +static inline CoMatrix intersection( const CoMatrix& m, const CoMatrix& n ) +{ + CoMatrix p; + for ( int i = 0; i < 13; i++ ) + p.w[i] = m.w[i] & n.w[i]; + return p; +} + +CandidateList similarTextHeuristicCandidates( const MetaTranslator *tor, + const char *text, + int maxCandidates ) +{ + QValueList<int> scores; + CandidateList candidates; + CoMatrix cmTarget( text ); + int targetLen = qstrlen( text ); + + TML all = tor->translatedMessages(); + TML::Iterator it; + + for ( it = all.begin(); it != all.end(); ++it ) { + if ( (*it).type() == MetaTranslatorMessage::Unfinished || + (*it).translation().isEmpty() ) + continue; + + QString s = tor->toUnicode( (*it).sourceText(), (*it).utf8() ); + CoMatrix cm( s.latin1() ); + int delta = QABS( (int) s.length() - targetLen ); + + /* + Here is the score formula. A comment above contains a + discussion on a similar (but simpler) formula. + */ + int score = ( (intersection(cm, cmTarget).worth() + 1) << 10 ) / + ( reunion(cm, cmTarget).worth() + (delta << 1) + 1 ); + + if ( (int) candidates.count() == maxCandidates && + score > scores[maxCandidates - 1] ) + candidates.remove( candidates.last() ); + if ( (int) candidates.count() < maxCandidates && score >= 190 ) { + Candidate cand( s, (*it).translation() ); + + int i; + for ( i = 0; i < (int) candidates.count(); i++ ) { + if ( score >= scores[i] ) { + if ( score == scores[i] ) { + if ( candidates[i] == cand ) + goto continue_outer_loop; + } else { + break; + } + } + } + scores.insert( scores.at(i), score ); + candidates.insert( candidates.at(i), cand ); + } + continue_outer_loop: + ; + } + return candidates; +} diff --git a/tools/linguist/linguist/simtexth.h b/tools/linguist/linguist/simtexth.h new file mode 100644 index 0000000..91d8cbd --- /dev/null +++ b/tools/linguist/linguist/simtexth.h @@ -0,0 +1,64 @@ +/********************************************************************** +** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved. +** +** This file is part of Qt 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 Qt 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 Qt Commercial licenses may use this file in +** accordance with the Qt 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. +** +**********************************************************************/ + +#ifndef SIMTEXTH_H +#define SIMTEXTH_H + +#include <qstring.h> +#include <qvaluelist.h> + +class MetaTranslator; + +struct Candidate { + QString source; + QString target; + + Candidate() { } + Candidate( const QString& source0, const QString& target0 ) + : source( source0 ), target( target0 ) { } +}; + +inline bool operator==( const Candidate& c, const Candidate& d ) { + return c.target == d.target && c.source == d.source; +} +inline bool operator!=( const Candidate& c, const Candidate& d ) { + return !operator==( c, d ); +} + +typedef QValueList<Candidate> CandidateList; + +CandidateList similarTextHeuristicCandidates( const MetaTranslator *tor, + const char *text, + int maxCandidates ); + +#endif diff --git a/tools/linguist/linguist/statistics.ui b/tools/linguist/linguist/statistics.ui new file mode 100644 index 0000000..c897b78 --- /dev/null +++ b/tools/linguist/linguist/statistics.ui @@ -0,0 +1,259 @@ +<!DOCTYPE UI><UI version="3.1" stdsetdef="1"> +<class>Statistics</class> +<comment>********************************************************************* +** Copyright (C) 2002-2008 Trolltech ASA. All rights reserved. +** +** This file is part of Qt 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 Qt 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 Qt Commercial licenses may use this file in +** accordance with the Qt 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. +** +*********************************************************************</comment> +<widget class="QDialog"> + <property name="name"> + <cstring>Statistics</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>336</width> + <height>164</height> + </rect> + </property> + <property name="caption"> + <string>Statistics</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget" row="1" column="0"> + <property name="name"> + <cstring>layout2</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer> + <property name="name"> + <cstring>spacer4_2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QPushButton"> + <property name="name"> + <cstring>closeBtn</cstring> + </property> + <property name="text"> + <string>&Close</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer4</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + <widget class="QFrame" row="0" column="0"> + <property name="name"> + <cstring>frame4</cstring> + </property> + <property name="frameShape"> + <enum>GroupBoxPanel</enum> + </property> + <property name="frameShadow"> + <enum>Raised</enum> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="0" column="2"> + <property name="name"> + <cstring>textLabel4</cstring> + </property> + <property name="text"> + <string>Translation</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="0" column="1"> + <property name="name"> + <cstring>textLabel5</cstring> + </property> + <property name="text"> + <string>Source</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="1" column="1"> + <property name="name"> + <cstring>untrWords</cstring> + </property> + <property name="text"> + <string>0</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="1" column="2"> + <property name="name"> + <cstring>trWords</cstring> + </property> + <property name="text"> + <string>0</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Words:</string> + </property> + </widget> + <widget class="QLabel" row="2" column="2"> + <property name="name"> + <cstring>trChars</cstring> + </property> + <property name="text"> + <string>0</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="2" column="1"> + <property name="name"> + <cstring>untrChars</cstring> + </property> + <property name="text"> + <string>0</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>textLabel3</cstring> + </property> + <property name="text"> + <string>Characters:</string> + </property> + </widget> + <widget class="QLabel" row="3" column="0"> + <property name="name"> + <cstring>textLabel6</cstring> + </property> + <property name="text"> + <string>Characters (with spaces):</string> + </property> + </widget> + <widget class="QLabel" row="3" column="2"> + <property name="name"> + <cstring>trCharsSpc</cstring> + </property> + <property name="text"> + <string>0</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="3" column="1"> + <property name="name"> + <cstring>untrCharsSpc</cstring> + </property> + <property name="text"> + <string>0</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + </grid> + </widget> + </grid> +</widget> +<connections> + <connection> + <sender>closeBtn</sender> + <signal>clicked()</signal> + <receiver>Statistics</receiver> + <slot>close()</slot> + </connection> +</connections> +<includes> + <include location="local" impldecl="in implementation">statistics.ui.h</include> +</includes> +<signals> + <signal>closed()</signal> +</signals> +<slots> + <slot>updateStats( int w1, int c1, int cs1, int w2, int c2, int cs2 )</slot> + <slot>closeEvent( QCloseEvent * e )</slot> +</slots> +<functions> + <function access="private" specifier="non virtual">init()</function> +</functions> +<pixmapinproject/> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/tools/linguist/linguist/statistics.ui.h b/tools/linguist/linguist/statistics.ui.h new file mode 100644 index 0000000..fe9b448 --- /dev/null +++ b/tools/linguist/linguist/statistics.ui.h @@ -0,0 +1,53 @@ +/********************************************************************** +** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved. +** +** This file is part of Qt 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 Qt 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 Qt Commercial licenses may use this file in +** accordance with the Qt 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. +** +**********************************************************************/ + +void Statistics::init() +{ + setFixedHeight( sizeHint().height() ); +} + +void Statistics::updateStats( int w1, int c1, int cs1, int w2, int c2, int cs2 ) +{ + untrWords->setText( QString::number( w1 ) ); + untrChars->setText( QString::number( c1 ) ); + untrCharsSpc->setText( QString::number( cs1 ) ); + trWords->setText( QString::number( w2 ) ); + trChars->setText( QString::number( c2 ) ); + trCharsSpc->setText( QString::number( cs2 ) ); +} + +void Statistics::closeEvent( QCloseEvent * e ) +{ + emit closed(); + QDialog::closeEvent( e ); +} diff --git a/tools/linguist/linguist/trwindow.cpp b/tools/linguist/linguist/trwindow.cpp new file mode 100644 index 0000000..e8725e5 --- /dev/null +++ b/tools/linguist/linguist/trwindow.cpp @@ -0,0 +1,2071 @@ +/********************************************************************** +** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved. +** +** This file is part of Qt 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 Qt 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 Qt Commercial licenses may use this file in +** accordance with the Qt 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 <qaccel.h> +#include <qaction.h> +#include <qapplication.h> +#include <qbitmap.h> +#include <qdict.h> +#include <qdockarea.h> +#include <qdockwindow.h> +#include <qfile.h> +#include <qfiledialog.h> +#include <qfileinfo.h> +#include <qheader.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qmenubar.h> +#include <qmessagebox.h> +#include <qpopupmenu.h> +#include <qregexp.h> +#include <qsettings.h> +#include <qstatusbar.h> +#include <qtoolbar.h> +#include <qwhatsthis.h> +#include <qprocess.h> +#include <qassistantclient.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 QValueList<MetaTranslatorMessage> TML; + +static const int ErrorMS = 600000; // for error messages +static const int MessageMS = 2500; + +QPixmap * TrWindow::pxOn = 0; +QPixmap * TrWindow::pxOff = 0; +QPixmap * TrWindow::pxObsolete = 0; +QPixmap * TrWindow::pxDanger = 0; + +enum Ending { End_None, End_FullStop, End_Interrobang, End_Colon, + End_Ellipsis }; + +static Ending ending( QString 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(QString("...")) ) + 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 QAction +{ +public: + Action( QPopupMenu *pop, const QString& menuText, QObject *receiver, + const char *member, const QString &imageName = QString::null, + int accel = 0, bool toggle = FALSE ); + Action( QPopupMenu *pop, const QString& menuText, int accel = 0, + bool toggle = FALSE ); + + virtual void setWhatsThis( const QString& whatsThis ); + + bool addToToolbar( QToolBar *tb, const QString& text ); +}; + +Action::Action( QPopupMenu *pop, const QString& menuText, QObject *receiver, + const char *member, const QString &imageName, int accel, + bool toggle ) + : QAction( pop->parent(), (const char *) 0, toggle ) +{ + setMenuText( menuText ); + setAccel( accel ); + + if ( !imageName.isEmpty() ) { + QPixmap enabledPix = QPixmap::fromMimeSource( imageName ); + QIconSet s( enabledPix ); + if ( imageName != "whatsthis.xpm" ) { + QPixmap disabledPix = QPixmap::fromMimeSource( "d_" + imageName ); + s.setPixmap( disabledPix, QIconSet::Small, QIconSet::Disabled ); + } + setIconSet( s ); + } + QAction::addTo( pop ); + connect( this, SIGNAL(activated()), receiver, member ); +} + +Action::Action( QPopupMenu *pop, const QString& menuText, int accel, + bool toggle ) + : QAction( pop->parent(), (const char *) 0, toggle ) +{ + QAction::addTo( pop ); + setMenuText( menuText ); + setAccel( accel ); +} + +void Action::setWhatsThis( const QString& whatsThis ) +{ + QAction::setWhatsThis( whatsThis ); + setStatusTip( whatsThis ); +} + +bool Action::addToToolbar( QToolBar *tb, const QString& text ) +{ + setText( text ); + return QAction::addTo( tb ); +} + +const QPixmap TrWindow::pageCurl() +{ + QPixmap pixmap; + pixmap = QPixmap::fromMimeSource( "pagecurl.png" ); + if ( !pixmap.isNull() ) { + QBitmap pageCurlMask( pagecurl_mask_width, pagecurl_mask_height, + pagecurl_mask_bits, TRUE ); + pixmap.setMask( pageCurlMask ); + } + + return pixmap; +} + +TrWindow::TrWindow() + : QMainWindow( 0, "translation window", WType_TopLevel | WDestructiveClose ) +{ + +#ifndef Q_WS_MACX + setIcon( QPixmap::fromMimeSource( "appicon.png" ) ); +#endif + + // Create the application global listview symbols + pxOn = new QPixmap( QPixmap::fromMimeSource( "s_check_on.png" ) ); + pxOff = new QPixmap( QPixmap::fromMimeSource( "s_check_off.png" ) ); + pxObsolete = new QPixmap( QPixmap::fromMimeSource( "d_s_check_obs.png" ) ); + pxDanger = new QPixmap( QPixmap::fromMimeSource( "s_check_danger.png" ) ); + + // Set up the Scope dock window + QDockWindow * dwScope = new QDockWindow( QDockWindow::InDock, this, + "context"); + dwScope->setResizeEnabled( TRUE ); + dwScope->setCloseMode( QDockWindow::Always ); + addDockWindow( dwScope, tr("Context"), Qt::DockLeft ); + dwScope->setCaption( tr("Context") ); + dwScope->setFixedExtentWidth( 200 ); + lv = new QListView( dwScope, "context list view" ); + lv->setShowSortIndicator( TRUE ); + lv->setAllColumnsShowFocus( TRUE ); + lv->header()->setStretchEnabled( TRUE, 1 ); + QFontMetrics fm( font() ); + lv->addColumn( tr("Done"), fm.width( tr("Done") ) + 10 ); + lv->addColumn( tr("Context") ); + lv->addColumn( tr("Items"), 55 ); + lv->setColumnAlignment( 0, Qt::AlignCenter ); + lv->setColumnAlignment( 2, Qt::AlignRight ); + lv->setSorting( 0 ); + lv->setHScrollBarMode( QScrollView::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 QLabel( statusBar(), "progress" ); + statusBar()->addWidget( progress, 0, TRUE ); + modified = new QLabel( QString(" %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("Qt Linguist") ); + h = new FindDialog( TRUE, this, "replace", FALSE ); + h->setCaption( tr("Qt Linguist") ); + findMatchCase = FALSE; + findWhere = 0; + foundItem = 0; + foundScope = 0; + foundWhere = 0; + foundOffset = 0; + + connect( lv, SIGNAL(selectionChanged(QListViewItem *)), + this, SLOT(showNewScope(QListViewItem *)) ); + + connect( slv, SIGNAL(currentChanged(QListViewItem *)), + this, SLOT(showNewCurrent(QListViewItem *)) ); + + connect( slv, SIGNAL(clicked(QListViewItem *, const QPoint&, int)), + this, SLOT(showNewCurrent(QListViewItem *)) ); + + connect( slv, SIGNAL(clicked(QListViewItem *, const QPoint&, int)), + this, SLOT(toggleFinished(QListViewItem *, const QPoint&, int)) ); + + connect( me, SIGNAL(translationChanged(const QString&)), + this, SLOT(updateTranslation(const QString&)) ); + 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 QString&, int, bool)), + this, SLOT(findNext(const QString&, int, bool)) ); + + QWhatsThis::add( lv, tr("This panel lists the source contexts.") ); + + QWhatsThis::add( slv, tr("This panel lists the source texts. " + "Items that violate validation rules " + "are marked with a warning.") ); + showNewCurrent( 0 ); + + QSize as( qApp->desktop()->size() ); + as -= QSize( 30, 30 ); + resize( QSize( 1000, 800 ).boundedTo( as ) ); + readConfig(); + stats = 0; + srcWords = 0; + srcChars = 0; + srcCharsSpc = 0; +} + +TrWindow::~TrWindow() +{ + writeConfig(); + delete stats; +} + +void TrWindow::openFile( const QString& name ) +{ + if ( !name.isEmpty() ) { + statusBar()->message( tr("Loading...") ); + qApp->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; + QDict<ContextLVI> contexts( 1009 ); + + srcWords = 0; + srcChars = 0; + srcCharsSpc = 0; + for ( it = all.begin(); it != all.end(); ++it ) { + qApp->processEvents(); + ContextLVI *c = contexts.find( QString((*it).context()) ); + if ( c == 0 ) { + c = new ContextLVI( lv, tor.toUnicode((*it).context(), + (*it).utf8()) ); + contexts.insert( QString((*it).context()), c ); + } + if ( QCString((*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(); + QMessageBox::warning( this, tr("Qt Linguist"), + tr("Cannot open '%1'.").arg(name) ); + } + } +} + +void TrWindow::open() +{ + if ( maybeSave() ) { + QString newFilename = QFileDialog::getOpenFileName( filename, + tr("Qt 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 { + QMessageBox::warning( this, tr("Qt Linguist"), tr("Cannot save '%1'.") + .arg(filename) ); + } +} + +void TrWindow::saveAs() +{ + QString newFilename = QFileDialog::getSaveFileName( filename, + tr( "Qt translation source (*.ts)\n" + "All files (*)"), + this, "save_as" ); + if ( !newFilename.isEmpty() ) { + filename = newFilename; + save(); + updateCaption(); + } +} + +void TrWindow::release() +{ + QString newFilename = filename; + newFilename.replace( QRegExp(".ts$"), "" ); + newFilename += QString( ".qm" ); + + newFilename = QFileDialog::getSaveFileName( newFilename, + tr("Qt 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 + QMessageBox::warning( this, tr("Qt Linguist"), + tr("Cannot save '%1'.").arg(newFilename) ); + } +} + +void TrWindow::print() +{ + int pageNum = 0; + + if ( printer.setup(this) ) { + QApplication::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 ); + + QString type; + switch ( m->message().type() ) { + case MetaTranslatorMessage::Finished: + type = tr( "finished" ); + break; + case MetaTranslatorMessage::Unfinished: + type = m->danger() ? tr( "unresolved" ) : QString( "unfinished" ); + break; + case MetaTranslatorMessage::Obsolete: + type = tr( "obsolete" ); + break; + default: + type = QString( "" ); + } + pout.addBox( 40, m->sourceText() ); + pout.addBox( 4 ); + pout.addBox( 40, m->translation() ); + pout.addBox( 4 ); + pout.addBox( 12, type, PrintOut::Normal, Qt::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 ); + QApplication::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() ); + QString delayedMsg; + QListViewItem * j = foundScope; + QListViewItem * k = indexToItem( slv, foundItem ); + QListViewItem * oldScope = lv->currentItem(); + + if ( lv->childCount() == 0 ) + return; +#if 1 + /* + As long as we don't implement highlighting of the text in the QTextView, + 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 ); + QListViewItem * 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(); + qApp->beep(); + QMessageBox::warning( this, tr("Qt Linguist"), + QString( 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( QListView * view, QListViewItem * item ) +{ + int no = 0; + QListViewItem * tmp; + + if( view && item ){ + if( (tmp = view->firstChild()) != 0 ) + do { + no++; + tmp = tmp->nextSibling(); + } while( tmp && (tmp != item) ); + } + return no; +} + +QListViewItem * TrWindow::indexToItem( QListView * view, int index ) +{ + QListViewItem * item = 0; + + if ( view && index > 0 ) { + item = view->firstChild(); + while( item && index-- > 0 ) + item = item->nextSibling(); + } + return item; +} + +bool TrWindow::searchItem( const QString & searchWhat, QListViewItem * j, + QListViewItem * 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() +{ + QString name; + for (;;) { + name = QFileDialog::getSaveFileName( QString::null, + tr("Qt phrase books (*.qph)\n" + "All files (*)"), + this, "new_phrasebook", + tr("Create New Phrase Book") ); + if ( !QFile::exists(name) ) + break; + QMessageBox::warning( this, tr("Qt 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() +{ + QString phrasebooks( qInstallPathData() ); + QString name = QFileDialog::getOpenFileName( phrasebooks + "/phrasebooks", + tr("Qt 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("Qt 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() +{ + QAssistantClient *ac = new QAssistantClient( qInstallPathBins(), this ); + ac->showPage( QString( qInstallPathDocs() ) + "/html/linguist-manual.html" ); +} + +void TrWindow::about() +{ + AboutDialog about( this, 0, TRUE ); + about.versionLabel->setText( tr("Version %1").arg(QT_VERSION_STR) ); + about.exec(); +} + +void TrWindow::aboutQt() +{ + QMessageBox::aboutQt( this, tr("Qt Linguist") ); +} + +void TrWindow::setupPhrase() +{ + bool enabled = !phraseBooks.isEmpty(); + phrasep->setItemEnabled( closePhraseBookId, enabled ); + phrasep->setItemEnabled( editPhraseBookId, enabled ); + phrasep->setItemEnabled( printPhraseBookId, enabled ); +} + +void TrWindow::closeEvent( QCloseEvent *e ) +{ + if ( maybeSave() ) + e->accept(); + else + e->ignore(); +} + +bool TrWindow::maybeSave() +{ + if ( dirty ) { + switch ( QMessageBox::information(this, tr("Qt Linguist"), + tr("Do you want to save '%1'?") + .arg(filename), + QMessageBox::Yes | QMessageBox::Default, + QMessageBox::No, + QMessageBox::Cancel | QMessageBox::Escape ) ) + { + case QMessageBox::Cancel: + return FALSE; + case QMessageBox::Yes: + save(); + return !dirty; + case QMessageBox::No: + break; + } + } + return TRUE; +} + +void TrWindow::updateCaption() +{ + QString 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( "Qt Linguist by Trolltech" ); + else + cap = tr( "%1 - %2" ).arg( tr("Qt 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( QListViewItem *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( QListViewItem *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 QString& translation ) +{ + QListViewItem *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 ) +{ + QListViewItem *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() ) + qApp->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(); + } + qApp->beep(); + } + updateStatistics(); +} + +void TrWindow::toggleFinished( QListViewItem *item, const QPoint& /* 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() ) + qApp->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. + QListViewItem * cItem = lv->currentItem(); // context item + QListViewItem * 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 ); + qApp->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 ); + qApp->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 ); + qApp->beep(); +} + +static QListViewItem * lastChild( QListView * view ) +{ + if ( view ) { + QListViewItem * 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. + QListViewItem * cItem = lv->currentItem(); // context item + QListViewItem * 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 ); + qApp->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 ); + qApp->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 ); + qApp->beep(); +} + +void TrWindow::prev() +{ + QListViewItem * cItem = lv->currentItem(); // context item + QListViewItem * mItem = slv->currentItem(); // message item + QListViewItem * 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() +{ + QListViewItem * cItem = lv->currentItem(); // context item + QListViewItem * mItem = slv->currentItem(); // message item + QListViewItem * 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 QString& text, int where, bool matchCase ) +{ + findText = text; + if ( findText.isEmpty() ) + findText = QString( "magicwordthatyoushouldavoid" ); + findWhere = where; + findMatchCase = matchCase; + findAgainAct->setEnabled( TRUE ); + findAgain(); +} + +void TrWindow::revalidate() +{ + ContextLVI *c = (ContextLVI *) lv->firstChild(); + QListViewItem * 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 ); + QListViewItem * tmp = indexToItem( slv, oldItemNo ); + if( tmp ) + setCurrentMessageItem( tmp ); + } + slv->setUpdatesEnabled( TRUE ); + slv->triggerUpdate(); +} + +QString TrWindow::friendlyString( const QString& str ) +{ + QString f = str.lower(); + f.replace( QRegExp(QString("[.,:;!?()-]")), QString(" ") ); + f.replace( "&", QString("") ); + f = f.simplifyWhiteSpace(); + f = f.lower(); + return f; +} + +void TrWindow::setupMenuBar() +{ + QMenuBar * m = menuBar(); + QPopupMenu * filep = new QPopupMenu( this ); + QPopupMenu * editp = new QPopupMenu( this ); + QPopupMenu * translationp = new QPopupMenu( this ); + QPopupMenu * validationp = new QPopupMenu( this ); + validationp->setCheckable( TRUE ); + phrasep = new QPopupMenu( this ); + closePhraseBookp = new QPopupMenu( this ); + editPhraseBookp = new QPopupMenu( this ); + printPhraseBookp = new QPopupMenu( this ); + QPopupMenu * viewp = new QPopupMenu( this ); + viewp->setCheckable( TRUE ); + QPopupMenu * helpp = new QPopupMenu( 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", QAccel::stringToKey(tr("Ctrl+O")) ); + + filep->insertSeparator(); + + saveAct = new Action( filep, tr("&Save"), this, SLOT(save()), + "filesave.png", QAccel::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", QAccel::stringToKey(tr("Ctrl+P")) ); + + filep->insertSeparator(); + + recentFilesMenu = new QPopupMenu( this ); + filep->insertItem( tr("Re¢ly 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()), + QString::null, QAccel::stringToKey(tr("Ctrl+Q")) ); + // Edit menu + undoAct = new Action( editp, tr("&Undo"), me, SLOT(undo()), + "undo.png", QAccel::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", QAccel::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", QAccel::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", QAccel::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", QAccel::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()), + QString::null, QAccel::stringToKey(tr("Ctrl+A")) ); + selectAllAct->setEnabled( FALSE ); + editp->insertSeparator(); + findAct = new Action( editp, tr("&Find..."), this, SLOT(find()), + "searchfind.png", QAccel::stringToKey(tr("Ctrl+F")) ); + findAct->setEnabled( FALSE ); + findAgainAct = new Action( editp, tr("Find &Next"), + this, SLOT(findAgain()), QString::null, Key_F3 ); + findAgainAct->setEnabled( FALSE ); +#ifdef notyet + replaceAct = new Action( editp, tr("&Replace..."), this, SLOT(replace()), + QAccel::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", QAccel::stringToKey(tr("Ctrl+K")) ); + nextUnfinishedAct = new Action( translationp, tr("&Next Unfinished"), + this, SLOT(nextUnfinished()), + "nextunfinished.png", QAccel::stringToKey(tr("Ctrl+L")) ); + + prevAct = new Action( translationp, tr("P&rev"), + this, SLOT(prev()), "prev.png", + QAccel::stringToKey(tr("Ctrl+Shift+K")) ); + nextAct = new Action( translationp, tr("Ne&xt"), + this, SLOT(next()), "next.png", + QAccel::stringToKey(tr("Ctrl+Shift+L")) ); + doneAndNextAct = new Action( translationp, tr("Done and &Next"), + this, SLOT(doneAndNext()), "doneandnext.png", + QAccel::stringToKey(tr("Ctrl+Enter")) ); + doneAndNextAlt = new QAction( this ); + doneAndNextAlt->setAccel( QAccel::stringToKey(tr("Ctrl+Return")) ); + connect( doneAndNextAlt, SIGNAL(activated()), this, SLOT(doneAndNext()) ); + beginFromSourceAct = new Action( translationp, tr("&Begin from Source"), + me, SLOT(beginFromSource()), + QString::null, QAccel::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()), + QString::null, QAccel::stringToKey(tr("Ctrl+N")) ); + openPhraseBookAct = new Action( phrasep, tr("&Open Phrase Book..."), + this, SLOT(openPhraseBook()), + "book.png", QAccel::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()) ); + aboutQtAct = new Action( helpp, tr("About &Qt"), this, SLOT(aboutQt()) ); + helpp->insertSeparator(); + whatsThisAct = new Action( helpp, tr("&What's This?"), + this, SLOT(whatsThis()), "whatsthis.xpm", SHIFT + Key_F1 ); + + openAct->setWhatsThis( tr("Open a Qt translation source file (TS file) for" + " editing.") ); + saveAct->setWhatsThis( tr("Save changes made to this Qt translation " + "source file.") ); + saveAsAct->setWhatsThis( tr("Save changes made to this Qt translation" + "source file into a new file.") ); + releaseAct->setWhatsThis( tr("Create a Qt message file suitable for" + " released applications" + " from the current message file.") ); + printAct->setWhatsThis( tr("Print a list of all the phrases in the current" + " Qt 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("Qt Linguist")) ); + aboutAct->setWhatsThis( tr("Display information about %1.") + .arg(tr("Qt Linguist")) ); + aboutQtAct->setWhatsThis( tr("Display information about the Qt 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() +{ + QToolBar *filet = new QToolBar( tr("File"), this ); + QToolBar *editt = new QToolBar( tr("Edit"), this ); + QToolBar *translationst = new QToolBar( tr("Translation"), this ); + QToolBar *validationt = new QToolBar( tr("Validation"), this ); + QToolBar *helpt = new QToolBar( 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( QListViewItem *item ) +{ + lv->ensureItemVisible( item ); + lv->setSelected( item, TRUE ); +} + +void TrWindow::setCurrentMessageItem( QListViewItem *item ) +{ + slv->ensureItemVisible( item ); + slv->setSelected( item, TRUE ); +} + +QString TrWindow::friendlyPhraseBookName( int k ) +{ + return QFileInfo( phraseBookNames[k] ).fileName(); +} + +bool TrWindow::openPhraseBook( const QString& name ) +{ + PhraseBook *pb = new PhraseBook; + if ( !pb->load(name) ) { + QMessageBox::warning( this, tr("Qt 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( QString& name, const PhraseBook& pb ) +{ + if ( !name.contains( ".qph" ) && !name.contains(".") ) + name += ".qph"; + + if ( !pb.save(name) ) { + QMessageBox::warning( this, tr("Qt Linguist"), + tr("Cannot create phrase book '%1'.") + .arg(name) ); + return FALSE; + } + return TRUE; +} + +void TrWindow::updateProgress() +{ + if ( numNonobsolete == 0 ) + progress->setText( QString(" " " ") ); + else + progress->setText( QString(" %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() +{ + QPtrListIterator<PhraseBook> pb = phraseBooks; + PhraseBook::Iterator p; + PhraseBook *ent; + phraseDict.clear(); + while ( pb.current() != 0 ) { + for ( p = (*pb)->begin(); p != (*pb)->end(); ++p ) { + QString f = friendlyString( (*p).source() ); + if ( f.length() > 0 ) { + f = QStringList::split( QChar(' '), 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 QString& source ) +{ + PhraseBook phrases; + QString f = friendlyString( source ); + QStringList lookupWords = QStringList::split( QChar(' '), f ); + QStringList::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 QString& source, const QString& translation, + bool verbose ) +{ + if ( acceleratorsAct->isOn() ) { + int sk = QAccel::shortcutKey( source ); + int tk = QAccel::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() ) { + QString fsource = friendlyString( source ); + QString ftranslation = friendlyString( translation ); + QStringList lookupWords = QStringList::split( QChar(' '), fsource ); + QStringList::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() +{ + QString keybase( "/Qt Linguist/" + + QString::number( (QT_VERSION >> 16) & 0xff ) + + "." + QString::number( (QT_VERSION >> 8) & 0xff ) + "/" ); + QSettings config; + + config.insertSearchPath( QSettings::Windows, "/Trolltech" ); + + QRect 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() ) ); + + QRect desk = QApplication::desktop()->geometry(); + QRect inter = desk.intersect( r ); + resize( r.size() ); + if ( inter.width() * inter.height() > ( r.width() * r.height() / 20 ) ) { + move( r.topLeft() ); + } + } + + QDockWindow * dw; + dw = (QDockWindow *) 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 == QDockWindow::OutsideDock ) { + dw->undock(); + dw->show(); + } + dw->setGeometry( r ); + + dw = (QDockWindow *) 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 == QDockWindow::OutsideDock ) { + dw->undock(); + dw->show(); + } + dw->setGeometry( r ); + + dw = (QDockWindow *) 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 == QDockWindow::OutsideDock ) { + dw->undock(); + dw->show(); + } + dw->setGeometry( r ); + QApplication::sendPostedEvents(); +} + +void TrWindow::writeConfig() +{ + QString keybase( "/Qt Linguist/" + + QString::number( (QT_VERSION >> 16) & 0xff ) + + "." + QString::number( (QT_VERSION >> 8) & 0xff ) + "/" ); + QSettings config; + + config.insertSearchPath( QSettings::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() ); + + QDockWindow * dw =(QDockWindow *) 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 =(QDockWindow *) 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 =(QDockWindow *) 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; + QStringList::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 QString &fn, QStringList &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() +{ + QListViewItem * 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( QListViewItem* ci, QListViewItem* 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 QString& 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] == QChar('_') ) { + if ( !inWord ) { + trW++; + inWord = TRUE; + } + } else { + inWord = FALSE; + } + if ( !text[i].isSpace() ) + trC++; + } +} diff --git a/tools/linguist/linguist/trwindow.h b/tools/linguist/linguist/trwindow.h new file mode 100644 index 0000000..38cba25 --- /dev/null +++ b/tools/linguist/linguist/trwindow.h @@ -0,0 +1,237 @@ +/********************************************************************** +** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved. +** +** This file is part of Qt 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 Qt 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 Qt Commercial licenses may use this file in +** accordance with the Qt 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. +** +**********************************************************************/ + +#ifndef TRWINDOW_H +#define TRWINDOW_H + +#include "phrase.h" + +#include <metatranslator.h> + +#include <qmainwindow.h> +#include <qptrlist.h> +#include <qdict.h> +#include <qprinter.h> +#include <qstringlist.h> +#include <qpixmap.h> +#include <qlistview.h> + +class QAction; +class QDialog; +class QLabel; +class QListView; +class QListViewItem; +class QPrinter; + +class Action; +class FindDialog; +class MessageEditor; + +class PhraseLV; +class ContextLVI; +class Statistics; + +class TrWindow : public QMainWindow +{ + Q_OBJECT +public: + static QPixmap * pxOn; + static QPixmap * pxOff; + static QPixmap * pxObsolete; + static QPixmap * pxDanger; + static const QPixmap pageCurl(); + + TrWindow(); + ~TrWindow(); + + void openFile( const QString& name ); + +protected: + void readConfig(); + void writeConfig(); + void closeEvent( QCloseEvent * ); + +signals: + void statsChanged( int w, int c, int cs, int w2, int c2, int cs2 ); + +private slots: + void doneAndNext(); + void prev(); + void next(); + void recentFileActivated( int ); + void setupRecentFilesMenu(); + void open(); + void save(); + void saveAs(); + void release(); + void print(); + void find(); + void findAgain(); + void replace(); + void newPhraseBook(); + void openPhraseBook(); + void closePhraseBook( int id ); + void editPhraseBook( int id ); + void printPhraseBook( int id ); + void manual(); + void revertSorting(); + void about(); + void aboutQt(); + + void setupPhrase(); + bool maybeSave(); + void updateCaption(); + void showNewScope( QListViewItem *item ); + void showNewCurrent( QListViewItem *item ); + void updateTranslation( const QString& translation ); + void updateFinished( bool finished ); + void toggleFinished( QListViewItem *item, const QPoint& p, int column ); + void prevUnfinished(); + void nextUnfinished(); + void findNext( const QString& text, int where, bool matchCase ); + void revalidate(); + void toggleGuessing(); + void focusSourceList(); + void focusPhraseList(); + void updateClosePhraseBook(); + void toggleStatistics(); + void updateStatistics(); + +private: + typedef QPtrList<PhraseBook> PBL; + typedef QDict<PhraseBook> PBD; + + static QString friendlyString( const QString& str ); + + void addRecentlyOpenedFile( const QString & fn, QStringList & lst ); + void setupMenuBar(); + void setupToolBars(); + void setCurrentContextItem( QListViewItem *item ); + void setCurrentMessageItem( QListViewItem *item ); + QString friendlyPhraseBookName( int k ); + bool openPhraseBook( const QString& name ); + bool savePhraseBook( QString& name, const PhraseBook& pb ); + void updateProgress(); + void updatePhraseDict(); + PhraseBook getPhrases( const QString& source ); + bool danger( const QString& source, const QString& translation, + bool verbose = FALSE ); + + int itemToIndex( QListView * view, QListViewItem * item ); + QListViewItem * indexToItem( QListView * view, int index ); + bool searchItem( const QString & searchWhat, QListViewItem * j, + QListViewItem * k ); + void countStats( QListViewItem * ci, QListViewItem * mi, int& trW, int& trC, int& trCS ); + void doCharCounting( const QString& text, int& trW, int& trC, int& trCS ); + + QListView * plv; + QListView * lv; + QListView * slv; + MessageEditor * me; + QLabel * progress; + QLabel * modified; + MetaTranslator tor; + bool dirty; + bool messageIsShown; + int numFinished; + int numNonobsolete; + int numMessages; + int dirtyItem; + QStringList recentFiles; + QString filename; + + PBD phraseDict; + PBL phraseBooks; + QStringList phraseBookNames; + + QPrinter printer; + + FindDialog *f; + FindDialog *h; + QString findText; + int findWhere; + bool findMatchCase; + int foundItem; + QListViewItem *foundScope; + int foundWhere; + int foundOffset; + + QPopupMenu * phrasep; + QPopupMenu * closePhraseBookp; + QPopupMenu * editPhraseBookp; + QPopupMenu * printPhraseBookp; + QPopupMenu * recentFilesMenu; + int closePhraseBookId; + int editPhraseBookId; + int printPhraseBookId; + Action *openAct; + Action *saveAct; + Action *saveAsAct; + Action *releaseAct; + Action *printAct; + Action *exitAct; + Action *undoAct; + Action *redoAct; + Action *cutAct; + Action *copyAct; + Action *pasteAct; + Action *selectAllAct; + Action *findAct; + Action *findAgainAct; + Action *replaceAct; + Action *newPhraseBookAct; + Action *openPhraseBookAct; + Action *acceleratorsAct; + Action *endingPunctuationAct; + Action *phraseMatchesAct; + Action *revertSortingAct; + Action *aboutAct; + Action *aboutQtAct; + Action *manualAct; + Action *whatsThisAct; + Action *beginFromSourceAct; + Action *prevAct; + Action *nextAct; + Action *prevUnfinishedAct; + Action *nextUnfinishedAct; + Action *doneAndNextAct; + QAction *doneAndNextAlt; + Action *doGuessesAct; + Action *toggleStats; + Statistics * stats; + int srcWords; + int srcChars; + int srcCharsSpc; +}; + +#endif |