diff --git a/src/catalog/gettextheader.cpp b/src/catalog/gettextheader.cpp index 5caff03..d2da34a 100644 --- a/src/catalog/gettextheader.cpp +++ b/src/catalog/gettextheader.cpp @@ -1,739 +1,745 @@ /* **************************************************************************** This file is part of Lokalize Copyright (C) 2008-2014 by Nick Shaforostoff This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License or (at your option) version 3 or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 14 of version 3 of the license. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . **************************************************************************** */ #include "gettextheader.h" #include "project.h" #include "version.h" #include "prefs_lokalize.h" #include "prefs.h" #include #include #include #include #include #include #include #include #include #include #include #include /** * this data was obtained by running GNUPluralForms() * on all languages KDE knows of **/ struct langPInfo { const char *lang; const char *plural; }; static const langPInfo langsWithPInfo[] = { { "ar", "nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;" }, { "be@latin", "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);" }, { "be", "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);" }, { "br", "nplurals=1; plural=0;" }, { "bs", "nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;" }, { "csb", "nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)" }, { "cs", "nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;" }, { "da", "nplurals=2; plural=(n != 1);" }, { "de", "nplurals=2; plural=(n != 1);" }, { "el", "nplurals=2; plural=(n != 1);" }, { "en", "nplurals=2; plural=(n != 1);" }, { "en_GB", "nplurals=2; plural=(n != 1);" }, { "en_US", "nplurals=2; plural=(n != 1);" }, { "eo", "nplurals=2; plural=(n != 1);" }, { "es", "nplurals=2; plural=(n != 1);" }, { "et", "nplurals=2; plural=(n != 1);" }, { "fa", "nplurals=1; plural=0;" }, { "fi", "nplurals=2; plural=(n != 1);" }, { "fo", "nplurals=2; plural=(n != 1);" }, { "fr", "nplurals=2; plural=(n > 1);" }, { "ga", "nplurals=5; plural=n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n < 11 ? 3 : 4" }, { "gd", "nplurals=4; plural=(n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : (n > 2 && n < 20) ? 2 : 3;" }, { "gu", "nplurals=2; plural=(n!=1);" }, { "he", "nplurals=2; plural=(n != 1);" }, { "hi", "nplurals=2; plural=(n!=1);" }, { "hne", "nplurals=2; plural=(n!=1);" }, { "hr", "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);" }, { "hsb", "nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3;" }, { "hu", "nplurals=2; plural=(n != 1);" }, { "hy", "nplurals=4; plural=n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;" }, { "id", "nplurals=1; plural=0;" }, { "it", "nplurals=2; plural=(n != 1);" }, { "ja", "nplurals=1; plural=0;" }, { "ka", "nplurals=1; plural=0;" }, { "kk", "nplurals=1; plural=0;" }, { "km", "nplurals=1; plural=0;" }, { "ko", "nplurals=1; plural=0;" }, { "lt", "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);" }, { "lv", "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);" }, { "mai", "nplurals=2; plural=(n!=1);" }, { "mk", "nplurals=3; plural=n%10==1 ? 0 : n%10==2 ? 1 : 2;" }, { "mr", "nplurals=2; plural=(n!=1);" }, { "ms", "nplurals=2; plural=1;" }, { "nb", "nplurals=2; plural=(n != 1);" }, { "nl", "nplurals=2; plural=(n != 1);" }, { "nn", "nplurals=2; plural=(n != 1);" }, { "oc", "nplurals=2; plural=(n > 1);" }, { "or", "nplurals=2; plural=(n!=1);" }, { "pl", "nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);" }, { "pt", "nplurals=2; plural=(n != 1);" }, { "pt_BR", "nplurals=2; plural=(n > 1);" }, { "ro", "nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2;" }, { "ru", "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);" }, { "sk", "nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;" }, { "sl", "nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n%100==4 ? 3 : 0);" }, { "sr", "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);" }, { "sr@latin", "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);" }, { "sv", "nplurals=2; plural=(n != 1);" }, { "te", "nplurals=5; plural=n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : 4;" }, { "th", "nplurals=1; plural=0;" }, { "tr", "nplurals=2; plural=(n > 1);" }, { "ug", "nplurals=1; plural=0;" }, { "uk", "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);" }, { "uz", "nplurals=1; plural=0;" }, { "uz@cyrillic", "nplurals=1; plural=0;" }, { "vi", "nplurals=1; plural=0;" }, { "zh_CN", "nplurals=1; plural=0;" }, { "zh_HK", "nplurals=1; plural=0;" }, { "zh_TW", "nplurals=1; plural=0;" } }; static const size_t langsWithPInfoCount = sizeof (langsWithPInfo) / sizeof (langsWithPInfo[0]); int numberOfPluralFormsFromHeader(const QString& header) { QRegExp rxplural(QStringLiteral("Plural-Forms:\\s*nplurals=(.);")); if (rxplural.indexIn(header) == -1) return 0; bool ok; int result=rxplural.cap(1).toShort(&ok); return ok?result:0; } int numberOfPluralFormsForLangCode(const QString& langCode) { QString expr=GNUPluralForms(langCode); QRegExp rxplural(QStringLiteral("nplurals=(.);")); if (rxplural.indexIn(expr) == -1) return 0; bool ok; int result=rxplural.cap(1).toShort(&ok); return ok?result:0; } QString GNUPluralForms(const QString& lang) { QByteArray l(lang.toUtf8()); int i=langsWithPInfoCount; while(--i>=0 && l!=langsWithPInfo[i].lang) ; if (KDE_ISLIKELY( i>=0 )) return QString::fromLatin1(langsWithPInfo[i].plural); + i=langsWithPInfoCount; + while(--i>=0 && !l.startsWith(langsWithPInfo[i].lang)) + ; + if (KDE_ISLIKELY( i>=0 )) + return QString::fromLatin1(langsWithPInfo[i].plural); + //BEGIN alternative // NOTE does this work under M$ OS? qWarning()<<"gonna call msginit"; QString def=QStringLiteral("nplurals=2; plural=n != 1;"); QStringList arguments; arguments << QLatin1String("-l") << lang << QLatin1String("-i") << QLatin1String("-") << QLatin1String("-o") << QLatin1String("-") << QLatin1String("--no-translator") << QLatin1String("--no-wrap"); QProcess msginit; msginit.start(QLatin1String("msginit"), arguments); msginit.waitForStarted(5000); if (Q_UNLIKELY( msginit.state()!=QProcess::Running )) { //qWarning()<<"msginit error"; return def; } msginit.write( "# SOME DESCRIPTIVE TITLE.\n" "# Copyright (C) YEAR Free Software Foundation, Inc.\n" "# FIRST AUTHOR , YEAR.\n" "#\n" "#, fuzzy\n" "msgid \"\"\n" "msgstr \"\"\n" "\"Project-Id-Version: PACKAGE VERSION\\n\"\n" "\"POT-Creation-Date: 2002-06-25 03:23+0200\\n\"\n" "\"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n\"\n" "\"Last-Translator: FULL NAME \\n\"\n" "\"Language-Team: LANGUAGE \\n\"\n" "\"Language: LL\\n\"\n" "\"MIME-Version: 1.0\\n\"\n" "\"Content-Type: text/plain; charset=UTF-8\\n\"\n" "\"Content-Transfer-Encoding: ENCODING\\n\"\n" // "\"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\\n\"\n" ); msginit.closeWriteChannel(); if (Q_UNLIKELY( !msginit.waitForFinished(5000) )) { qWarning()<<"msginit error"; return def; } QByteArray result = msginit.readAll(); int pos = result.indexOf("Plural-Forms: "); if (Q_UNLIKELY( pos==-1 )) { //qWarning()<<"msginit error"<'); temp=QStringLiteral("Last-Translator: ") % authorNameEmail % BACKSLASH_N; QRegExp lt(QStringLiteral("^ *Last-Translator:.*")); for ( it = headerList.begin(),found=false; it != headerList.end() && !found; ++it ) { if (it->contains(lt)) { if (forSaving) *it = temp; found=true; } } if (Q_UNLIKELY( !found )) headerList.append(temp); QLocale cLocale(QLocale::C); QString dateTimeString = cLocale.toString(QDateTime::currentDateTime(), QStringLiteral("yyyy-MM-dd hh:mm")); QString zoneOffsetString1 = QTimeZone(QTimeZone::systemTimeZoneId()).displayName(QTimeZone::GenericTime, QTimeZone::OffsetName); int zpos=qMax(qMax(0, zoneOffsetString1.indexOf('+')), zoneOffsetString1.indexOf('-')); QString zoneOffsetString = QString::fromRawData(zoneOffsetString1.unicode()+zpos, zoneOffsetString1.length()-zpos); temp=QStringLiteral("PO-Revision-Date: ") % dateTimeString % zoneOffsetString.remove(':') % BACKSLASH_N; QRegExp poRevDate(QStringLiteral("^ *PO-Revision-Date:.*")); for ( it = headerList.begin(),found=false; it != headerList.end() && !found; ++it ) { found=it->contains(poRevDate); if (found && forSaving) *it = temp; } if (Q_UNLIKELY( !found )) headerList.append(temp); temp=QStringLiteral("Project-Id-Version: ") % CatalogProjectId % BACKSLASH_N; //temp.replace( "@PACKAGE@", packageName()); QRegExp projectIdVer(QStringLiteral("^ *Project-Id-Version:.*")); for ( it = headerList.begin(),found=false; it != headerList.end() && !found; ++it ) { found=it->contains(projectIdVer); if (found && it->contains(QLatin1String("PACKAGE VERSION"))) *it = temp; } if (Q_UNLIKELY( !found )) headerList.append(temp); - + langCode=Project::instance()->isLoaded()? Project::instance()->langCode(): Settings::defaultLangCode(); QString language; //initialized with preexisting value or later QString mailingList; //initialized with preexisting value or later static QMap langEnums; if (!langEnums.size()) for (int l=QLocale::Abkhazian; l<=QLocale::Akoose; ++l) langEnums[QLocale::languageToString((QLocale::Language)l)]=(QLocale::Language)l; static QRegExp langTeamRegExp(QStringLiteral("^ *Language-Team:.*")); for ( it = headerList.begin(),found=false; it != headerList.end() && !found; ++it ) { found=it->contains(langTeamRegExp); if (found) { //really parse header QRegExp re(QStringLiteral("^ *Language-Team: *(.*) *<([^>]*)>")); if (re.indexIn(*it) != -1 ) { if (langEnums.contains( re.cap(1).trimmed() )) { language=re.cap(1).trimmed(); mailingList=re.cap(2).trimmed(); QList locales = QLocale::matchingLocales(langEnums.value(language), QLocale::AnyScript, QLocale::AnyCountry); if (locales.size()) langCode=locales.first().name().left(2); } } ait=it; } } if (language.isEmpty()) { language=QLocale::languageToString(QLocale(langCode).language()); if (language.isEmpty()) language=langCode; } if (mailingList.isEmpty() || belongsToProject) { if (Project::instance()->isLoaded()) mailingList=Project::instance()->mailingList(); else //if (mailingList.isEmpty()) mailingList=Settings::defaultMailingList(); } temp=QStringLiteral("Language-Team: ")%language%QStringLiteral(" <")%mailingList%QStringLiteral(">\\n"); if (KDE_ISLIKELY( found )) (*ait) = temp; else headerList.append(temp); static QRegExp langCodeRegExp(QStringLiteral("^ *Language: *([^ \\\\]*)")); temp=QStringLiteral("Language: ") % langCode % BACKSLASH_N; for ( it = headerList.begin(),found=false; it != headerList.end() && !found; ++it ) { found=(langCodeRegExp.indexIn(*it)!=-1); if (found && langCodeRegExp.cap(1).isEmpty()) *it=temp; //if (found) qWarning()<<"got explicit lang code:"<contains(ctRe); if (found) *it=temp; } if (Q_UNLIKELY( !found )) headerList.append(temp); temp=QStringLiteral("Content-Transfer-Encoding: 8bit\\n"); QRegExp cteRe(QStringLiteral("^ *Content-Transfer-Encoding:.*")); for ( it = headerList.begin(),found=false; it != headerList.end() && !found; ++it ) found=it->contains(cteRe); if (!found) headerList.append(temp); // ensure MIME-Version header temp=QStringLiteral("MIME-Version: 1.0\\n"); QRegExp mvRe(QStringLiteral("^ *MIME-Version:")); for ( it = headerList.begin(),found=false; it != headerList.end()&& !found; ++it ) { found=it->contains(mvRe); if (found) *it = temp; } if (Q_UNLIKELY( !found )) headerList.append(temp); //qDebug()<<"testing for GNUPluralForms"; // update plural form header QRegExp pfRe(QStringLiteral("^ *Plural-Forms:")); for ( it = headerList.begin(),found=false; it != headerList.end()&& !found; ++it ) found=it->contains(pfRe); if (found) { --it; //qDebug()<<"GNUPluralForms found"; int num=numberOfPluralFormsFromHeader(header); if (!num) { if (generatedFromDocbook) num=1; else { qWarning()<<"No plural form info in header, using project-defined one"<replace(pf,temp); num=numberOfPluralFormsFromHeader(temp); } else { qWarning()<<"no... smth went wrong :(\ncheck your gettext install"; num=2; } } } numberOfPluralForms=num; } else if ( !generatedFromDocbook) { //qDebug()<<"generating GNUPluralForms"<contains(xgRe); if (found) *it = temp; } if (Q_UNLIKELY( !found )) headerList.append(temp); //m_header.setMsgstr( headerList.join( "\n" ) ); header=headerList.join(QStringLiteral("\n")); //END header itself //BEGIN comment = description, copyrights // U+00A9 is the Copyright sign QRegExp fsfc(QStringLiteral("^# *Copyright (\\(C\\)|\\x00a9).*Free Software Foundation, Inc")); for ( it = commentList.begin(),found=false; it != commentList.end()&&!found; ++it ) { found=it->contains( fsfc ) ; if (found) it->replace(QStringLiteral("YEAR"), cLocale.toString(QDate::currentDate(), QStringLiteral("yyyy"))); } /* if( saveOptions.FSFCopyright == ProjectSettingsBase::Update ) { //update years QString cy = cLocale.toString(QDate::currentDate(), "yyyy"); if( !it->contains( QRegExp(cy)) ) // is the year already included? { int index = it->lastIndexOf( QRegExp("[\\d]+[\\d\\-, ]*") ); if( index == -1 ) { KMessageBox::information(0,i18n("Free Software Foundation Copyright does not contain any year. " "It will not be updated.")); } else { it->insert(index+1, QString(", ")+cy); } } }*/ #if 0 if ( ( !usePrefs || saveOptions.updateDescription ) && ( !saveOptions.descriptionString.isEmpty() ) ) { temp = "# "+saveOptions.descriptionString; temp.replace( "@PACKAGE@", packageName()); temp.replace( "@LANGUAGE@", identityOptions.languageName); temp = temp.trimmed(); // The description strings has often buggy variants already in the file, these must be removed QString regexpstr = "^#\\s+" + QRegExp::escape( saveOptions.descriptionString.trimmed() ) + "\\s*$"; regexpstr.replace( "@PACKAGE@", ".*" ); regexpstr.replace( "@LANGUAGE@", ".*" ); //qDebug() << "REGEXPSTR: " << regexpstr; QRegExp regexp ( regexpstr ); // The buggy variants exist in English too (of a time before KBabel got a translation for the corresponding language) QRegExp regexpUntranslated ( "^#\\s+translation of .* to .*\\s*$" ); qDebug () << "Temp is '" << temp << "'"; found=false; bool foundTemplate=false; it = commentList.begin(); while ( it != commentList.end() ) { qDebug () << "testing '" << (*it) << "'"; bool deleteItem = false; if ( (*it) == temp ) { qDebug () << "Match "; if ( found ) deleteItem = true; else found=true; } else if ( regexp.indexIn( *it ) >= 0 ) { // We have a similar (translated) string (from another project or another language (perhaps typos)). Remove it. deleteItem = true; } else if ( regexpUntranslated.indexIn( *it ) >= 0 ) { // We have a similar (untranslated) string (from another project or another language (perhaps typos)). Remove it. deleteItem = true; } else if ( (*it) == "# SOME DESCRIPTIVE TITLE." ) { // We have the standard title placeholder, remove it deleteItem = true; } if ( deleteItem ) it = commentList.erase( it ); else ++it; } if (!found) commentList.prepend(temp); } #endif // qDebug() << "HEADER COMMENT: " << commentList; /* if ( (!usePrefs || saveOptions.updateTranslatorCopyright) && ( ! identityOptions->readEntry("authorName","").isEmpty() ) && ( ! identityOptions->readEntry("Email","").isEmpty() ) ) // An email address can be used as ersatz of a name {*/ // return; QStringList foundAuthors; temp=QStringLiteral("# ")%authorNameEmail%QStringLiteral(", ")%cLocale.toString(QDate::currentDate(), QStringLiteral("yyyy"))%'.'; // ### TODO: it would be nice if the entry could start with "COPYRIGHT" and have the "(C)" symbol (both not mandatory) QRegExp regexpAuthorYear( QStringLiteral("^#.*(<.+@.+>)?,\\s*([\\d]+[\\d\\-, ]*|YEAR)") ); QRegExp regexpYearAlone( QStringLiteral("^# , \\d{4}.?\\s*$") ); if (commentList.isEmpty()) { commentList.append(temp); commentList.append(QString()); } else { it = commentList.begin(); while ( it != commentList.end() ) { bool deleteItem = false; if ( it->indexOf( QLatin1String("copyright"), 0, Qt::CaseInsensitive ) != -1 ) { // We have a line with a copyright. It should not be moved. } else if ( it->contains( QRegExp(QStringLiteral("#, *fuzzy")) ) ) deleteItem = true; else if ( it->contains( regexpYearAlone ) ) { // We have found a year number that is preceded by a comma. // That is typical of KBabel 1.10 (and earlier?) when there is neither an author name nor an email // Remove the entry deleteItem = true; } else if ( it->contains( QLatin1String("# FIRST AUTHOR , YEAR.")) ) deleteItem = true; else if ( it->contains( QLatin1String("# SOME DESCRIPTIVE TITLE"))) deleteItem = true; else if ( it->contains( regexpAuthorYear ) ) // email address followed by year { if ( !foundAuthors.contains( (*it) ) ) { // The author line is new (and not a duplicate), so add it to the author line list foundAuthors.append( (*it) ); } // Delete also non-duplicated entry, as now all what is needed will be processed in foundAuthors deleteItem = true; } if ( deleteItem ) it = commentList.erase( it ); else ++it; } if ( !foundAuthors.isEmpty() ) { found = false; bool foundAuthor = false; const QString cy = cLocale.toString(QDate::currentDate(), QStringLiteral("yyyy")); ait = foundAuthors.end(); for ( it = foundAuthors.begin() ; it!=foundAuthors.end(); ++it ) { if ( it->contains(Settings::authorName()) || it->contains(Settings::authorEmail()) ) { foundAuthor = true; if ( it->contains( cy ) ) found = true; else ait = it; } } if ( !found ) { if ( !foundAuthor ) foundAuthors.append(temp); else if ( ait != foundAuthors.end() ) { //update years const int index = (*ait).lastIndexOf( QRegExp(QStringLiteral("[\\d]+[\\d\\-, ]*")) ); if ( index == -1 ) (*ait)+=QStringLiteral(", ")%cy; else ait->insert(index+1, QStringLiteral(", ")%cy); } else qDebug() << "INTERNAL ERROR: author found but iterator dangling!"; } } else foundAuthors.append(temp); foreach (QString author, foundAuthors) { // ensure dot at the end of copyright if ( !author.endsWith(QLatin1Char('.')) ) author += QLatin1Char('.'); commentList.append(author); } } //m_header.setComment( commentList.join( "\n" ) ); comment=commentList.join(QStringLiteral("\n")); //END comment = description, copyrights } QString fullUserName();// defined in helpers.cpp bool askAuthorInfoIfEmpty() { if(QThread::currentThread() == qApp->thread()) { if (Settings::authorName().isEmpty()) { bool ok; QString contact = QInputDialog::getText( SettingsController::instance()->mainWindowPtr(), i18nc("@window:title", "Author name missing"), i18n("Your name:"), QLineEdit::Normal, fullUserName(), &ok); #ifndef NOKDE Settings::self()->authorNameItem()->setValue(ok?contact:fullUserName()); Settings::self()->save(); #else Settings::self()->setAuthorName(ok?contact:fullUserName()); #endif } if (Settings::authorEmail().isEmpty()) { bool ok; QString email = QInputDialog::getText( SettingsController::instance()->mainWindowPtr(), i18nc("@window:title", "Author email missing"), i18n("Your email:"), QLineEdit::Normal, QString(), &ok); if (ok) { #ifndef NOKDE Settings::self()->authorEmailItem()->setValue(email); Settings::self()->save(); #else Settings::self()->setAuthorEmail(email); #endif } } } return !Settings::authorName().isEmpty() && !Settings::authorEmail().isEmpty(); } diff --git a/src/lokalize.pro b/src/lokalize.pro index 1018a15..b0b4efa 100644 --- a/src/lokalize.pro +++ b/src/lokalize.pro @@ -1,184 +1,185 @@ #------------------------------------------------- # # Project created by QtCreator 2012-06-06T01:26:21 # #------------------------------------------------- QT += core widgets xml sql TARGET = lokalize mac: TARGET = Lokalize win32: TARGET = Lokalize TEMPLATE = app SOURCES += main.cpp\ ## lokalizemainwindow.cpp actionproxy.cpp\ editortab.cpp\ # editortab_findreplace.cpp editorview.cpp\ xlifftextedit.cpp\ syntaxhighlighter.cpp\ completionstorage.cpp\ phaseswindow.cpp\ noteeditor.cpp\ msgctxtview.cpp\ binunitsview.cpp\ cataloglistview/cataloglistview.cpp\ cataloglistview/catalogmodel.cpp\ common/headerviewmenu.cpp\ common/domroutines.cpp\ common/fastsizehintitemdelegate.cpp\ common/flowlayout.cpp\ common/termlabel.cpp\ common/languagelistmodel.cpp\ common/stemming.cpp\ common/htmlhelpers.cpp\ glossary/glossaryview.cpp\ glossary/glossary.cpp\ glossary/glossarywindow.cpp\ mergemode/mergecatalog.cpp\ mergemode/mergeview.cpp\ alttransview.cpp\ common/diff.cpp\ project/project.cpp\ # project/projectmodel.cpp # project/projectwidget.cpp # project/projecttab.cpp # project/poextractor.cpp ## prefs/prefs.cpp # webquery/webqueryview.cpp # webquery/webquerycontroller.cpp # webquery/myactioncollectionview.cpp # tools/widgettextcaptureconfig.cpp filesearch/filesearchtab.cpp\ tm/tmview.cpp\ tm/tmscanapi.cpp\ tm/jobs.cpp\ tm/dbfilesmodel.cpp\ tm/tmmanager.cpp\ tm/tmtab.cpp\ tm/qaview.cpp\ tm/qamodel.cpp\ catalog/phase.cpp\ catalog/cmd.cpp\ catalog/pos.cpp\ catalog/catalog.cpp\ catalog/catalogstring.cpp\ catalog/gettextheader.cpp\ catalog/gettext/gettextstorage.cpp\ catalog/gettext/catalogitem.cpp\ catalog/gettext/importplugin.cpp\ catalog/gettext/gettextimport.cpp\ catalog/gettext/gettextexport.cpp\ catalog/xliff/xliffstorage.cpp\ catalog/ts/tsstorage.cpp\ nokde-stubs/prefs.cpp\ nokde-stubs/lokalizesubwindowbase.cpp\ nokde-stubs/welcometab.cpp mac: CONFIG += objective_c mac: OBJECTIVE_SOURCES += common/machelpers.mm win32: SOURCES += common/winhelpers.cpp unix:!mac: SOURCES += common/unixhelpers.cpp HEADERS += editortab.h\ editorview.h\ xlifftextedit.h\ syntaxhighlighter.h\ ## completionstorage.h\ phaseswindow.h\ noteeditor.h\ msgctxtview.h\ binunitsview.h\ cataloglistview/cataloglistview.h\ cataloglistview/catalogmodel.h\ common/headerviewmenu.h\ common/fastsizehintitemdelegate.h\ common/flowlayout.h\ common/termlabel.h\ common/languagelistmodel.h\ common/stemming.h\ glossary/glossaryview.h\ glossary/glossary.h\ glossary/glossarywindow.h\ mergemode/mergecatalog.h\ mergemode/mergeview.h\ alttransview.h\ project/project.h\ # project/projectmodel.h # project/projectwidget.h # project/projecttab.h # project/poextractor.h ## prefs/prefs.h # webquery/webqueryview.h # webquery/webquerycontroller.h # webquery/myactioncollectionview.h # tools/widgettextcaptureconfig.h filesearch/filesearchtab.h\ tm/tmview.h\ ## tm/tmscanapi.h\ tm/jobs.h\ tm/dbfilesmodel.h\ tm/tmmanager.h\ tm/tmtab.h\ tm/qaview.h\ tm/qamodel.h\ catalog/phase.h\ catalog/cmd.h\ catalog/pos.h\ catalog/catalog.h\ catalog/catalogstring.h\ nokde-stubs/prefs.h\ nokde-stubs/prefs_lokalize.h\ nokde-stubs/projectbase.h\ nokde-stubs/projectlocal.h\ nokde-stubs/kaboutdata.h\ nokde-stubs/welcometab.h FORMS += glossary/termedit.ui\ tm/queryoptions.ui\ tm/managedatabases.ui\ tm/dbparams.ui\ filesearch/filesearchoptions.ui\ filesearch/massreplaceoptions.ui\ nokde-stubs/welcomewidget.ui INCLUDEPATH += catalog catalog/gettext catalog/xliff catalog/ts cataloglistview mergemode glossary tm filesearch project common nokde-stubs filesearch DEFINES += NOKDE #unix: LIBS += -lhunspell CONFIG += exceptions_off c++11 stl_off mac: QMAKE_LFLAGS += -dead_strip mac: ICON = ../icons/osx/Lokalize.icns mac: QMAKE_INFO_PLIST = ../icons/osx/Info.plist mac: QMAKE_POST_LINK += cp -n ../icons/osx/LokalizePo*.icns ../icons/osx/LokalizeXliff.icns Lokalize.app/Contents/Resources/ #remove this block to get a simpler build sonnet_static { DEFINES += SONNET_STATIC SONNETCORE_EXPORT="" SONNETUI_EXPORT="" INCLUDEPATH += ../../sonnet/src/core INCLUDEPATH += ../../sonnet/src/ui win32:LIBS += -L../../sonnet/src/core/release -lsonnet-core win32:LIBS += -L../../sonnet/src/ui/release -lsonnet-ui win32:LIBS += -L../../sonnet/src/plugins/hunspell/release -lsonnet-hunspell mac:LIBS += -L../../sonnet/src/core -lsonnet-core mac:LIBS += -L../../sonnet/src/ui -lsonnet-ui mac:LIBS += -L../../sonnet/src/plugins/hunspell -lsonnet-hunspell mac:LIBS += -L../../sonnet/src/plugins/nsspellchecker -lsonnet-nsspellchecker DEFINES += HAVE_HUNSPELL #win32: DEFINES += HUNSPELL_STATIC + INCLUDEPATH += ../../hunspell/src/hunspell INCLUDEPATH += ../../hunspell/src mac:LIBS += -L../../hunspell/src/hunspell/.libs/ -lhunspell-1.2 win32:LIBS += -L../../hunspell/src/win_api/x64/Release_dll -llibhunspell win32:system("copy ..\\..\\hunspell\\src\\win_api\\x64\\Release_dll\\libhunspell.dll release") } diff --git a/src/nokde-stubs/prefs.cpp b/src/nokde-stubs/prefs.cpp index 039501a..9c1cadd 100644 --- a/src/nokde-stubs/prefs.cpp +++ b/src/nokde-stubs/prefs.cpp @@ -1,372 +1,375 @@ #include "prefs.h" #include "prefs_lokalize.h" #include "projectbase.h" #include "projectlocal.h" #include "project.h" #include "tmtab.h" #include "filesearchtab.h" #include "kaboutdata.h" #include #include #include #include #include #include #include SettingsController* SettingsController::_instance=0; void SettingsController::cleanupSettingsController() { delete SettingsController::_instance; SettingsController::_instance = 0; } SettingsController* SettingsController::instance() { if (_instance==0){ _instance=new SettingsController; ///qAddPostRoutine(SettingsController::cleanupSettingsController); } return _instance; } bool SettingsController::ensureProjectIsLoaded() { Project::instance()->populateGlossary(); return true; } QString fullUserName();// defined in helpers.cpp Settings::Settings() - : mDefaultLangCode(QLocale::system().name()) - , mAddColor(0x99,0xCC,0xFF) + : mAddColor(0x99,0xCC,0xFF) , mDelColor(0xFF,0x99,0x99) , mMsgFont() , mHighlightSpaces(true) , mLeds(false) // Editor , mAutoApprove(true) , mAutoSpellcheck(true) , mMouseWheelGo(false) , mAltTransViewEverShownWithData(false) // TM , mPrefetchTM(false) , mAutoaddTM(true) , mScanToTMOnOpen(false) , mWordCompletionLength(3) , mSuggCount(10) { QSettings s; mAuthorName = s.value(QStringLiteral("Author/Name"), QString()).toString(); if (mAuthorName.isEmpty()) {mAuthorName = fullUserName(); if (mAuthorName.length()) mAuthorName[0]=mAuthorName.at(0).toUpper();} mAuthorEmail = s.value(QStringLiteral("Author/Email"), QString()).toString(); + mDefaultLangCode = s.value(QStringLiteral("Editor/TargetLangCode"), QLocale::system().name()).toString(); + mAltTransViewEverShownWithData = s.value(QStringLiteral("Editor/AltTransViewEverShownWithData"),false).toBool(); } void Settings::save() { QSettings s; s.setValue(QStringLiteral("Author/Name"), mAuthorName); s.setValue(QStringLiteral("Author/Email"), mAuthorEmail); + s.setValue(QStringLiteral("Editor/TargetLangCode"), mDefaultLangCode); + s.setValue(QStringLiteral("Editor/AltTransViewEverShownWithData"), mAltTransViewEverShownWithData); } Settings *Settings::self() { static Settings* s=new Settings; return s; } void writeUiState(const char* elementName, const QByteArray& state) { QSettings s; s.setValue(QStringLiteral("UI/")+QLatin1String(elementName), state.toBase64()); } QByteArray readUiState(const char* elementName) { QSettings s; return QByteArray::fromBase64( s.value(QStringLiteral("UI/")+QLatin1String(elementName), QByteArray()).toByteArray() ); } #include "editortab.h" ProjectBase::ProjectBase() : m_tmTab(0) , mProjectID(QStringLiteral("default")) , mKind() , mTargetLangCode(Settings::defaultLangCode()) , mSourceLangCode("en_US") , mPoBaseDir(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)) , mPotBaseDir() , mBranchDir() , mAltDir() , mGlossaryTbx(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)+"/terms.tbx") , mMainQA(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)+"/main.lqa") // RegExps , mAccel("&") , mMarkup("(<[^>]+>)+|(&[A-Za-z_:][A-Za-z0-9_\\.:-]*;)+") , mWordWrap(80) { QSettings s; mSourceLangCode = s.value(QStringLiteral("Project/SourceLangCode"), mSourceLangCode).toString(); mTargetLangCode = s.value(QStringLiteral("Project/TargetLangCode"), mTargetLangCode).toString(); } void ProjectBase::save() { QSettings s; s.setValue(QStringLiteral("Project/SourceLangCode"), mSourceLangCode); s.setValue(QStringLiteral("Project/TargetLangCode"), mTargetLangCode); } ProjectLocal::ProjectLocal() : mRole(Translator) , mFirstRun(true) { QSettings s; mRole = s.value("Project/AuthorRole", mRole).toInt(); mSourceDir = s.value("Project/SourceDir", mSourceDir).toString(); } void ProjectLocal::save() { QSettings s; s.setValue(QStringLiteral("Project/AuthorRole"), mRole); s.setValue(QStringLiteral("Project/SourceDir"), mSourceDir); } EditorTab* ProjectBase::fileOpen(QString filePath, int entry, bool setAsActive, const QString& mergeFile, bool silent) { if (filePath.length()) { FileToEditor::const_iterator it=m_fileToEditor.constFind(filePath); if (it!=m_fileToEditor.constEnd()) { qWarning()<<"already opened:"<activateWindow(); return e; } } } QByteArray state=m_lastEditorState; EditorTab* w=new EditorTab(0); QString suggestedDirPath; if (EditorTab* e=qobject_cast(QApplication::activeWindow())) { QString fp=e->currentFilePath(); if (fp.length()) suggestedDirPath=QFileInfo(fp).absolutePath(); } if (!w->fileOpen(filePath,suggestedDirPath,silent)) { w->deleteLater(); return 0; } if (filePath.length()) { FileToEditor::const_iterator it=m_fileToEditor.constFind(filePath); if (it!=m_fileToEditor.constEnd()) { qWarning()<<"already opened:"<activateWindow(); w->deleteLater(); return e; } } } w->show(); if (!state.isEmpty()) w->restoreState(QByteArray::fromBase64(state)); if (entry/* || offset*/) w->gotoEntry(DocPosition(entry/*, DocPosition::Target, 0, offset*/)); if (!mergeFile.isEmpty()) w->mergeOpen(mergeFile); // m_openRecentFileAction->addUrl(QUrl::fromLocalFile(filePath));//(w->currentUrl()); connect(w, SIGNAL(destroyed(QObject*)),this,SLOT(editorClosed(QObject*))); connect(w, SIGNAL(fileOpenRequested(QString,QString,QString)),this,SLOT(fileOpen(QString,QString,QString))); connect(w, SIGNAL(tmLookupRequested(QString,QString)),this,SLOT(lookupInTranslationMemory(QString,QString))); filePath=w->currentFilePath(); QStringRef fnSlashed=filePath.midRef(filePath.lastIndexOf('/')); FileToEditor::const_iterator i = m_fileToEditor.constBegin(); while (i != m_fileToEditor.constEnd()) { if (i.key().endsWith(fnSlashed)) { i.value()->setFullPathShown(true); w->setFullPathShown(true); } ++i; } m_fileToEditor.insert(filePath,w); //emit editorAdded(); return w; } EditorTab* ProjectBase::fileOpen(const QString& filePath, const QString& source, const QString& ctxt) { EditorTab* w=fileOpen(filePath, 0, true); if (!w) return 0;//TODO message w->findEntryBySourceContext(source,ctxt); return w; } EditorTab* ProjectBase::fileOpen(const QString& filePath, DocPosition docPos, int selection) { EditorTab* w=fileOpen(filePath, 0, true); if (!w) return 0;//TODO message w->gotoEntry(docPos, selection); return w; } void ProjectBase::editorClosed(QObject* obj) { m_fileToEditor.remove(m_fileToEditor.key(static_cast(obj))); } bool ProjectBase::eventFilter(QObject *obj, QEvent *event) { if (event->type() == QEvent::FileOpen) { QFileOpenEvent *e = static_cast(event); fileOpen(e->file()); return true; } return QObject::eventFilter(obj, event); } void ProjectBase::lookupInTranslationMemory(const QString& source, const QString& target) { TM::TMTab* w=showTM(); w->lookup(source, target); } TM::TMTab* ProjectBase::showTM() { if (!m_tmTab) { m_tmTab=new TM::TMTab(0); connect(m_tmTab, SIGNAL(fileOpenRequested(QString,QString,QString)),this,SLOT(fileOpen(QString,QString,QString))); } m_tmTab->show(); m_tmTab->activateWindow(); return m_tmTab; } void ProjectBase::showFileSearch() { if (!m_fileSearchTab) { m_fileSearchTab=new FileSearchTab(0); connect(m_fileSearchTab, SIGNAL(fileOpenRequested(QString,DocPosition,int)),this,SLOT(fileOpen(QString,DocPosition,int))); connect(m_fileSearchTab, SIGNAL(fileOpenRequested(QString)),this,SLOT(fileOpen(QString))); } if (EditorTab* e=qobject_cast(QApplication::activeWindow())) { QString fp=e->currentFilePath(); if (fp.length()) { m_fileSearchTab->addFilesToSearch(QStringList(fp)); m_fileSearchTab->setSourceQuery(e->selectionInSource()); m_fileSearchTab->setTargetQuery(e->selectionInTarget()); } } m_fileSearchTab->show(); m_fileSearchTab->activateWindow(); } void ProjectBase::fileSearchNext() { if (!m_fileSearchTab) showFileSearch(); else m_fileSearchTab->fileSearchNext(); } KAboutData* KAboutData::instance=0; KAboutData::KAboutData(const QString&, const QString& n, const QString& v, const QString& d, KAboutLicense::L, const QString& c) : name(n) , version(v) , description(d) , copyright(c) { KAboutData::instance=this; } void KAboutData::addAuthor(const QString& name, const QString&, const QString& mail) { // Credit c; // c.name=name; // c.mail=mail; // credits.append(c); } void KAboutData::addCredit(const QString& name, const QString& forwhat, const QString& mail, const QString& site) { Credit c; c.name=name; c.mail=mail; c.what=forwhat; c.site=site; credits.append(c); } void KAboutData::doAbout() { QString cs; foreach(const Credit& c, credits) { cs+=c.name%": "%c.what%"
"; } QMessageBox::about(0, name, "

