diff --git a/src/alttransview.cpp b/src/alttransview.cpp index 61c900f..ddb1d43 100644 --- a/src/alttransview.cpp +++ b/src/alttransview.cpp @@ -1,310 +1,310 @@ /* **************************************************************************** This file is part of Lokalize Copyright (C) 2007-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 "alttransview.h" #include "lokalize_debug.h" #include "diff.h" #include "catalog.h" #include "cmd.h" #include "project.h" #include "xlifftextedit.h" #include "tmview.h" //TextBrowser #include "mergecatalog.h" #include "prefs_lokalize.h" #include #include #include #include #include #include #include #include -#include -#include +#include +#include AltTransView::AltTransView(QWidget* parent, Catalog* catalog, const QVector& actions) : QDockWidget(i18nc("@title:window", "Alternate Translations"), parent) , m_browser(new TM::TextBrowser(this)) , m_catalog(catalog) , m_normTitle(i18nc("@title:window", "Alternate Translations")) , m_hasInfoTitle(m_normTitle + QStringLiteral(" [*]")) , m_hasInfo(false) , m_everShown(false) , m_actions(actions) { setObjectName(QStringLiteral("msgIdDiff")); setWidget(m_browser); hide(); m_browser->setReadOnly(true); m_browser->viewport()->setBackgroundRole(QPalette::Background); QTimer::singleShot(0, this, &AltTransView::initLater); } void AltTransView::initLater() { setAcceptDrops(true); KConfig config; KConfigGroup group(&config, "AltTransView"); m_everShown = group.readEntry("EverShown", false); QSignalMapper* signalMapper = new QSignalMapper(this); int i = m_actions.size(); while (--i >= 0) { connect(m_actions.at(i), &QAction::triggered, signalMapper, QOverload<>::of(&QSignalMapper::map)); signalMapper->setMapping(m_actions.at(i), i); } connect(signalMapper, QOverload::of(&QSignalMapper::mapped), this, &AltTransView::slotUseSuggestion); connect(m_browser, &TM::TextBrowser::textInsertRequested, this, &AltTransView::textInsertRequested); //connect(m_browser, &TM::TextBrowser::customContextMenuRequested, this, &AltTransView::contextMenu); } AltTransView::~AltTransView() { } void AltTransView::dragEnterEvent(QDragEnterEvent* event) { if (event->mimeData()->hasUrls() && Catalog::extIsSupported(event->mimeData()->urls().first().path())) event->acceptProposedAction(); } void AltTransView::dropEvent(QDropEvent *event) { event->acceptProposedAction(); attachAltTransFile(event->mimeData()->urls().first().toLocalFile()); //update m_prevEntry.entry = -1; QTimer::singleShot(0, this, &AltTransView::process); } void AltTransView::attachAltTransFile(const QString& path) { MergeCatalog* altCat = new MergeCatalog(m_catalog, m_catalog, /*saveChanges*/false); altCat->loadFromUrl(path); m_catalog->attachAltTransCatalog(altCat); } void AltTransView::addAlternateTranslation(int entry, const QString& trans) { AltTrans altTrans; altTrans.target = trans; m_catalog->attachAltTrans(entry, altTrans); m_prevEntry = DocPos(); QTimer::singleShot(0, this, &AltTransView::process); } void AltTransView::fileLoaded() { m_prevEntry.entry = -1; QString absPath = m_catalog->url(); QString relPath = QDir(Project::instance()->projectDir()).relativeFilePath(absPath); QFileInfo info(Project::instance()->altTransDir() % '/' % relPath); if (info.canonicalFilePath() != absPath && info.exists()) attachAltTransFile(info.canonicalFilePath()); else qCWarning(LOKALIZE_LOG) << "alt trans file doesn't exist:" << Project::instance()->altTransDir() % '/' % relPath; } void AltTransView::slotNewEntryDisplayed(const DocPosition& pos) { m_entry = DocPos(pos); QTimer::singleShot(0, this, &AltTransView::process); } void AltTransView::process() { if (m_entry == m_prevEntry) return; if (m_catalog->numberOfEntries() <= m_entry.entry) return;//because of Qt::QueuedConnection m_prevEntry = m_entry; m_browser->clear(); m_entryPositions.clear(); const QVector& entries = m_catalog->altTrans(m_entry.toDocPosition()); m_entries = entries; if (entries.isEmpty()) { if (m_hasInfo) { m_hasInfo = false; setWindowTitle(m_normTitle); } return; } if (!m_hasInfo) { m_hasInfo = true; setWindowTitle(m_hasInfoTitle); } if (!isVisible() && !Settings::altTransViewEverShownWithData()) { if (KMessageBox::questionYesNo(this, i18n("There is useful data available in Alternate Translations view.\n\n" "For Gettext PO files it displays difference between current source text " "and the source text corresponding to the fuzzy translation found by msgmerge when updating PO based on POT template.\n\n" "Do you want to show the view with the data?"), m_normTitle) == KMessageBox::Yes) show(); Settings::setAltTransViewEverShownWithData(true); } CatalogString source = m_catalog->sourceWithTags(m_entry.toDocPosition()); QTextBlockFormat blockFormatBase; QTextBlockFormat blockFormatAlternate; blockFormatAlternate.setBackground(QPalette().alternateBase()); QTextCharFormat noncloseMatchCharFormat; QTextCharFormat closeMatchCharFormat; closeMatchCharFormat.setFontWeight(QFont::Bold); int i = 0; int limit = entries.size(); forever { const AltTrans& entry = entries.at(i); QTextCursor cur = m_browser->textCursor(); QString html; html.reserve(1024); if (!entry.source.isEmpty()) { html += QStringLiteral("

"); QString result = userVisibleWordDiff(entry.source.string, source.string, Project::instance()->accel(), Project::instance()->markup()).toHtmlEscaped(); //result.replace("&","&"); //result.replace("<","<"); //result.replace(">",">"); result.replace(QStringLiteral("{KBABELADD}"), QStringLiteral("")); result.replace(QStringLiteral("{/KBABELADD}"), QStringLiteral("")); result.replace(QStringLiteral("{KBABELDEL}"), QStringLiteral("")); result.replace(QStringLiteral("{/KBABELDEL}"), QStringLiteral("")); result.replace(QStringLiteral("\\n"), QStringLiteral("\\n

")); html += result; html += QStringLiteral("
"); cur.insertHtml(html); html.clear(); } if (!entry.target.isEmpty()) { if (Q_LIKELY(i < m_actions.size())) { m_actions.at(i)->setStatusTip(entry.target.string); html += QString(QStringLiteral("[%1] ")).arg(m_actions.at(i)->shortcut().toString(QKeySequence::NativeText)); } else html += QStringLiteral("[ - ] "); cur.insertText(html); html.clear(); insertContent(cur, entry.target); } m_entryPositions.insert(cur.anchor(), i); html += i ? QStringLiteral("

") : QStringLiteral("

"); cur.insertHtml(html); if (Q_UNLIKELY(++i >= limit)) break; cur.insertBlock(i % 2 ? blockFormatAlternate : blockFormatBase); } if (!m_everShown) { m_everShown = true; show(); KConfig config; KConfigGroup group(&config, "AltTransView"); group.writeEntry("EverShown", true); } } bool AltTransView::event(QEvent *event) { if (event->type() == QEvent::ToolTip) { QHelpEvent *helpEvent = static_cast(event); if (m_entryPositions.isEmpty()) { QString tooltip = i18nc("@info:tooltip", "

Sometimes, if source text is changed, its translation becomes deprecated and is either marked as needing review (i.e. looses approval status), " "or (only in case of XLIFF file) moved to the alternate translations section accompanying the unit.

" "

This toolview also shows the difference between current source string and the previous source string, so that you can easily see which changes should be applied to existing translation to make it reflect current source.

" "

Double-clicking any word in this toolview inserts it into translation.

" "

Drop translation file onto this toolview to use it as a source for additional alternate translations.

" ); QToolTip::showText(helpEvent->globalPos(), tooltip); return true; } int block1 = m_browser->cursorForPosition(m_browser->viewport()->mapFromGlobal(helpEvent->globalPos())).blockNumber(); int block = *m_entryPositions.lowerBound(m_browser->cursorForPosition(m_browser->viewport()->mapFromGlobal(helpEvent->globalPos())).anchor()); if (block1 != block) qCWarning(LOKALIZE_LOG) << "block numbers don't match"; if (block >= m_entries.size()) return false; QString origin = m_entries.at(block).origin; if (origin.isEmpty()) return false; QString tooltip = i18nc("@info:tooltip", "Origin: %1", origin); QToolTip::showText(helpEvent->globalPos(), tooltip); return true; } return QWidget::event(event); } void AltTransView::slotUseSuggestion(int i) { if (Q_UNLIKELY(i >= m_entries.size())) return; TM::TMEntry tmEntry; tmEntry.target = m_entries.at(i).target; CatalogString source = m_catalog->sourceWithTags(m_entry.toDocPosition()); tmEntry.diff = userVisibleWordDiff(m_entries.at(i).source.string, source.string, Project::instance()->accel(), Project::instance()->markup()); CatalogString target = TM::targetAdapted(tmEntry, source); qCWarning(LOKALIZE_LOG) << "0" << target.string; if (Q_UNLIKELY(target.isEmpty())) return; m_catalog->beginMacro(i18nc("@item Undo action", "Use alternate translation")); QString old = m_catalog->targetWithTags(m_entry.toDocPosition()).string; if (!old.isEmpty()) { //FIXME test! removeTargetSubstring(m_catalog, m_entry.toDocPosition(), 0, old.size()); //m_catalog->push(new DelTextCmd(m_catalog,m_pos,m_catalog->msgstr(m_pos))); } qCWarning(LOKALIZE_LOG) << "1" << target.string; //m_catalog->push(new InsTextCmd(m_catalog,m_pos,target)/*,true*/); insertCatalogString(m_catalog, m_entry.toDocPosition(), target, 0); m_catalog->endMacro(); emit refreshRequested(); } diff --git a/src/binunitsview.cpp b/src/binunitsview.cpp index 036d661..c5c5f98 100644 --- a/src/binunitsview.cpp +++ b/src/binunitsview.cpp @@ -1,213 +1,213 @@ /* **************************************************************************** This file is part of Lokalize Copyright (C) 2009-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 "binunitsview.h" #include "phaseswindow.h" //MyTreeView #include "catalog.h" #include "cmd.h" #include "project.h" #include #include #include -#include -#include -#include +#include +#include +#include //BEGIN BinUnitsModel BinUnitsModel::BinUnitsModel(Catalog* catalog, QObject* parent) : QAbstractListModel(parent) , m_catalog(catalog) { connect(catalog, QOverload<>::of(&Catalog::signalFileLoaded), this, &BinUnitsModel::fileLoaded); connect(catalog, &Catalog::signalEntryModified, this, &BinUnitsModel::entryModified); connect(KDirWatch::self(), &KDirWatch::dirty, this, &BinUnitsModel::updateFile); } void BinUnitsModel::fileLoaded() { beginResetModel(); m_imageCache.clear(); endResetModel(); } void BinUnitsModel::entryModified(const DocPosition& pos) { if (pos.entry < m_catalog->numberOfEntries()) return; QModelIndex item = index(pos.entry - m_catalog->numberOfEntries(), TargetFilePath); emit dataChanged(item, item); } void BinUnitsModel::updateFile(QString path) { QString relPath = QDir(Project::instance()->projectDir()).relativeFilePath(path); DocPosition pos(m_catalog->numberOfEntries()); int limit = m_catalog->numberOfEntries() + m_catalog->binUnitsCount(); while (pos.entry < limit) { if (m_catalog->target(pos) == relPath || m_catalog->source(pos) == relPath) { int row = pos.entry - m_catalog->numberOfEntries(); m_imageCache.remove(relPath); emit dataChanged(index(row, SourceFilePath), index(row, TargetFilePath)); return; } pos.entry++; } } void BinUnitsModel::setTargetFilePath(int row, const QString& path) { DocPosition pos(row + m_catalog->numberOfEntries()); QString old = m_catalog->target(pos); if (!old.isEmpty()) { m_catalog->push(new DelTextCmd(m_catalog, pos, old)); m_imageCache.remove(old); } m_catalog->push(new InsTextCmd(m_catalog, pos, QDir(Project::instance()->projectDir()).relativeFilePath(path))); QModelIndex item = index(row, TargetFilePath); emit dataChanged(item, item); } int BinUnitsModel::rowCount(const QModelIndex& parent) const { if (parent.isValid()) return 0; return m_catalog->binUnitsCount(); } QVariant BinUnitsModel::data(const QModelIndex& index, int role) const { if (role == Qt::DecorationRole) { DocPosition pos(index.row() + m_catalog->numberOfEntries()); if (index.column() < Approved) { QString path = index.column() == SourceFilePath ? m_catalog->source(pos) : m_catalog->target(pos); if (!m_imageCache.contains(path)) { QString absPath = Project::instance()->absolutePath(path); KDirWatch::self()->addFile(absPath); //TODO remember watched files to react only on them in dirty() signal handler m_imageCache.insert(path, QImage(absPath).scaled(128, 128, Qt::KeepAspectRatio)); } return m_imageCache.value(path); } } else if (role == Qt::TextAlignmentRole) return int(Qt::AlignLeft | Qt::AlignTop); if (role != Qt::DisplayRole) return QVariant(); static const char* noyes[] = {I18N_NOOP("no"), I18N_NOOP("yes")}; DocPosition pos(index.row() + m_catalog->numberOfEntries()); switch (index.column()) { case SourceFilePath: return m_catalog->source(pos); case TargetFilePath: return m_catalog->target(pos); case Approved: return noyes[m_catalog->isApproved(pos)]; } return QVariant(); } QVariant BinUnitsModel::headerData(int section, Qt::Orientation, int role) const { if (role != Qt::DisplayRole) return QVariant(); switch (section) { case SourceFilePath: return i18nc("@title:column", "Source"); case TargetFilePath: return i18nc("@title:column", "Target"); case Approved: return i18nc("@title:column", "Approved"); } return QVariant(); } //END BinUnitsModel BinUnitsView::BinUnitsView(Catalog* catalog, QWidget* parent) : QDockWidget(i18nc("@title toolview name", "Binary Units"), parent) , m_catalog(catalog) , m_model(new BinUnitsModel(catalog, this)) , m_view(new MyTreeView(this)) { setObjectName(QStringLiteral("binUnits")); hide(); setWidget(m_view); m_view->setModel(m_model); m_view->setRootIsDecorated(false); m_view->setAlternatingRowColors(true); m_view->viewport()->setBackgroundRole(QPalette::Background); connect(m_view, &MyTreeView::doubleClicked, this, &BinUnitsView::mouseDoubleClicked); connect(catalog, QOverload<>::of(&Catalog::signalFileLoaded), this, &BinUnitsView::fileLoaded); } void BinUnitsView::fileLoaded() { setVisible(m_catalog->binUnitsCount()); } void BinUnitsView::selectUnit(const QString& id) { QModelIndex item = m_model->index(m_catalog->unitById(id) - m_catalog->numberOfEntries()); m_view->setCurrentIndex(item); m_view->scrollTo(item); show(); } void BinUnitsView::contextMenuEvent(QContextMenuEvent *event) { QModelIndex item = m_view->currentIndex(); if (!item.isValid()) return; QMenu menu; QAction* setTarget = menu.addAction(i18nc("@action:inmenu", "Set the file")); QAction* useSource = menu.addAction(i18nc("@action:inmenu", "Use source file")); // menu.addSeparator(); // QAction* openSource=menu.addAction(i18nc("@action:inmenu","Open source file in external program")); // QAction* openTarget=menu.addAction(i18nc("@action:inmenu","Open target file in external program")); QAction* result = menu.exec(event->globalPos()); if (!result) return; QString sourceFilePath = item.sibling(item.row(), BinUnitsModel::SourceFilePath).data().toString(); if (result == useSource) m_model->setTargetFilePath(item.row(), sourceFilePath); else if (result == setTarget) { QString targetFilePath = QFileDialog::getOpenFileName(this, QString(), Project::instance()->projectDir()); if (!targetFilePath.isEmpty()) m_model->setTargetFilePath(item.row(), targetFilePath); } event->accept(); } void BinUnitsView::mouseDoubleClicked(const QModelIndex& item) { //FIXME child processes don't notify us about changes ;( if (item.column() < BinUnitsModel::Approved) new KRun(QUrl::fromLocalFile(Project::instance()->absolutePath(item.data().toString())), this); } diff --git a/src/catalog/gettext/gettextstorage.cpp b/src/catalog/gettext/gettextstorage.cpp index 0ee7931..cc67a08 100644 --- a/src/catalog/gettext/gettextstorage.cpp +++ b/src/catalog/gettext/gettextstorage.cpp @@ -1,466 +1,466 @@ /* Copyright 2008-2014 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 "gettextstorage.h" #include "lokalize_debug.h" #include "gettextheader.h" #include "catalogitem_private.h" #include "gettextimport.h" #include "gettextexport.h" #include "project.h" #include "version.h" #include "prefs_lokalize.h" #include "diff.h" #include #include #include #include #include #include QMutex regExMutex; // static QString GNUPluralForms(const QString& lang); using namespace GettextCatalog; GettextStorage::GettextStorage() : CatalogStorage() , m_codec(0) , m_maxLineLength(80) , m_trailingNewLines(0) , m_generatedFromDocbook(false) { } GettextStorage::~GettextStorage() { } //BEGIN OPEN/SAVE int GettextStorage::load(QIODevice* device/*, bool readonly*/) { //GettextImportPlugin importer=GettextImportPlugin(readonly?(new ExtraDataSaver()):(new ExtraDataListSaver())); GettextImportPlugin importer; ConversionStatus status = OK; int errorLine; { QMutexLocker locker(®ExMutex); status = importer.open(device, this, &errorLine); } //for langs with more than 2 forms //we create any form-entries additionally needed uint i = 0; uint lim = size(); while (i < lim) { CatalogItem& item = m_entries[i]; if (item.isPlural() && item.msgstrPlural().count() < m_numberOfPluralForms ) { QVector msgstr(item.msgstrPlural()); while (msgstr.count() < m_numberOfPluralForms) msgstr.append(QString()); item.setMsgstr(msgstr); } ++i; } //qCompress(m_storage->m_catalogExtraData.join("\n\n").toUtf8(),9); return status == OK ? 0 : (errorLine + 1); } bool GettextStorage::save(QIODevice* device, bool belongsToProject) { QString header = m_header.msgstr(); QString comment = m_header.comment(); QString catalogProjectId;//=m_url.fileName(); //catalogProjectId=catalogProjectId.left(catalogProjectId.lastIndexOf('.')); { QMutexLocker locker(®ExMutex); updateHeader(header, comment, m_targetLangCode, m_numberOfPluralForms, catalogProjectId, m_generatedFromDocbook, belongsToProject, /*forSaving*/true, m_codec); } m_header.setMsgstr(header); m_header.setComment(comment); //GettextExportPlugin exporter(m_maxLineLength>70?m_maxLineLength:-1, m_trailingNewLines);// this is kinda hackish... GettextExportPlugin exporter(Project::instance()->wordWrap(), m_trailingNewLines); ConversionStatus status = OK; status = exporter.save(device/*x-gettext-translation*/, this, m_codec); return status == OK; } //END OPEN/SAVE //BEGIN STORAGE TRANSLATION int GettextStorage::size() const { return m_entries.size(); } static const QChar altSep(156); static InlineTag makeInlineTag(int i) { static const QString altSepText(QStringLiteral(" | ")); static const QString ctype = i18n("separator for different-length string alternatives"); return InlineTag(i, i, InlineTag::x, QString::number(i), QString(), altSepText, ctype); } static CatalogString makeCatalogString(const QString& string) { CatalogString result; result.string = string; int i = 0; while ((i = result.string.indexOf(altSep, i)) != -1) { result.string[i] = TAGRANGE_IMAGE_SYMBOL; result.tags.append(makeInlineTag(i)); ++i; } return result; } //flat-model interface (ignores XLIFF grouping) CatalogString GettextStorage::sourceWithTags(DocPosition pos) const { return makeCatalogString(source(pos)); } CatalogString GettextStorage::targetWithTags(DocPosition pos) const { return makeCatalogString(target(pos)); } QString GettextStorage::source(const DocPosition& pos) const { return m_entries.at(pos.entry).msgid(pos.form); } QString GettextStorage::target(const DocPosition& pos) const { return m_entries.at(pos.entry).msgstr(pos.form); } QString GettextStorage::sourceWithPlurals(const DocPosition& pos) const { if (m_entries.at(pos.entry).isPlural()) { const QVector plurals = m_entries.at(pos.entry).msgidPlural(); - QString pluralString = QString(); + QString pluralString; for (int i = 0; i < plurals.size(); i++) { pluralString += plurals.at(i); if (i != plurals.size() - 1) { pluralString += '|'; } } return pluralString; } else { return m_entries.at(pos.entry).msgid(pos.form); } } QString GettextStorage::targetWithPlurals(const DocPosition& pos) const { if (m_entries.at(pos.entry).isPlural()) { const QVector plurals = m_entries.at(pos.entry).msgstrPlural(); - QString pluralString = QString(); + QString pluralString; for (int i = 0; i < plurals.size(); i++) { pluralString += plurals.at(i); if (i != plurals.size() - 1) { pluralString += '|'; } } return pluralString; } else { return m_entries.at(pos.entry).msgstr(pos.form); } } void GettextStorage::targetDelete(const DocPosition& pos, int count) { m_entries[pos.entry].d._msgstrPlural[pos.form].remove(pos.offset, count); } void GettextStorage::targetInsert(const DocPosition& pos, const QString& arg) { m_entries[pos.entry].d._msgstrPlural[pos.form].insert(pos.offset, arg); } void GettextStorage::setTarget(const DocPosition& pos, const QString& arg) { m_entries[pos.entry].d._msgstrPlural[pos.form] = arg; } void GettextStorage::targetInsertTag(const DocPosition& pos, const InlineTag& tag) { Q_UNUSED(tag); targetInsert(pos, altSep); } InlineTag GettextStorage::targetDeleteTag(const DocPosition& pos) { targetDelete(pos, 1); return makeInlineTag(pos.offset); } QStringList GettextStorage::sourceAllForms(const DocPosition& pos, bool stripNewLines) const { return m_entries.at(pos.entry).allPluralForms(CatalogItem::Source, stripNewLines); } QStringList GettextStorage::targetAllForms(const DocPosition& pos, bool stripNewLines) const { return m_entries.at(pos.entry).allPluralForms(CatalogItem::Target, stripNewLines); } QVector GettextStorage::altTrans(const DocPosition& pos) const { static const QRegExp alt_trans_mark_re(QStringLiteral("^#\\|")); QStringList prev = m_entries.at(pos.entry).comment().split('\n').filter(alt_trans_mark_re); QString oldSingular; QString oldPlural; QString* cur = &oldSingular; QStringList::iterator it = prev.begin(); static const QString msgid_plural_alt = QStringLiteral("#| msgid_plural \""); while (it != prev.end()) { if (it->startsWith(msgid_plural_alt)) cur = &oldPlural; int start = it->indexOf('\"') + 1; int end = it->lastIndexOf('\"'); if (start && end != -1) { if (!cur->isEmpty()) (*cur) += '\n'; if (!(cur->isEmpty() && (end - start) == 0)) //for multiline msgs (*cur) += it->midRef(start, end - start); } ++it; } if (pos.form == 0) cur = &oldSingular; cur->replace(QStringLiteral("\\\""), QStringLiteral("\"")); QVector result; if (!cur->isEmpty()) result << AltTrans(CatalogString(*cur), i18n("Previous source value, saved by Gettext during transition to a newer POT template")); return result; } Note GettextStorage::setNote(DocPosition pos, const Note& note) { //qCWarning(LOKALIZE_LOG)<<"s"< l = notes(pos); if (l.size()) oldNote = l.first(); QStringList comment = m_entries.at(pos.entry).comment().split('\n'); //remove previous comment; QStringList::iterator it = comment.begin(); while (it != comment.end()) { if (it->startsWith(QLatin1String("# "))) it = comment.erase(it); else ++it; } if (note.content.size()) comment.prepend(QStringLiteral("# ") + note.content.split('\n').join(QStringLiteral("\n# "))); m_entries[pos.entry].setComment(comment.join(QStringLiteral("\n"))); //qCWarning(LOKALIZE_LOG)<<"e"< GettextStorage::notes(const DocPosition& docPosition, const QRegExp& re, int preLen) const { QVector result; QString content; QStringList note = m_entries.at(docPosition.entry).comment().split('\n').filter(re); foreach (const QString &s, note) { if (s.size() >= preLen) { content += s.midRef(preLen); content += QLatin1Char('\n'); } } if (!content.isEmpty()) { content.chop(1); result << Note(content); } return result; //i18nc("@info PO comment parsing. contains filename","Place:"); //i18nc("@info PO comment parsing","GUI place:"); } QVector GettextStorage::notes(const DocPosition& docPosition) const { static const QRegExp nre(QStringLiteral("^# ")); return notes(docPosition, nre, 2); } QVector GettextStorage::developerNotes(const DocPosition& docPosition) const { static const QRegExp dnre(QStringLiteral("^#\\. (?!i18n: file:)")); return notes(docPosition, dnre, 3); } QStringList GettextStorage::sourceFiles(const DocPosition& pos) const { QStringList result; QStringList commentLines = m_entries.at(pos.entry).comment().split('\n'); static const QRegExp i18n_file_re(QStringLiteral("^#. i18n: file: ")); foreach (const QString &uiLine, commentLines.filter(i18n_file_re)) { foreach (const QStringRef &fileRef, uiLine.midRef(15).split(' ')) { result << fileRef.toString(); } } bool hasUi = !result.isEmpty(); static const QRegExp cpp_re(QStringLiteral("^#: ")); foreach (const QString &cppLine, commentLines.filter(cpp_re)) { if (hasUi && cppLine.startsWith(QLatin1String("#: rc.cpp"))) continue; foreach (const QStringRef &fileRef, cppLine.midRef(3).split(' ')) { result << fileRef.toString(); } } return result; } QStringList GettextStorage::context(const DocPosition& pos) const { return matchData(pos); } QStringList GettextStorage::matchData(const DocPosition& pos) const { QString ctxt = m_entries.at(pos.entry).msgctxt(); //KDE-specific //Splits @info:whatsthis and actual note /* if (ctxt.startsWith('@') && ctxt.contains(' ')) { QStringList result(ctxt.section(' ',0,0,QString::SectionSkipEmpty)); result<poDir()); updateHeader(values, comment, m_targetLangCode, m_numberOfPluralForms, catalogProjectId, m_generatedFromDocbook, belongsToProject, /*forSaving*/true, m_codec); m_header = newHeader; m_header.setComment(comment); m_header.setMsgstr(values); // setClean(false); //emit signalHeaderChanged(); return true; } qCWarning(LOKALIZE_LOG) << "header Not valid"; return false; } diff --git a/src/common/winhelpers.cpp b/src/common/winhelpers.cpp index ac134f8..5229222 100644 --- a/src/common/winhelpers.cpp +++ b/src/common/winhelpers.cpp @@ -1,12 +1,36 @@ +/* **************************************************************************** + This file is part of Lokalize + + Copyright (C) 2018 by Simon Depiets + 2007-2017 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 #include #define SECURITY_WIN32 #include QString fullUserName() { ushort name[100]; unsigned long size = 99; GetUserNameW((LPWSTR)name, &size); return QString::fromUtf16(name); } diff --git a/src/glossary/tbxparser_obsolete.cpp b/src/glossary/tbxparser_obsolete.cpp index 622e1ba..34a5da3 100644 --- a/src/glossary/tbxparser_obsolete.cpp +++ b/src/glossary/tbxparser_obsolete.cpp @@ -1,124 +1,124 @@ /* **************************************************************************** This file is part of Lokalize Copyright (C) 2007-2009 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 "lokalize_debug.h" #include "tbxparser.h" #include "glossary.h" #include "project.h" using namespace GlossaryNS; bool TbxParser::startDocument() { m_state = null; m_lang = langNull; return true; } bool TbxParser::startElement(const QString&, const QString&, const QString& qName, const QXmlAttributes& attr) { if (qName == "langSet") { - if (attr.value("xml:lang").startsWith("en")) + if (attr.value("xml:lang").startsWith(!QLatin1String("en"))) m_lang = langEn; else if (attr.value("xml:lang") == Project::instance()->langCode()) m_lang = langTarget; else m_lang = langNull; } else if (qName == "term") { m_state = term; } else if (qName == "termEntry") { m_termEn.clear(); m_termOther.clear(); m_entry.clear(); m_entry.id = attr.value("id"); } else if (qName == "descrip") { if (attr.value("type") == "definition") m_state = descripDefinition; else if (attr.value("type") == "subjectField") m_state = descripSubjectField; } return true; } bool TbxParser::endElement(const QString&, const QString&, const QString& qName) { if (qName == "term") { if (m_lang == langEn) { m_entry.english << m_termEn; m_termEn.clear(); m_entry.english.last().squeeze(); } else if (m_lang == langTarget) { m_entry.target << m_termOther; m_termOther.clear(); m_entry.target.last().squeeze(); } } else if (qName == "descrip") { if (m_state == descripSubjectField && !m_subjectField.isEmpty()) { m_entry.subjectField = Project::instance()->glossary()->subjectFields.indexOf(m_subjectField); if (m_entry.subjectField == -1) { //got this field value for the first time m_entry.subjectField = Project::instance()->glossary()->subjectFields.size(); Project::instance()->glossary()->subjectFields << m_subjectField; } m_subjectField.clear(); } } else if (qName == "termEntry") { //sanity check --maybe this entry is only for another language? if (m_entry.target.isEmpty() || m_entry.english.isEmpty()) return true; int index = m_glossary->termList.count(); m_glossary->termList.append(m_entry); m_glossary->hashTermEntry(index); m_entry.clear(); } m_state = null; return true; } bool TbxParser::characters(const QString & ch) { if (m_state == term) { if (m_lang == langEn) m_termEn += ch.toLower(); //this is important else if (m_lang == langTarget) m_termOther += ch; } else if (m_state == descripDefinition) m_entry.definition += ch; else if (m_state == descripSubjectField) m_subjectField += ch; return true; } diff --git a/src/prefs/prefs.cpp b/src/prefs/prefs.cpp index a24cfd5..a026c0d 100644 --- a/src/prefs/prefs.cpp +++ b/src/prefs/prefs.cpp @@ -1,395 +1,395 @@ /* **************************************************************************** This file is part of Lokalize Copyright (C) 2007-2011 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 "prefs.h" #include "lokalize_debug.h" #include "prefs_lokalize.h" #include "project.h" #include "projectlocal.h" #include "projectmodel.h" #include "languagelistmodel.h" #include "dbfilesmodel.h" #include "ui_prefs_identity.h" #include "ui_prefs_editor.h" #include "ui_prefs_general.h" #include "ui_prefs_appearance.h" #include "ui_prefs_pology.h" #include "ui_prefs_tm.h" #include "ui_prefs_projectmain.h" #include "ui_prefs_project_advanced.h" #include "ui_prefs_project_local.h" -#include -#include -#include -#include +#include +#include +#include +#include #include #include #include #include #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; } SettingsController::SettingsController() : QObject(Project::instance()) , dirty(false) , m_projectActionsView(0) , m_mainWindowPtr(0) {} SettingsController::~SettingsController() {} void SettingsController::showSettingsDialog() { if (KConfigDialog::showDialog("lokalize_settings")) return; KConfigDialog *dialog = new KConfigDialog(m_mainWindowPtr, "lokalize_settings", Settings::self()); dialog->setFaceType(KPageDialog::List); // Identity QWidget *w = new QWidget(dialog); Ui_prefs_identity ui_prefs_identity; ui_prefs_identity.setupUi(w); KConfigGroup grp = Settings::self()->config()->group("Identity"); ui_prefs_identity.DefaultLangCode->setModel(LanguageListModel::instance()->sortModel()); ui_prefs_identity.DefaultLangCode->setCurrentIndex(LanguageListModel::instance()->sortModelRowForLangCode(grp.readEntry("DefaultLangCode", QLocale::system().name()))); connect(ui_prefs_identity.DefaultLangCode, QOverload::of(&KComboBox::activated), ui_prefs_identity.kcfg_DefaultLangCode, &LangCodeSaver::setLangCode); ui_prefs_identity.kcfg_DefaultLangCode->hide(); dialog->addPage(w, i18nc("@title:tab", "Identity"), "preferences-desktop-user"); //General w = new QWidget(dialog); Ui_prefs_general ui_prefs_general; ui_prefs_general.setupUi(w); dialog->addPage(w, i18nc("@title:tab", "General"), "preferences-system-windows"); //Editor w = new QWidget(dialog); Ui_prefs_editor ui_prefs_editor; ui_prefs_editor.setupUi(w); dialog->addPage(w, i18nc("@title:tab", "Editing"), "accessories-text-editor"); //Font w = new QWidget(dialog); Ui_prefs_appearance ui_prefs_appearance; ui_prefs_appearance.setupUi(w); dialog->addPage(w, i18nc("@title:tab", "Appearance"), "preferences-desktop-font"); //TM w = new QWidget(dialog); Ui_prefs_tm ui_prefs_tm; ui_prefs_tm.setupUi(w); dialog->addPage(w, i18nc("@title:tab", "Translation Memory"), "configure"); //Pology w = new QWidget(dialog); Ui_prefs_pology ui_prefs_pology; ui_prefs_pology.setupUi(w); dialog->addPage(w, i18nc("@title:tab", "Pology"), "preferences-desktop-filetype-association"); connect(dialog, &KConfigDialog::settingsChanged, this, &SettingsController::generalSettingsChanged); //Spellcheck #if 0 w = new Sonnet::ConfigWidget(Settings::self()->config(), dialog); w->setParent(this); dialog->addPage(w, i18nc("@title:tab", "Spellcheck"), "spellcheck_setting"); connect(dialog, SIGNAL(okClicked()), w, SLOT(save())); connect(dialog, SIGNAL(applyClicked()), w, SLOT(save())); connect(dialog, SIGNAL(defaultClicked()), w, SLOT(slotDefault())); #endif //connect(dialog,SIGNAL(settingsChanged(const QString&)),m_view, SLOT(settingsChanged())); dialog->show(); // dialog->addPage(new General(0, "General"), i18n("General") ); // dialog->addPage(new Appearance(0, "Style"), i18n("Appearance") ); // connect(dialog, SIGNAL(settingsChanged(const QString&)), mainWidget, SLOT(loadSettings())); // connect(dialog, SIGNAL(settingsChanged(const QString&)), this, SLOT(loadSettings())); } ScriptsView::ScriptsView(QWidget* parent): Kross::ActionCollectionView(parent) { setAcceptDrops(true); } void ScriptsView::dragEnterEvent(QDragEnterEvent* event) { if (!event->mimeData()->urls().isEmpty() && event->mimeData()->urls().first().path().endsWith(QLatin1String(".rc"))) event->accept(); } void ScriptsView::dropEvent(QDropEvent* event) { Kross::ActionCollectionModel* scriptsModel = static_cast(model()); foreach (const QUrl& url, event->mimeData()->urls()) - if (url.path().endsWith(".rc")) + if (url.path().endsWith(QLatin1String(".rc"))) scriptsModel->rootCollection()->readXmlFile(url.path()); } bool SettingsController::ensureProjectIsLoaded() { if (Project::instance()->isLoaded()) return true; int answer = KMessageBox::questionYesNoCancel(m_mainWindowPtr, i18n("You have accessed a feature that requires a project to be loaded. Do you want to create a new project or open an existing project?"), QString(), KGuiItem(i18nc("@action", "New"), QIcon::fromTheme("document-new")), KGuiItem(i18nc("@action", "Open"), QIcon::fromTheme("project-open")) ); if (answer == KMessageBox::Yes) return projectCreate(); if (answer == KMessageBox::No) return !projectOpen().isEmpty(); return false; } QString SettingsController::projectOpen(QString path, bool doOpen) { if (path.isEmpty()) { //Project::instance()->model()->weaver()->suspend(); //KDE5PORT mutex if needed path = QFileDialog::getOpenFileName(m_mainWindowPtr, QString(), QDir::homePath()/*_catalog->url().directory()*/, i18n("Lokalize translation project (*.lokalize)")/*"text/x-lokalize-project"*/); //Project::instance()->model()->weaver()->resume(); } if (!path.isEmpty() && doOpen) Project::instance()->load(path); return path; } bool SettingsController::projectCreate() { //Project::instance()->model()->weaver()->suspend(); //KDE5PORT mutex if needed QString desirablePath = Project::instance()->desirablePath(); if (desirablePath.isEmpty()) desirablePath = QDir::homePath() + "/index.lokalize"; QString path = QFileDialog::getSaveFileName(m_mainWindowPtr, i18nc("@window:title", "Select folder with Gettext .po files to translate"), desirablePath, i18n("Lokalize translation project (*.lokalize)") /*"text/x-lokalize-project"*/); //Project::instance()->model()->weaver()->resume(); if (path.isEmpty()) return false; if (m_projectActionsView && m_projectActionsView->model()) { //ActionCollectionModel is known to be have bad for the usecase of reinitializing krossplugin m_projectActionsView->model()->deleteLater(); m_projectActionsView->setModel(0); } //TODO ask-n-save QDir projectFolder = QFileInfo(path).absoluteDir(); QString projectId = projectFolder.dirName(); if (projectFolder.cdUp()) projectId = projectFolder.dirName() % '-' % projectId;; Project::instance()->load(path, QString(), projectId); //Project::instance()->setDefaults(); //NOTE will this be an obstacle? //Project::instance()->setProjectID(); QTimer::singleShot(500, this, &SettingsController::projectConfigure); return true; } void SettingsController::projectConfigure() { if (Project::instance()->path().isEmpty()) { KMessageBox::error(mainWindowPtr(), i18n("Create software or OpenDocument translation project first.")); return; } if (KConfigDialog::showDialog("project_settings")) { if (!m_projectActionsView->model()) m_projectActionsView->setModel(new Kross::ActionCollectionModel(m_projectActionsView, Kross::Manager::self().actionCollection()->collection(Project::instance()->kind()))); return; } KConfigDialog *dialog = new KConfigDialog(m_mainWindowPtr, "project_settings", Project::instance()); dialog->setFaceType(KPageDialog::List); // Main QWidget *w = new QWidget(dialog); Ui_prefs_projectmain ui_prefs_projectmain; ui_prefs_projectmain.setupUi(w); dialog->addPage(w, i18nc("@title:tab", "General"), "preferences-desktop-locale"); ui_prefs_projectmain.kcfg_LangCode->hide(); ui_prefs_projectmain.kcfg_PoBaseDir->hide(); ui_prefs_projectmain.kcfg_GlossaryTbx->hide(); Project& p = *(Project::instance()); ui_prefs_projectmain.LangCode->setModel(LanguageListModel::instance()->sortModel()); ui_prefs_projectmain.LangCode->setCurrentIndex(LanguageListModel::instance()->sortModelRowForLangCode(p.langCode())); connect(ui_prefs_projectmain.LangCode, QOverload::of(&KComboBox::activated), ui_prefs_projectmain.kcfg_LangCode, &LangCodeSaver::setLangCode); ui_prefs_projectmain.poBaseDir->setMode(KFile::Directory | KFile::ExistingOnly | KFile::LocalOnly); ui_prefs_projectmain.glossaryTbx->setMode(KFile::File | KFile::ExistingOnly | KFile::LocalOnly); ui_prefs_projectmain.glossaryTbx->setFilter("*.tbx\n*.xml"); connect(ui_prefs_projectmain.poBaseDir, &KUrlRequester::textChanged, ui_prefs_projectmain.kcfg_PoBaseDir, &RelPathSaver::setText); connect(ui_prefs_projectmain.glossaryTbx, &KUrlRequester::textChanged, ui_prefs_projectmain.kcfg_GlossaryTbx, &RelPathSaver::setText); ui_prefs_projectmain.poBaseDir->setUrl(QUrl::fromLocalFile(p.poDir())); ui_prefs_projectmain.glossaryTbx->setUrl(QUrl::fromLocalFile(p.glossaryPath())); // RegExps w = new QWidget(dialog); Ui_project_advanced ui_project_advanced; ui_project_advanced.setupUi(w); ui_project_advanced.kcfg_PotBaseDir->hide(); ui_project_advanced.kcfg_BranchDir->hide(); ui_project_advanced.kcfg_AltDir->hide(); ui_project_advanced.potBaseDir->setMode(KFile::Directory | KFile::ExistingOnly | KFile::LocalOnly); ui_project_advanced.branchDir->setMode(KFile::Directory | KFile::ExistingOnly | KFile::LocalOnly); ui_project_advanced.altDir->setMode(KFile::Directory | KFile::ExistingOnly | KFile::LocalOnly); connect(ui_project_advanced.potBaseDir, &KUrlRequester::textChanged, ui_project_advanced.kcfg_PotBaseDir, &RelPathSaver::setText); connect(ui_project_advanced.branchDir, &KUrlRequester::textChanged, ui_project_advanced.kcfg_BranchDir, &RelPathSaver::setText); connect(ui_project_advanced.altDir, &KUrlRequester::textChanged, ui_project_advanced.kcfg_AltDir, &RelPathSaver::setText); ui_project_advanced.potBaseDir->setUrl(QUrl::fromLocalFile(p.potDir())); ui_project_advanced.branchDir->setUrl(QUrl::fromLocalFile(p.branchDir())); ui_project_advanced.altDir->setUrl(QUrl::fromLocalFile(p.altTransDir())); dialog->addPage(w, i18nc("@title:tab", "Advanced"), "applications-development-translation"); //Scripts w = new QWidget(dialog); QVBoxLayout* layout = new QVBoxLayout(w); layout->setSpacing(6); layout->setMargin(11); //m_projectActionsEditor=new Kross::ActionCollectionEditor(Kross::Manager::self().actionCollection()->collection(Project::instance()->projectID()),w); m_projectActionsView = new ScriptsView(w); layout->addWidget(m_projectActionsView); m_projectActionsView->setModel(new Kross::ActionCollectionModel(w, Kross::Manager::self().actionCollection()->collection(Project::instance()->kind()))); QHBoxLayout* btns = new QHBoxLayout(); layout->addLayout(btns); btns->addWidget(m_projectActionsView->createButton(w, "edit")); dialog->addPage(w, i18nc("@title:tab", "Scripts"), "preferences-system-windows-actions"); w = new QWidget(dialog); Ui_prefs_project_local ui_prefs_project_local; ui_prefs_project_local.setupUi(w); dialog->addPage(w, Project::local(), i18nc("@title:tab", "Personal"), "preferences-desktop-user"); connect(dialog, &KConfigDialog::settingsChanged, Project::instance(), &Project::reinit); connect(dialog, &KConfigDialog::settingsChanged, Project::instance(), &Project::save, Qt::QueuedConnection); connect(dialog, &KConfigDialog::settingsChanged, TM::DBFilesModel::instance(), &TM::DBFilesModel::updateProjectTmIndex); connect(dialog, &KConfigDialog::settingsChanged, this, &SettingsController::reflectProjectConfigChange); dialog->show(); } void SettingsController::reflectProjectConfigChange() { //TODO check target language change: reflect changes in TM and glossary TM::DBFilesModel::instance()->openDB(Project::instance()->projectID()); } void SettingsController::reflectRelativePathsHack() { //m_scriptsRelPrefWidget->clear(); QStringList actionz(m_scriptsPrefWidget->items()); QString projectDir(Project::instance()->projectDir()); int i = actionz.size(); while (--i >= 0) actionz[i] = QDir(projectDir).relativeFilePath(actionz.at(i)); m_scriptsRelPrefWidget->setItems(actionz); } void LangCodeSaver::setLangCode(int index) { setText(LanguageListModel::instance()->langCodeForSortModelRow(index)); } void RelPathSaver::setText(const QString& txt) { QLineEdit::setText(QDir(Project::instance()->projectDir()).relativeFilePath(txt)); } void writeUiState(const char* elementName, const QByteArray& state) { KConfig config; KConfigGroup cg(&config, "MainWindow"); cg.writeEntry(elementName, state.toBase64()); } QByteArray readUiState(const char* elementName) { KConfig config; KConfigGroup cg(&config, "MainWindow"); return QByteArray::fromBase64(cg.readEntry(elementName, QByteArray())); } diff --git a/src/project/prefs_project_advanced.ui b/src/project/prefs_project_advanced.ui index 54642e1..41b07dd 100644 --- a/src/project/prefs_project_advanced.ui +++ b/src/project/prefs_project_advanced.ui @@ -1,222 +1,222 @@ - + project_advanced 0 0 611 419 Syntax Accelerator: Usually '&', but may also be '_' for GTK apps. Markup: false Regular expression of markup. It is used for translation memory matching and for 'Insert tag' feature. A default value (suitable for XML-based texts) is: (<[^>]+>)+|(&[A-Za-z_:][A-Za-z0-9_\.:-]*;)+ It is only used for gettext PO files, as XLIFF format has its own way of specifying where markup is. Word wrap: Width used for the automatic msgfmt-like word wrap. Use the negative value '-1' to disable the word wrap. -1 100000 Paths QFormLayout::ExpandingFieldsGrow Template files folder: false 0 0 Usually your translation project will be a subproject of a project for translating same texts into multiple languages. Set this to path of a folder containing empty translation files (i.e. files without translation into any language) shared among all subprojects. Branch folder: false 0 0 This setting is for Sync Mode. Sync Mode may be used to make changes to translation for two branches simultaneously. Set this to path that corresponds to root folder of the branch project, and Secondary Sync view will automatically open files from branch. Then, each time you make changes in files of your main branch, they will automatically be replicated to the branch (of course, if it contains the same English string). See documentation for more details. Alternate translations folder: false 0 0 Set this to path of a folder with structure similar to Root Folder. On each translation file open, a corresponding file in Alternate translations directory will be looked up and, if it is found, it will be used for Alternate Translations view. You will likely want to use translations of another target language (i.e. another subproject), which is close to yours. Also, you can use other subproject's translations either immediately, or have them pretranslated to your language by machine. See documentation for more details. Qt::Vertical 20 40 KUrlRequester QFrame
kurlrequester.h
1
RelPathSaver QLineEdit
prefs.h
diff --git a/src/version.h b/src/version.h index 6e9a080..a5ee0b3 100644 --- a/src/version.h +++ b/src/version.h @@ -1,12 +1,27 @@ -// -// C++ Interface: version -// -// Description: -// -// -// Copyright: 2007-2014 Nick Shaforostoff -// -// +/* **************************************************************************** + This file is part of Lokalize + + Copyright (C) 2018 by Simon Depiets + 2007-2017 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 . + +**************************************************************************** */ + #ifndef LOKALIZE_VERSION #define LOKALIZE_VERSION "2.0" #endif