7#include <QtCore/QCoreApplication>
8#include <QtCore/QDebug>
10#include <QtWidgets/QMessageBox>
11#include <QtGui/QPainter>
12#include <QtGui/QPixmap>
13#include <QtGui/QTextDocument>
15#include <private/qtranslator_p.h>
22
23
24
25
27MessageItem::MessageItem(
const TranslatorMessage &message)
31 if (m_message.translation().isEmpty())
32 m_message.setTranslation(QString());
37 Qt::CaseSensitivity cs)
const
40 ? text().indexOf(findText, 0, cs) >= 0
41 : text().compare(findText, cs) == 0;
45
46
47
48
53 m_finishedDangerCount(0),
54 m_unfinishedDangerCount(0),
58void ContextItem::appendToComment(
const QString &str)
60 if (!m_comment.isEmpty())
61 m_comment += QLatin1String(
"\n\n");
67 if (i >= 0 && i < msgItemList.size())
68 return const_cast<MessageItem *>(&msgItemList[i]);
69 Q_ASSERT(i >= 0 && i < msgItemList.size());
77 if (mi->text() == sourcetext && mi->comment() == comment)
84
85
86
87
96 m_language(QLocale::Language(-1)),
97 m_sourceLanguage(QLocale::Language(-1)),
98 m_territory(QLocale::Territory(-1)),
99 m_sourceTerritory(QLocale::Territory(-1))
104 return Translator::normalizedTranslations(m.message(), m_numerusForms.size());
109 if (context >= 0 && context < m_contextList.size())
110 return const_cast<ContextItem *>(&m_contextList[context]);
111 Q_ASSERT(context >= 0 && context < m_contextList.size());
124 for (
int c = 0; c < m_contextList.size(); ++c) {
126 if (ctx->context() == context)
133 const QString &sourcetext,
const QString &comment)
const
136 return ctx->findMessage(sourcetext, comment);
145 if (
ContextItem *c = one->findContext(oc->context())) {
148 if (c->findMessage(m->text(), m->comment()))
164bool DataModel::
load(
const QString &fileName,
bool *langGuessed, QWidget *parent)
168 bool ok = tor.load(fileName, cd, QLatin1String(
"auto"));
170 QMessageBox::warning(parent, QObject::tr(
"Qt Linguist"), cd.error());
175 QMessageBox::warning(parent, QObject::tr(
"Qt Linguist"),
176 tr(
"The translation file '%1' will not be loaded because it is empty.")
177 .arg(fileName.toHtmlEscaped()));
182 if (!dupes.byId.isEmpty() || !dupes.byContents.isEmpty()) {
183 QString err = tr(
"<qt>Duplicate messages found in '%1':").arg(fileName.toHtmlEscaped());
185 for (
auto it = dupes.byId.begin(); it != dupes.byId.end(); ++it) {
186 if (++numdups >= 5) {
187 err += tr(
"<p>[more duplicates omitted]");
190 err += tr(
"<p>* ID: %1").arg(tor.message(it.key()).id().toHtmlEscaped());
192 for (
auto it = dupes.byContents.begin(); it != dupes.byContents.end(); ++it) {
194 if (++numdups >= 5) {
195 err += tr(
"<p>[more duplicates omitted]");
198 err += tr(
"<p>* Context: %1<br>* Source: %2")
199 .arg(msg.context().toHtmlEscaped(), msg.sourceText().toHtmlEscaped());
200 if (!msg.comment().isEmpty())
201 err += tr(
"<br>* Comment: %3").arg(msg.comment().toHtmlEscaped());
204 QMessageBox::warning(parent, QObject::tr(
"Qt Linguist"), err);
207 m_srcFileName = fileName;
210 m_contextList.clear();
213 QHash<QString,
int> contexts;
219 for (
const TranslatorMessage &msg : tor.messages()) {
220 if (!contexts.contains(msg.context())) {
221 contexts.insert(msg.context(), m_contextList.size());
222 m_contextList.append(ContextItem(msg.context()));
225 ContextItem *c = contextItem(contexts.value(msg.context()));
227 c->appendToComment(msg.comment());
229 MessageItem tmp(msg);
230 if (msg.type() == TranslatorMessage::Finished)
231 c->incrementFinishedCount();
232 if (msg.type() == TranslatorMessage::Finished || msg.type() == TranslatorMessage::Unfinished) {
233 doCharCounting(tmp.text(), m_srcWords, m_srcChars, m_srcCharsSpc);
234 doCharCounting(tmp.pluralText(), m_srcWords, m_srcChars, m_srcCharsSpc);
235 c->incrementNonobsoleteCount();
237 c->appendMessage(tmp);
249 *langGuessed =
false;
250 QString lang = tor.languageCode();
251 if (lang.isEmpty()) {
252 lang = QFileInfo(fileName).baseName();
253 int pos = lang.indexOf(QLatin1Char(
'_'));
255 lang.remove(0, pos + 1);
261 QLocale::Territory c;
262 Translator::languageAndTerritory(lang, &l, &c);
263 if (l == QLocale::C) {
269 if (!setLanguageAndTerritory(l, c))
270 QMessageBox::warning(parent, QObject::tr(
"Qt Linguist"),
271 tr(
"Linguist does not know the plural rules for '%1'.\n"
272 "Will assume a single universal form.")
273 .arg(m_localizedLanguage));
278 lang = tor.sourceLanguageCode();
279 if (lang.isEmpty()) {
281 c = QLocale::AnyTerritory;
283 Translator::languageAndTerritory(lang, &l, &c);
285 setSourceLanguageAndTerritory(l, c);
292bool DataModel::save(
const QString &fileName, QWidget *parent)
298 tor.setLanguageCode(Translator::makeLanguageCode(m_language, m_territory));
299 tor.setSourceLanguageCode(Translator::makeLanguageCode(m_sourceLanguage, m_sourceTerritory));
305 bool ok = tor.save(fileName, cd, QLatin1String(
"auto"));
308 if (!cd.error().isEmpty())
309 QMessageBox::warning(parent, QObject::tr(
"Qt Linguist"), cd.error());
315 if (!save(newFileName, parent))
317 m_srcFileName = newFileName;
324 QFile file(fileName);
325 if (!file.open(QIODevice::WriteOnly)) {
326 QMessageBox::warning(parent, QObject::tr(
"Qt Linguist"),
327 tr(
"Cannot create '%2': %1").arg(file.errorString()).arg(fileName));
331 QLocale locale(m_language, m_territory);
332 tor.setLanguageCode(locale.name());
340 std::all_of(tor.messages().begin(), tor.messages().end(),
341 [](
const TranslatorMessage &message) {
return !message.id().isEmpty(); });
342 bool ok = saveQM(tor, file, cd);
344 QMessageBox::warning(parent, QObject::tr(
"Qt Linguist"), cd.error());
352 for (
int i = 0; i < text.size(); ++i) {
353 if (text[i].isLetterOrNumber() || text[i] == QLatin1Char(
'_')) {
361 if (!text[i].isSpace())
366bool DataModel::setLanguageAndTerritory(QLocale::Language lang, QLocale::Territory territory)
368 if (m_language == lang && m_territory == territory)
371 m_territory = territory;
373 if (lang == QLocale::C || uint(lang) > uint(QLocale::LastLanguage))
374 lang = QLocale::English;
376 bool ok = getNumerusInfo(lang, territory, &rules, &m_numerusForms, 0);
377 QLocale loc(lang, territory);
380 const bool mentionTerritory = (loc.territory() != territory) || [lang, territory]() {
381 const auto locales = QLocale::matchingLocales(lang, QLocale::AnyScript,
382 QLocale::AnyTerritory);
383 return std::any_of(locales.cbegin(), locales.cend(), [territory](
const QLocale &locale) {
384 return locale.territory() != territory;
387 m_localizedLanguage = mentionTerritory
389 ? tr(
"%1 (%2)").arg(loc.nativeLanguageName(), loc.nativeTerritoryName())
390 : loc.nativeLanguageName();
391 m_countRefNeeds.clear();
392 for (
int i = 0; i < rules.size(); ++i) {
393 m_countRefNeeds.append(!(rules.at(i) == Q_EQ && (i == (rules.size() - 2) || rules.at(i + 2) == (
char)Q_NEWRULE)));
394 while (++i < rules.size() && rules.at(i) != (
char)Q_NEWRULE) {}
396 m_countRefNeeds.append(
true);
398 m_numerusForms.clear();
399 m_numerusForms << tr(
"Universal Form");
401 emit languageChanged();
406void DataModel::setSourceLanguageAndTerritory(QLocale::Language lang, QLocale::Territory territory)
408 if (m_sourceLanguage == lang && m_sourceTerritory == territory)
410 m_sourceLanguage = lang;
411 m_sourceTerritory = territory;
423 bool hasDanger =
false;
424 for (
const QString &trnsl : mi->translations()) {
425 doCharCounting(trnsl, stats.wordsFinished, stats.charsFinished, stats.charsSpacesFinished);
426 hasDanger |= mi->danger();
433 bool hasDanger =
false;
434 for (
const QString &trnsl : mi->translations()) {
435 doCharCounting(trnsl, stats.wordsUnfinished, stats.charsUnfinished, stats.charsSpacesUnfinished);
436 hasDanger |= mi->danger();
447 emit statsChanged(stats);
452 if (m_modified == isModified)
454 m_modified = isModified;
455 emit modifiedChanged();
458QString
DataModel::prettifyPlainFileName(
const QString &fn)
460 static QString workdir = QDir::currentPath() + QLatin1Char(
'/');
462 return QDir::toNativeSeparators(fn.startsWith(workdir) ? fn.mid(workdir.size()) : fn);
467 if (fn.startsWith(QLatin1Char(
'=')))
468 return QLatin1Char(
'=') + prettifyPlainFileName(fn.mid(1));
470 return prettifyPlainFileName(fn);
474
475
476
477
486 return m_context < m_model->m_contextList.size();
505
506
507
508
516 m_nonobsoleteCount(0),
523
524
525
526
533 m_nonobsoleteCount(0)
535 QList<MessageItem *> mList;
536 QList<MessageItem *> eList;
541 m_multiMessageList.append(MultiMessageItem(m));
543 for (
int i = 0; i < oldCount; ++i) {
544 m_messageLists.append(eList);
545 m_writableMessageLists.append(0);
546 m_contextList.append(0);
548 m_messageLists.append(mList);
549 m_writableMessageLists.append(writable ? &m_messageLists.last() : 0);
550 m_contextList.append(ctx);
555 QList<MessageItem *> eList;
558 m_messageLists.append(eList);
559 m_writableMessageLists.append(0);
560 m_contextList.append(0);
566 m_writableMessageLists.last() = &m_messageLists.last();
567 m_contextList.last() = ctx;
573 m_contextList.insert(newPos, m_contextList[oldPos]);
574 m_messageLists.insert(newPos, m_messageLists[oldPos]);
575 m_writableMessageLists.insert(newPos, m_writableMessageLists[oldPos]);
576 removeModel(oldPos < newPos ? oldPos : oldPos + 1);
581 m_contextList.removeAt(pos);
582 m_messageLists.removeAt(pos);
583 m_writableMessageLists.removeAt(pos);
588 m_messageLists.last()[pos] = m;
593 QList<MessageItem *> nullItems = m;
594 for (
int i = 0; i < nullItems.size(); ++i)
596 for (
int i = 0; i < m_messageLists.size() - 1; ++i)
597 m_messageLists[i] += nullItems;
598 m_messageLists.last() += m;
599 for (MessageItem *mi : m)
600 m_multiMessageList.append(MultiMessageItem(mi));
605 for (
int i = 0; i < m_messageLists.size(); ++i)
606 m_messageLists[i].removeAt(pos);
607 m_multiMessageList.removeAt(pos);
612 for (
int i = 0; i < m_messageLists.size(); ++i)
613 if (m_messageLists[i][msgIdx] && !m_messageLists[i][msgIdx]->isObsolete())
622 if (m->text() == sourcetext && m->comment() == comment)
639
640
641
642
661 for (
int i = 0; i < 7; ++i)
662 m_colors[i] = QColor(paletteRGBs[i][0], paletteRGBs[i][1], paletteRGBs[i][2]);
664 m_bitmap = QBitmap(8, 8);
666 QPainter p(&m_bitmap);
667 for (
int j = 0; j < 8; ++j)
668 for (
int k = 0; k < 8; ++k)
675 qDeleteAll(m_dataModels);
680 QBrush brush(m_colors[model % 7]);
681 if (!isModelWritable(model))
682 brush.setTexture(m_bitmap);
697 if (mc->findMessage(m->text(), m->comment()) >= 0)
707 if (
ContextItem *c = dm->findContext(mc->context())) {
710 if (c->findMessage(m->text(), m->comment()))
717 return newRatio + oldRatio > 90;
723 m_msgModel->beginInsertColumns(QModelIndex(), insCol, insCol);
724 m_dataModels.append(dm);
726 m_msgModel->beginInsertColumns(m_msgModel->createIndex(j, 0), insCol, insCol);
727 m_multiContextList[j].appendEmptyModel();
728 m_msgModel->endInsertColumns();
730 m_msgModel->endInsertColumns();
731 int appendedContexts = 0;
734 int mcx = findContextIndex(c->context());
737 mc->assignLastModel(c, readWrite);
738 QList<MessageItem *> appendItems;
743 if (!m->id().isEmpty())
744 msgIdx = mc->findMessageById(m->id());
747 msgIdx = mc->findMessage(m->text(), m->comment());
750 mc->putMessageItem(msgIdx, m);
754 if (!appendItems.isEmpty()) {
756 m_msgModel->beginInsertRows(m_msgModel->createIndex(mcx, 0),
757 msgCnt, msgCnt + appendItems.size() - 1);
758 mc->appendMessageItems(appendItems);
759 m_msgModel->endInsertRows();
760 m_numMessages += appendItems.size();
763 m_multiContextList << MultiContextItem(modelCount() - 1, c, readWrite);
768 if (appendedContexts) {
771 m_msgModel->beginInsertRows(QModelIndex(),
773 m_msgModel->endInsertRows();
777 connect(dm, &DataModel::modifiedChanged,
778 this, &MultiDataModel::onModifiedChanged);
781 connect(dm, &DataModel::statsChanged,
782 this, &MultiDataModel::statsChanged);
783 emit modelAppended();
788 if (m_dataModels.size() == 1) {
792 int delCol = model + 1;
793 m_msgModel->beginRemoveColumns(QModelIndex(), delCol, delCol);
794 for (
int i = m_multiContextList.size(); --i >= 0;) {
795 m_msgModel->beginRemoveColumns(m_msgModel->createIndex(i, 0), delCol, delCol);
796 m_multiContextList[i].removeModel(model);
797 m_msgModel->endRemoveColumns();
799 delete m_dataModels.takeAt(model);
800 m_msgModel->endRemoveColumns();
801 emit modelDeleted(model);
802 for (
int i = m_multiContextList.size(); --i >= 0;) {
804 QModelIndex contextIdx = m_msgModel->createIndex(i, 0);
807 m_msgModel->beginRemoveRows(contextIdx, j, j);
808 mc.removeMultiMessageItem(j);
809 m_msgModel->endRemoveRows();
813 m_msgModel->beginRemoveRows(QModelIndex(), i, i);
814 m_multiContextList.removeAt(i);
815 m_msgModel->endRemoveRows();
824 m_msgModel->beginResetModel();
828 qDeleteAll(m_dataModels);
829 m_dataModels.clear();
830 m_multiContextList.clear();
831 m_msgModel->endResetModel();
832 emit allModelsDeleted();
839 int delPos = oldPos < newPos ? oldPos : oldPos + 1;
840 m_dataModels.insert(newPos, m_dataModels[oldPos]);
841 m_dataModels.removeAt(delPos);
842 for (
int i = 0; i < m_multiContextList.size(); ++i)
843 m_multiContextList[i].moveModel(oldPos, newPos);
850 for (
const QString &name : names)
851 out << DataModel::prettifyFileName(name);
860 if (names.size() < 2)
861 return names.first();
863 QString prefix = names.first();
864 if (prefix.startsWith(QLatin1Char(
'=')))
866 QString suffix = prefix;
867 for (
int i = 1; i < names.size(); ++i) {
868 QString fn = names[i];
869 if (fn.startsWith(QLatin1Char(
'=')))
871 for (
int j = 0; j < prefix.size(); ++j)
872 if (fn[j] != prefix[j]) {
873 if (j < prefix.size()) {
874 while (j > 0 && prefix[j - 1].isLetterOrNumber())
880 int fnl = fn.size() - 1;
881 int sxl = suffix.size() - 1;
882 for (
int k = 0; k <= sxl; ++k)
883 if (fn[fnl - k] != suffix[sxl - k]) {
885 while (k > 0 && suffix[sxl - k + 1].isLetterOrNumber())
887 if (prefix.size() + k > fnl)
889 suffix.remove(0, sxl - k + 1);
894 QString ret = prefix + QLatin1Char(
'{');
895 int pxl = prefix.size();
896 int sxl = suffix.size();
897 for (
int j = 0; j < names.size(); ++j) {
899 ret += QLatin1Char(
',');
901 QString fn = names[j];
902 if (fn.startsWith(QLatin1Char(
'='))) {
903 ret += QLatin1Char(
'=');
906 ret += fn.mid(off, fn.size() - sxl - off);
908 ret += QLatin1Char(
'}') + suffix;
915 for (DataModel *dm : m_dataModels)
916 names << (dm->isWritable() ? QString() : QString::fromLatin1(
"=")) + dm->srcFileName(pretty);
922 return condenseFileNames(srcFileNames(pretty));
927 for (
const DataModel *mdl : m_dataModels)
928 if (mdl->isModified())
936 if (modified != m_modified) {
937 emit modifiedChanged(modified);
938 m_modified = modified;
945 while (sender() != m_dataModels[i])
947 emit languageChanged(i);
952 for (
int i = 0; i < m_dataModels.size(); ++i)
953 if (m_dataModels[i]->srcFileName() == name)
960 for (
int i = 0; i < m_multiContextList.size(); ++i) {
962 if (mc.context() == context)
970 for (
int i = 0; i < m_multiContextList.size(); ++i) {
972 if (mc.context() == context)
993 if (translation == m->translation())
995 m->setTranslation(translation);
997 emit translationChanged(index);
1009 mm->decrementUnfinishedCount();
1011 incrementFinishedCount();
1012 mc->incrementFinishedCount();
1013 emit multiContextDataChanged(index);
1015 c->incrementFinishedCount();
1017 c->incrementFinishedDangerCount();
1018 c->decrementUnfinishedDangerCount();
1021 emit contextDataChanged(index);
1023 emit contextDataChanged(index);
1025 emit messageDataChanged(index);
1029 mm->incrementUnfinishedCount();
1031 decrementFinishedCount();
1032 mc->decrementFinishedCount();
1033 emit multiContextDataChanged(index);
1035 c->decrementFinishedCount();
1037 c->decrementFinishedDangerCount();
1038 c->incrementUnfinishedDangerCount();
1041 emit contextDataChanged(index);
1043 emit contextDataChanged(index);
1045 emit messageDataChanged(index);
1056 c->incrementFinishedDangerCount();
1058 emit contextDataChanged(index);
1060 c->incrementUnfinishedDangerCount();
1062 emit contextDataChanged(index);
1064 emit messageDataChanged(index);
1068 c->decrementFinishedDangerCount();
1070 emit contextDataChanged(index);
1072 c->decrementUnfinishedDangerCount();
1074 emit contextDataChanged(index);
1076 emit messageDataChanged(index);
1083 for (
int i = 0; i < m_multiContextList.size(); ++i) {
1088 mm->incrementNonnullCount();
1092 mc.incrementEditableCount();
1093 incrementEditableCount();
1095 mc.incrementFinishedCount();
1096 incrementFinishedCount();
1098 mm->incrementUnfinishedCount();
1102 mc.decrementFinishedCount();
1103 decrementFinishedCount();
1105 mm->incrementUnfinishedCount();
1107 mm->incrementEditableCount();
1109 mc.incrementNonobsoleteCount();
1110 mm->incrementNonobsoleteCount();
1116void MultiDataModel::updateCountsOnRemove(
int model,
bool writable)
1118 for (
int i = 0; i < m_multiContextList.size(); ++i) {
1123 mm->decrementNonnullCount();
1125 mm->decrementNonobsoleteCount();
1126 mc.decrementNonobsoleteCount();
1128 mm->decrementEditableCount();
1130 mc.decrementEditableCount();
1131 decrementEditableCount();
1133 mc.decrementFinishedCount();
1134 decrementFinishedCount();
1136 mm->decrementUnfinishedCount();
1139 mm->decrementUnfinishedCount();
1141 mc.incrementFinishedCount();
1142 incrementFinishedCount();
1152
1153
1154
1155
1174 return m_context < m_dataModel->m_multiContextList.size();
1184
1185
1186
1187
1192 data->m_msgModel =
this;
1193 connect(m_data, &MultiDataModel::multiContextDataChanged,
1194 this, &MessageModel::multiContextItemChanged);
1203 if (!parent.isValid())
1204 return createIndex(row, column);
1205 if (!parent.internalId())
1206 return createIndex(row, column, parent.row() + 1);
1207 return QModelIndex();
1212 if (index.internalId())
1213 return createIndex(index.internalId() - 1, 0);
1214 return QModelIndex();
1219 QModelIndex idx = createIndex(index.context(), m_data->modelCount() + 2);
1220 emit dataChanged(idx, idx);
1225 QModelIndex idx = createIndex(index.context(), index.model() + 1);
1226 emit dataChanged(idx, idx);
1231 QModelIndex idx = createIndex(index.message(), index.model() + 1, index.context() + 1);
1232 emit dataChanged(idx, idx);
1244 if (!parent.isValid())
1246 if (!parent.internalId())
1253 if (!parent.isValid())
1260 static QVariant pxOn =
1261 QVariant::fromValue(QPixmap(QLatin1String(
":/images/s_check_on.png")));
1262 static QVariant pxOff =
1263 QVariant::fromValue(QPixmap(QLatin1String(
":/images/s_check_off.png")));
1264 static QVariant pxObsolete =
1265 QVariant::fromValue(QPixmap(QLatin1String(
":/images/s_check_obsolete.png")));
1266 static QVariant pxDanger =
1267 QVariant::fromValue(QPixmap(QLatin1String(
":/images/s_check_danger.png")));
1268 static QVariant pxWarning =
1269 QVariant::fromValue(QPixmap(QLatin1String(
":/images/s_check_warning.png")));
1270 static QVariant pxEmpty =
1271 QVariant::fromValue(QPixmap(QLatin1String(
":/images/s_check_empty.png")));
1273 int row = index.row();
1274 int column = index.column() - 1;
1280 if (role == Qt::ToolTipRole && column < numLangs) {
1281 return tr(
"Completion status for %1").arg(m_data
->model(column
)->localizedLanguage());
1282 }
else if (index.internalId()) {
1284 int crow = index.internalId() - 1;
1289 if (role == Qt::DisplayRole || (role == Qt::ToolTipRole && column == numLangs)) {
1290 switch (column - numLangs) {
1294 if (msgItem->text().isEmpty()) {
1295 if (mci->context().isEmpty())
1296 return tr(
"<file header>");
1298 return tr(
"<context comment>");
1300 return msgItem->text().simplified();
1306 else if (role == Qt::DecorationRole && column < numLangs) {
1310 if (msgItem->translation().isEmpty())
1325 else if (role == SortRole) {
1326 switch (column - numLangs) {
1333 int rslt = !msgItem->translation().isEmpty();
1345 else if (role == Qt::ForegroundRole && column > 0
1346 && mci->multiMessageItem(row)->isObsolete()) {
1347 return QBrush(Qt::darkGray);
1349 else if (role == Qt::ForegroundRole && column == numLangs
1350 && mci->multiMessageItem(row)->text().isEmpty()) {
1351 return QBrush(QColor(0, 0xa0, 0xa0));
1353 else if (role == Qt::BackgroundRole) {
1354 if (column < numLangs && numLangs != 1)
1355 return m_data->brushForModel(column);
1364 if (role == Qt::DisplayRole || role == Qt::ToolTipRole) {
1365 switch (column - numLangs) {
1368 if (mci->context().isEmpty())
1369 return tr(
"<unnamed context>");
1370 return mci->context().simplified();
1374 if (role == Qt::ToolTipRole) {
1375 return tr(
"%n unfinished message(s) left.", 0,
1378 return QString::asprintf(
"%d/%d", mci->getNumFinished(), mci->getNumEditable());
1384 else if (role == Qt::DecorationRole && column < numLangs) {
1394 else if (role == SortRole) {
1395 switch (column - numLangs) {
1397 return mci->context().simplified();
1403 int percent = totalItems ? (100 * contextItem
->finishedCount()) / totalItems : 100;
1404 int rslt = percent * (((1 << 28) - 1) / 100) + totalItems;
1420 else if (role == Qt::ForegroundRole && column >= numLangs
1421 && m_data->multiContextItem(row)->isObsolete()) {
1422 return QBrush(Qt::darkGray);
1424 else if (role == Qt::ForegroundRole && column == numLangs
1425 && m_data->multiContextItem(row)->context().isEmpty()) {
1426 return QBrush(QColor(0, 0xa0, 0xa0));
1428 else if (role == Qt::BackgroundRole) {
1429 if (column < numLangs && numLangs != 1) {
1430 QBrush brush = m_data->brushForModel(column);
1432 brush.setColor(brush.color().darker(108));
1443 Q_ASSERT(index.isValid());
1444 Q_ASSERT(index.internalId());
1445 return MultiDataIndex(model, index.internalId() - 1, index.row());
MessageItem * findMessage(const QString &sourcetext, const QString &comment) const
int finishedDangerCount() const
int finishedCount() const
int unfinishedDangerCount() const
ContextItem(const QString &context)
int nonobsoleteCount() const
MessageItem * messageItem(int i) const
TranslatorSaveMode m_saveMode
DataIndex(int context, int message)
MessageItem * current() const
DataModelIterator(DataModel *model, int contextNo=0, int messageNo=0)
bool load(const QString &fileName, bool *langGuessed, QWidget *parent)
void doCharCounting(const QString &text, int &trW, int &trC, int &trCS)
bool saveAs(const QString &newFileName, QWidget *parent)
ContextItem * contextItem(int index) const
MessageItem * messageItem(const DataIndex &index) const
bool isWellMergeable(const DataModel *other) const
void setModified(bool dirty)
ContextItem * findContext(const QString &context) const
MessageItem * findMessage(const QString &context, const QString &sourcetext, const QString &comment) const
bool release(const QString &fileName, bool verbose, bool ignoreUnfinished, TranslatorSaveMode mode, QWidget *parent)
void setWritable(bool writable)
QStringList normalizedTranslations(const MessageItem &m) const
bool compare(const QString &findText, bool matchSubstring, Qt::CaseSensitivity cs) const
const TranslatorMessage & message() const
void setDanger(bool danger)
bool isUnfinished() const
TranslatorMessage::Type type() const
void setType(TranslatorMessage::Type type)
QModelIndex modelIndex(const MultiDataIndex &index)
QModelIndex parent(const QModelIndex &index) const override
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
Returns the index of the item in the model specified by the given row, column and parent index.
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
Returns the data stored under the given role for the item referred to by the index.
MessageModel(QObject *parent, MultiDataModel *data)
MultiDataIndex dataIndex(const QModelIndex &index, int model) const
int rowCount(const QModelIndex &parent=QModelIndex()) const override
Returns the number of rows under the given parent.
int columnCount(const QModelIndex &parent=QModelIndex()) const override
Returns the number of columns for the children of the given parent.
MultiDataIndex(int model, int context, int message)
MultiDataModelIterator(MultiDataModel *model, int modelNo, int contextNo=0, int messageNo=0)
MessageItem * current() const
QStringList srcFileNames(bool pretty=false) const
void append(DataModel *dm, bool readWrite)
MessageItem * messageItem(const MultiDataIndex &index, int model) const
void setModified(int model, bool dirty)
MultiContextItem * findContext(const QString &context) const
QString condensedSrcFileNames(bool pretty=false) const
QBrush brushForModel(int model) const
int isFileLoaded(const QString &name) const
void setTranslation(const MultiDataIndex &index, const QString &translation)
void setDanger(const MultiDataIndex &index, bool danger)
bool isModelWritable(int model) const
void contextDataChanged(const MultiDataIndex &index)
MultiContextItem * multiContextItem(int ctxIdx) const
MessageItem * messageItem(const MultiDataIndex &index) const
void setFinished(const MultiDataIndex &index, bool finished)
void messageDataChanged(const MultiDataIndex &index)
bool isWellMergeable(const DataModel *dm) const
void moveModel(int oldPos, int newPos)
int findContextIndex(const QString &context) const
LocationsType locationsType() const
void setExtras(const ExtraData &extras)
void append(const TranslatorMessage &msg)
void setLocationsType(LocationsType lt)
Duplicates resolveDuplicates()
void normalizeTranslations(ConversionData &cd)
const ExtraData & extras() const
static const uchar paletteRGBs[7][3]
static int calcMergeScore(const DataModel *one, const DataModel *two)
int getNumEditable() const
ContextItem * contextItem(int model) const
int getNumFinished() const
MultiContextItem(int oldCount, ContextItem *ctx, bool writable)
int findMessageById(const QString &id) const
MessageItem * messageItem(int model, int msgIdx) const
MultiMessageItem * multiMessageItem(int msgIdx) const
int firstNonobsoleteMessageIndex(int msgIdx) const
int findMessage(const QString &sourcetext, const QString &comment) const
int countUnfinished() const
MultiMessageItem(const MessageItem *m)
int countEditable() const
bool isUnfinished() const
int unfinishedMsgNoDanger
int translatedMsgNoDanger