"%name%' '%version%"

"%description%"

"%copyright.replace('\n', "
")%"


Credits:
"%cs%"
"); } namespace KLocalizedString { void setApplicationDomain(const char*){} }; diff --git a/src/nokde-stubs/prefs_lokalize.h b/src/nokde-stubs/prefs_lokalize.h index f5366b4..45e29c7 100644 --- a/src/nokde-stubs/prefs_lokalize.h +++ b/src/nokde-stubs/prefs_lokalize.h @@ -1,178 +1,179 @@ // This file is generated by kconfig_compiler_kf5 from lokalize.kcfg. #ifndef SETTINGS_H #define SETTINGS_H #include #include #include #include class Settings: public QObject { Q_OBJECT public: static Settings *self(); ~Settings(){} void save(); public slots: static void setAuthorName(const QString& v){self()->mAuthorName = v;} static void setAuthorEmail(const QString& v){self()->mAuthorEmail = v;} + static void setDefaultLangCode(const QString& v){self()->mDefaultLangCode = v;} public: static QString authorName() {return self()->mAuthorName;} static QString authorLocalizedName() {return self()->mAuthorLocalizedName;} static QString authorEmail() {return self()->mAuthorEmail;} static QString defaultLangCode() { return self()->mDefaultLangCode; } static QString defaultMailingList() { return self()->mDefaultMailingList; } static QColor addColor() { return self()->mAddColor; } static QColor delColor() { return self()->mDelColor; } static bool highlightSpaces() { return self()->mHighlightSpaces; } static QFont msgFont() { return self()->mMsgFont; } static void setLeds( bool v ) { self()->mLeds = v; } static bool leds() { return self()->mLeds; } static bool autoApprove() { return self()->mAutoApprove; } static void setAutoSpellcheck( bool v ) { self()->mAutoSpellcheck = v; } static bool autoSpellcheck() { return self()->mAutoSpellcheck; } static bool mouseWheelGo() { return self()->mMouseWheelGo; } static bool altTransViewEverShownWithData() { return self()->mAltTransViewEverShownWithData; } static void setAltTransViewEverShownWithData( bool v ) { self()->mAltTransViewEverShownWithData = v; } static int wordCompletionLength() { return self()->mWordCompletionLength; } static bool prefetchTM() { return self()->mPrefetchTM; } static int suggCount() { return self()->mSuggCount; } static bool autoaddTM() { return self()->mAutoaddTM; } static bool scanToTMOnOpen() { return self()->mScanToTMOnOpen; } protected: Settings(); friend class SettingsHelper; // Identity QString mAuthorName; QString mAuthorLocalizedName; QString mAuthorEmail; QString mDefaultLangCode; QString mDefaultMailingList; // Appearance QColor mAddColor; QColor mDelColor; QFont mMsgFont; bool mHighlightSpaces; bool mLeds; // Editor bool mAutoApprove; bool mAutoSpellcheck; bool mMouseWheelGo; bool mAltTransViewEverShownWithData; // TM bool mPrefetchTM; bool mAutoaddTM; bool mScanToTMOnOpen; int mWordCompletionLength; int mSuggCount; }; #endif diff --git a/src/nokde-stubs/welcometab.cpp b/src/nokde-stubs/welcometab.cpp index 07a8513..f77e076 100644 --- a/src/nokde-stubs/welcometab.cpp +++ b/src/nokde-stubs/welcometab.cpp @@ -1,98 +1,99 @@ /* **************************************************************************** This file is part of Lokalize Copyright (C) 2014 by Nick Shaforostoff This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License or (at your option) version 3 or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 14 of version 3 of the license. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . **************************************************************************** */ #include "welcometab.h" #include "prefs_lokalize.h" #include "languagelistmodel.h" #include "tmscanapi.h" #include "project.h" #include "catalog.h" #include #include #include #include WelcomeTab::WelcomeTab(QWidget *parent) : LokalizeSubwindowBase2(parent) { #ifndef Q_OS_DARWIN menuBar()->hide(); #endif setWindowTitle("Lokalize"/*i18nc("@title:window","Lokalize")*/);//setCaption(i18nc("@title:window","Project"),false); setAcceptDrops(true); setCentralWidget(new QWidget(this)); setupUi(centralWidget()); QStringList i; i<addItems(i); roleCombo->setCurrentIndex(Project::instance()->local()->role()); connect(roleCombo, SIGNAL(currentIndexChanged(int)), Project::instance()->local(), SLOT(setRole(int))); sourceLangCombo->setModel(LanguageListModel::instance()->sortModel()); targetLangCombo->setModel(LanguageListModel::instance()->sortModel()); sourceLangCombo->setCurrentIndex(LanguageListModel::instance()->sortModelRowForLangCode( Project::instance()->sourceLangCode() )); targetLangCombo->setCurrentIndex(LanguageListModel::instance()->sortModelRowForLangCode( Project::instance()->targetLangCode() )); LangCodeSaver* s = new LangCodeSaver(this); LangCodeSaver* t = new LangCodeSaver(this); connect(sourceLangCombo, SIGNAL(currentIndexChanged(int)), s, SLOT(setLangCode(int))); connect(targetLangCombo, SIGNAL(currentIndexChanged(int)), t, SLOT(setLangCode(int))); connect(s, SIGNAL(langCodeSelected(QString)), Project::instance(), SLOT(setSourceLangCode(QString))); connect(t, SIGNAL(langCodeSelected(QString)), Project::instance(), SLOT(setTargetLangCode(QString))); + connect(t, SIGNAL(langCodeSelected(QString)), Settings::self(), SLOT(setDefaultLangCode(QString))); authorNameEdit->setText(Settings::self()->authorName()); connect(authorNameEdit, SIGNAL(textChanged(QString)), Settings::self(), SLOT(setAuthorName(QString))); glossaryPathEdit->setText(Project::instance()->glossaryPath()); } WelcomeTab::~WelcomeTab() { } void LangCodeSaver::setLangCode(int index) { emit langCodeSelected(LanguageListModel::instance()->langCodeForSortModelRow(index)); } void WelcomeTab::dragEnterEvent(QDragEnterEvent* event) { if(dragIsAcceptable(event->mimeData()->urls())) event->acceptProposedAction(); } void WelcomeTab::dropEvent(QDropEvent* event) { foreach(const QUrl& url, event->mimeData()->urls()) { const QString& filePath=url.toLocalFile(); if (Catalog::extIsSupported(filePath) && Project::instance()->fileOpen(filePath)) { event->acceptProposedAction(); } } }