1 | // Copyright (C) 2016 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 |
3 | |
4 | #include "formpreviewview.h" |
5 | #include "messagemodel.h" |
6 | |
7 | #include <quiloader.h> |
8 | |
9 | #include <QtWidgets/QApplication> |
10 | #include <QtWidgets/QFontComboBox> |
11 | #include <QtWidgets/QFrame> |
12 | #include <QtWidgets/QGridLayout> |
13 | #include <QtWidgets/QListWidget> |
14 | #include <QtWidgets/QMdiArea> |
15 | #include <QtWidgets/QMdiSubWindow> |
16 | #include <QtWidgets/QMenu> |
17 | #include <QtWidgets/QStackedLayout> |
18 | #include <QtWidgets/QStackedWidget> |
19 | #include <QtWidgets/QTableWidget> |
20 | #include <QtWidgets/QTabWidget> |
21 | #include <QtWidgets/QToolBox> |
22 | #include <QtWidgets/QTreeWidget> |
23 | #include <QtWidgets/QScrollArea> |
24 | |
25 | #include <QtGui/QAction> |
26 | |
27 | #include <QtCore/QDebug> |
28 | #include <QtCore/QTime> |
29 | |
30 | QT_BEGIN_NAMESPACE |
31 | |
32 | #if defined(Q_CC_SUN) || defined(Q_CC_HPACC) || defined(Q_CC_XLC) |
33 | size_t qHash(const QUiTranslatableStringValue &tsv) |
34 | #else |
35 | static size_t qHash(const QUiTranslatableStringValue &tsv) |
36 | #endif |
37 | { |
38 | return qHash(key: tsv.value()) ^ qHash(key: tsv.qualifier()); |
39 | } |
40 | |
41 | static bool operator==(const QUiTranslatableStringValue &tsv1, const QUiTranslatableStringValue &tsv2) |
42 | { |
43 | return tsv1.value() == tsv2.value() && tsv1.qualifier() == tsv2.qualifier(); |
44 | } |
45 | |
46 | #define INSERT_TARGET(_tsv, _type, _target, _prop) \ |
47 | do { \ |
48 | target.type = _type; \ |
49 | target.target._target; \ |
50 | target.prop._prop; \ |
51 | (*targets)[qvariant_cast<QUiTranslatableStringValue>(_tsv)].append(target); \ |
52 | } while (0) |
53 | |
54 | static void registerTreeItem(QTreeWidgetItem *item, TargetsHash *targets) |
55 | { |
56 | const QUiItemRolePair *irs = QFormInternal::qUiItemRoles; |
57 | |
58 | int cnt = item->columnCount(); |
59 | for (int i = 0; i < cnt; ++i) { |
60 | for (unsigned j = 0; irs[j].shadowRole >= 0; j++) { |
61 | QVariant v = item->data(column: i, role: irs[j].shadowRole); |
62 | if (v.isValid()) { |
63 | TranslatableEntry target; |
64 | target.prop.treeIndex.column = i; |
65 | INSERT_TARGET(v, TranslatableTreeWidgetItem, treeWidgetItem = item, treeIndex.index = j); |
66 | } |
67 | } |
68 | } |
69 | |
70 | cnt = item->childCount(); |
71 | for (int j = 0; j < cnt; ++j) |
72 | registerTreeItem(item: item->child(index: j), targets); |
73 | } |
74 | |
75 | #define REGISTER_ITEM_CORE(item, propType, targetName) \ |
76 | const QUiItemRolePair *irs = QFormInternal::qUiItemRoles; \ |
77 | for (unsigned j = 0; irs[j].shadowRole >= 0; j++) { \ |
78 | QVariant v = item->data(irs[j].shadowRole); \ |
79 | if (v.isValid()) \ |
80 | INSERT_TARGET(v, propType, targetName = item, index = j); \ |
81 | } |
82 | |
83 | static void registerListItem(QListWidgetItem *item, TargetsHash *targets) |
84 | { |
85 | TranslatableEntry target; |
86 | REGISTER_ITEM_CORE(item, TranslatableListWidgetItem, listWidgetItem); |
87 | } |
88 | |
89 | static void registerTableItem(QTableWidgetItem *item, TargetsHash *targets) |
90 | { |
91 | if (!item) |
92 | return; |
93 | |
94 | TranslatableEntry target; |
95 | REGISTER_ITEM_CORE(item, TranslatableTableWidgetItem, tableWidgetItem); |
96 | } |
97 | |
98 | #define REGISTER_SUBWIDGET_PROP(mainWidget, propType, propName) \ |
99 | do { \ |
100 | QVariant v = mainWidget->widget(i)->property(propName); \ |
101 | if (v.isValid()) \ |
102 | INSERT_TARGET(v, propType, object = mainWidget, index = i); \ |
103 | } while (0) |
104 | |
105 | static void buildTargets(QObject *o, TargetsHash *targets) |
106 | { |
107 | TranslatableEntry target; |
108 | |
109 | const auto propNames = o->dynamicPropertyNames(); |
110 | for (const QByteArray &prop : propNames) { |
111 | if (prop.startsWith(PROP_GENERIC_PREFIX)) { |
112 | const QByteArray propName = prop.mid(index: sizeof(PROP_GENERIC_PREFIX) - 1); |
113 | INSERT_TARGET(o->property(prop), |
114 | TranslatableProperty, object = o, name = qstrdup(propName.data())); |
115 | } |
116 | } |
117 | if (0) { |
118 | #ifndef QT_NO_TABWIDGET |
119 | } else if (QTabWidget *tabw = qobject_cast<QTabWidget*>(object: o)) { |
120 | const int cnt = tabw->count(); |
121 | for (int i = 0; i < cnt; ++i) { |
122 | REGISTER_SUBWIDGET_PROP(tabw, TranslatableTabPageText, PROP_TABPAGETEXT); |
123 | # ifndef QT_NO_TOOLTIP |
124 | REGISTER_SUBWIDGET_PROP(tabw, TranslatableTabPageToolTip, PROP_TABPAGETOOLTIP); |
125 | # endif |
126 | # ifndef QT_NO_WHATSTHIS |
127 | REGISTER_SUBWIDGET_PROP(tabw, TranslatableTabPageWhatsThis, PROP_TABPAGEWHATSTHIS); |
128 | # endif |
129 | } |
130 | #endif |
131 | #ifndef QT_NO_TOOLBOX |
132 | } else if (QToolBox *toolw = qobject_cast<QToolBox*>(object: o)) { |
133 | const int cnt = toolw->count(); |
134 | for (int i = 0; i < cnt; ++i) { |
135 | REGISTER_SUBWIDGET_PROP(toolw, TranslatableToolItemText, PROP_TOOLITEMTEXT); |
136 | # ifndef QT_NO_TOOLTIP |
137 | REGISTER_SUBWIDGET_PROP(toolw, TranslatableToolItemToolTip, PROP_TOOLITEMTOOLTIP); |
138 | # endif |
139 | } |
140 | #endif |
141 | #ifndef QT_NO_COMBOBOX |
142 | } else if (QComboBox *combow = qobject_cast<QComboBox*>(object: o)) { |
143 | if (!qobject_cast<QFontComboBox*>(object: o)) { |
144 | const int cnt = combow->count(); |
145 | for (int i = 0; i < cnt; ++i) { |
146 | const QVariant v = combow->itemData(index: i, role: Qt::DisplayPropertyRole); |
147 | if (v.isValid()) |
148 | INSERT_TARGET(v, TranslatableComboBoxItem, comboBox = combow, index = i); |
149 | } |
150 | } |
151 | #endif |
152 | #ifndef QT_NO_LISTWIDGET |
153 | } else if (QListWidget *listw = qobject_cast<QListWidget*>(object: o)) { |
154 | const int cnt = listw->count(); |
155 | for (int i = 0; i < cnt; ++i) |
156 | registerListItem(item: listw->item(row: i), targets); |
157 | #endif |
158 | #ifndef QT_NO_TABLEWIDGET |
159 | } else if (QTableWidget *tablew = qobject_cast<QTableWidget*>(object: o)) { |
160 | const int row_cnt = tablew->rowCount(); |
161 | const int col_cnt = tablew->columnCount(); |
162 | for (int j = 0; j < col_cnt; ++j) |
163 | registerTableItem(item: tablew->horizontalHeaderItem(column: j), targets); |
164 | for (int i = 0; i < row_cnt; ++i) { |
165 | registerTableItem(item: tablew->verticalHeaderItem(row: i), targets); |
166 | for (int j = 0; j < col_cnt; ++j) |
167 | registerTableItem(item: tablew->item(row: i, column: j), targets); |
168 | } |
169 | #endif |
170 | #ifndef QT_NO_TREEWIDGET |
171 | } else if (QTreeWidget *treew = qobject_cast<QTreeWidget*>(object: o)) { |
172 | if (QTreeWidgetItem *item = treew->headerItem()) |
173 | registerTreeItem(item, targets); |
174 | const int cnt = treew->topLevelItemCount(); |
175 | for (int i = 0; i < cnt; ++i) |
176 | registerTreeItem(item: treew->topLevelItem(index: i), targets); |
177 | #endif |
178 | } |
179 | for (QObject *co : o->children()) |
180 | buildTargets(o: co, targets); |
181 | } |
182 | |
183 | static void destroyTargets(TargetsHash *targets) |
184 | { |
185 | for (const auto &targetList : std::as_const(t&: *targets)) |
186 | for (const TranslatableEntry &target : targetList) |
187 | if (target.type == TranslatableProperty) |
188 | delete target.prop.name; |
189 | targets->clear(); |
190 | } |
191 | |
192 | static void retranslateTarget(const TranslatableEntry &target, const QString &text) |
193 | { |
194 | switch (target.type) { |
195 | case TranslatableProperty: |
196 | target.target.object->setProperty(name: target.prop.name, value: text); |
197 | break; |
198 | #ifndef QT_NO_TABWIDGET |
199 | case TranslatableTabPageText: |
200 | target.target.tabWidget->setTabText(index: target.prop.index, text); |
201 | break; |
202 | # ifndef QT_NO_TOOLTIP |
203 | case TranslatableTabPageToolTip: |
204 | target.target.tabWidget->setTabToolTip(index: target.prop.index, tip: text); |
205 | break; |
206 | # endif |
207 | # ifndef QT_NO_WHATSTHIS |
208 | case TranslatableTabPageWhatsThis: |
209 | target.target.tabWidget->setTabWhatsThis(index: target.prop.index, text); |
210 | break; |
211 | # endif |
212 | #endif // QT_NO_TABWIDGET |
213 | #ifndef QT_NO_TOOLBOX |
214 | case TranslatableToolItemText: |
215 | target.target.toolBox->setItemText(index: target.prop.index, text); |
216 | break; |
217 | # ifndef QT_NO_TOOLTIP |
218 | case TranslatableToolItemToolTip: |
219 | target.target.toolBox->setItemToolTip(index: target.prop.index, toolTip: text); |
220 | break; |
221 | # endif |
222 | #endif // QT_NO_TOOLBOX |
223 | #ifndef QT_NO_COMBOBOX |
224 | case TranslatableComboBoxItem: |
225 | target.target.comboBox->setItemText(index: target.prop.index, text); |
226 | break; |
227 | #endif |
228 | #ifndef QT_NO_LISTWIDGET |
229 | case TranslatableListWidgetItem: |
230 | target.target.listWidgetItem->setData(role: target.prop.index, value: text); |
231 | break; |
232 | #endif |
233 | #ifndef QT_NO_TABLEWIDGET |
234 | case TranslatableTableWidgetItem: |
235 | target.target.tableWidgetItem->setData(role: target.prop.index, value: text); |
236 | break; |
237 | #endif |
238 | #ifndef QT_NO_TREEWIDGET |
239 | case TranslatableTreeWidgetItem: |
240 | target.target.treeWidgetItem->setData(column: target.prop.treeIndex.column, role: target.prop.treeIndex.index, value: text); |
241 | break; |
242 | #endif |
243 | } |
244 | } |
245 | |
246 | static void retranslateTargets( |
247 | const QList<TranslatableEntry> &targets, const QUiTranslatableStringValue &tsv, |
248 | const DataModel *dataModel, const QString &className) |
249 | { |
250 | QString sourceText = QString::fromUtf8(ba: tsv.value()); |
251 | QString text; |
252 | if (MessageItem *msg = dataModel->findMessage( |
253 | context: className, sourcetext: sourceText, comment: QString::fromUtf8(ba: tsv.qualifier()))) |
254 | text = msg->translation(); |
255 | if (text.isEmpty() && !tsv.value().isEmpty()) |
256 | text = QLatin1Char('#') + sourceText; |
257 | |
258 | for (const TranslatableEntry &target : targets) |
259 | retranslateTarget(target, text); |
260 | } |
261 | |
262 | static void bringToFront(QWidget *w) |
263 | { |
264 | for (; QWidget *pw = w->parentWidget(); w = pw) { |
265 | #ifndef QT_NO_STACKEDWIDGET |
266 | if (QStackedWidget *stack = qobject_cast<QStackedWidget *>(object: pw)) { |
267 | #ifndef QT_NO_TABWIDGET |
268 | // Updating QTabWidget's embedded QStackedWidget does not update its |
269 | // QTabBar, so handle tab widgets explicitly. |
270 | if (QTabWidget *tab = qobject_cast<QTabWidget *>(object: stack->parent())) |
271 | tab->setCurrentWidget(w); |
272 | else |
273 | #endif |
274 | stack->setCurrentWidget(w); |
275 | continue; |
276 | } |
277 | #endif |
278 | #ifndef QT_NO_TOOLBOX |
279 | if (QScrollArea *sv = qobject_cast<QScrollArea *>(object: pw)) { |
280 | if (QToolBox *tb = qobject_cast<QToolBox *>(object: sv->parent())) |
281 | tb->setCurrentWidget(w); |
282 | } |
283 | #endif |
284 | } |
285 | } |
286 | |
287 | static void highlightTreeWidgetItem(QTreeWidgetItem *item, int col, bool on) |
288 | { |
289 | QVariant br = item->data(column: col, role: Qt::BackgroundRole + 500); |
290 | QVariant fr = item->data(column: col, role: Qt::ForegroundRole + 500); |
291 | if (on) { |
292 | if (!br.isValid() && !fr.isValid()) { |
293 | item->setData(column: col, role: Qt::BackgroundRole + 500, value: item->data(column: col, role: Qt::BackgroundRole)); |
294 | item->setData(column: col, role: Qt::ForegroundRole + 500, value: item->data(column: col, role: Qt::ForegroundRole)); |
295 | QPalette pal = qApp->palette(); |
296 | item->setData(column: col, role: Qt::BackgroundRole, value: pal.color(cr: QPalette::Dark)); |
297 | item->setData(column: col, role: Qt::ForegroundRole, value: pal.color(cr: QPalette::Light)); |
298 | } |
299 | } else { |
300 | if (br.isValid() || fr.isValid()) { |
301 | item->setData(column: col, role: Qt::BackgroundRole, value: br); |
302 | item->setData(column: col, role: Qt::ForegroundRole, value: fr); |
303 | item->setData(column: col, role: Qt::BackgroundRole + 500, value: QVariant()); |
304 | item->setData(column: col, role: Qt::ForegroundRole + 500, value: QVariant()); |
305 | } |
306 | } |
307 | } |
308 | |
309 | template <class T> |
310 | static void highlightWidgetItem(T *item, bool on) |
311 | { |
312 | QVariant br = item->data(Qt::BackgroundRole + 500); |
313 | QVariant fr = item->data(Qt::ForegroundRole + 500); |
314 | if (on) { |
315 | if (!br.isValid() && !fr.isValid()) { |
316 | item->setData(Qt::BackgroundRole + 500, item->data(Qt::BackgroundRole)); |
317 | item->setData(Qt::ForegroundRole + 500, item->data(Qt::ForegroundRole)); |
318 | QPalette pal = qApp->palette(); |
319 | item->setData(Qt::BackgroundRole, pal.color(cr: QPalette::Dark)); |
320 | item->setData(Qt::ForegroundRole, pal.color(cr: QPalette::Light)); |
321 | } |
322 | } else { |
323 | if (br.isValid() || fr.isValid()) { |
324 | item->setData(Qt::BackgroundRole, br); |
325 | item->setData(Qt::ForegroundRole, fr); |
326 | item->setData(Qt::BackgroundRole + 500, QVariant()); |
327 | item->setData(Qt::ForegroundRole + 500, QVariant()); |
328 | } |
329 | } |
330 | } |
331 | |
332 | #define AUTOFILL_BACKUP_PROP "_q_linguist_autoFillBackup" |
333 | #define PALETTE_BACKUP_PROP "_q_linguist_paletteBackup" |
334 | #define FONT_BACKUP_PROP "_q_linguist_fontBackup" |
335 | |
336 | static void highlightWidget(QWidget *w, bool on); |
337 | |
338 | static void highlightAction(QAction *a, bool on) |
339 | { |
340 | QVariant bak = a->property(FONT_BACKUP_PROP); |
341 | if (on) { |
342 | if (!bak.isValid()) { |
343 | QFont fnt = qApp->font(); |
344 | a->setProperty(FONT_BACKUP_PROP, value: QVariant::fromValue(value: a->font().resolve(fnt))); |
345 | fnt.setBold(true); |
346 | fnt.setItalic(true); |
347 | a->setFont(fnt); |
348 | } |
349 | } else { |
350 | if (bak.isValid()) { |
351 | a->setFont(qvariant_cast<QFont>(v: bak)); |
352 | a->setProperty(FONT_BACKUP_PROP, value: QVariant()); |
353 | } |
354 | } |
355 | for (QObject *o : a->associatedObjects()) { |
356 | if (QWidget *w = qobject_cast<QWidget *>(o)) |
357 | highlightWidget(w, on); |
358 | } |
359 | } |
360 | |
361 | static void highlightWidget(QWidget *w, bool on) |
362 | { |
363 | QVariant bak = w->property(PALETTE_BACKUP_PROP); |
364 | if (on) { |
365 | if (!bak.isValid()) { |
366 | QPalette pal = qApp->palette(); |
367 | for (QObject *co : w->children()) |
368 | if (QWidget *cw = qobject_cast<QWidget *>(o: co)) |
369 | cw->setPalette(cw->palette().resolve(other: pal)); |
370 | w->setProperty(PALETTE_BACKUP_PROP, value: QVariant::fromValue(value: w->palette().resolve(other: pal))); |
371 | w->setProperty(AUTOFILL_BACKUP_PROP, value: QVariant::fromValue(value: w->autoFillBackground())); |
372 | QColor col1 = pal.color(cr: QPalette::Dark); |
373 | QColor col2 = pal.color(cr: QPalette::Light); |
374 | pal.setColor(acr: QPalette::Base, acolor: col1); |
375 | pal.setColor(acr: QPalette::Window, acolor: col1); |
376 | pal.setColor(acr: QPalette::Button, acolor: col1); |
377 | pal.setColor(acr: QPalette::Text, acolor: col2); |
378 | pal.setColor(acr: QPalette::WindowText, acolor: col2); |
379 | pal.setColor(acr: QPalette::ButtonText, acolor: col2); |
380 | pal.setColor(acr: QPalette::BrightText, acolor: col2); |
381 | w->setPalette(pal); |
382 | w->setAutoFillBackground(true); |
383 | } |
384 | } else { |
385 | if (bak.isValid()) { |
386 | w->setPalette(qvariant_cast<QPalette>(v: bak)); |
387 | w->setAutoFillBackground(qvariant_cast<bool>(v: w->property(AUTOFILL_BACKUP_PROP))); |
388 | w->setProperty(PALETTE_BACKUP_PROP, value: QVariant()); |
389 | w->setProperty(AUTOFILL_BACKUP_PROP, value: QVariant()); |
390 | } |
391 | } |
392 | if (QMenu *m = qobject_cast<QMenu *>(object: w)) |
393 | if (m->menuAction()) |
394 | highlightAction(a: m->menuAction(), on); |
395 | } |
396 | |
397 | static void highlightTarget(const TranslatableEntry &target, bool on) |
398 | { |
399 | switch (target.type) { |
400 | case TranslatableProperty: |
401 | if (QAction *a = qobject_cast<QAction *>(object: target.target.object)) { |
402 | highlightAction(a, on); |
403 | } else if (QWidget *w = qobject_cast<QWidget *>(o: target.target.object)) { |
404 | bringToFront(w); |
405 | highlightWidget(w, on); |
406 | } |
407 | break; |
408 | #ifndef QT_NO_COMBOBOX |
409 | case TranslatableComboBoxItem: |
410 | static_cast<QComboBox *>(target.target.object)->setCurrentIndex(target.prop.index); |
411 | goto frontAndHighlight; |
412 | #endif |
413 | #ifndef QT_NO_TABWIDGET |
414 | case TranslatableTabPageText: |
415 | static_cast<QTabWidget *>(target.target.object)->setCurrentIndex(target.prop.index); |
416 | goto frontAndHighlight; |
417 | # ifndef QT_NO_TOOLTIP |
418 | case TranslatableTabPageToolTip: |
419 | # endif |
420 | # ifndef QT_NO_WHATSTHIS |
421 | case TranslatableTabPageWhatsThis: |
422 | # endif |
423 | #endif // QT_NO_TABWIDGET |
424 | #ifndef QT_NO_TOOLBOX |
425 | case TranslatableToolItemText: |
426 | # ifndef QT_NO_TOOLTIP |
427 | case TranslatableToolItemToolTip: |
428 | # endif |
429 | #endif // QT_NO_TOOLBOX |
430 | #if !defined(QT_NO_COMBOBOX) || !defined(QT_NO_TABWIDGET) |
431 | frontAndHighlight: |
432 | #endif |
433 | bringToFront(w: static_cast<QWidget *>(target.target.object)); |
434 | highlightWidget(w: static_cast<QWidget *>(target.target.object), on); |
435 | break; |
436 | #ifndef QT_NO_LISTWIDGET |
437 | case TranslatableListWidgetItem: |
438 | bringToFront(w: target.target.listWidgetItem->listWidget()); |
439 | highlightWidgetItem(item: target.target.listWidgetItem, on); |
440 | break; |
441 | #endif |
442 | #ifndef QT_NO_TABLEWIDGET |
443 | case TranslatableTableWidgetItem: |
444 | bringToFront(w: target.target.tableWidgetItem->tableWidget()); |
445 | highlightWidgetItem(item: target.target.tableWidgetItem, on); |
446 | break; |
447 | #endif |
448 | #ifndef QT_NO_TREEWIDGET |
449 | case TranslatableTreeWidgetItem: |
450 | bringToFront(w: target.target.treeWidgetItem->treeWidget()); |
451 | highlightTreeWidgetItem(item: target.target.treeWidgetItem, col: target.prop.treeIndex.column, on); |
452 | break; |
453 | #endif |
454 | } |
455 | } |
456 | |
457 | static void highlightTargets(const QList<TranslatableEntry> &targets, bool on) |
458 | { |
459 | for (const TranslatableEntry &target : targets) |
460 | highlightTarget(target, on); |
461 | } |
462 | |
463 | FormPreviewView::FormPreviewView(QWidget *parent, MultiDataModel *dataModel) |
464 | : QMainWindow(parent), m_form(0), m_dataModel(dataModel) |
465 | { |
466 | m_mdiSubWindow = new QMdiSubWindow; |
467 | m_mdiSubWindow->setWindowFlags(m_mdiSubWindow->windowFlags() & ~Qt::WindowSystemMenuHint); |
468 | m_mdiArea = new QMdiArea(this); |
469 | m_mdiArea->addSubWindow(widget: m_mdiSubWindow); |
470 | setCentralWidget(m_mdiArea); |
471 | m_mdiArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); |
472 | m_mdiArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); |
473 | } |
474 | |
475 | void FormPreviewView::setSourceContext(int model, MessageItem *messageItem) |
476 | { |
477 | if (model < 0 || !messageItem) { |
478 | m_lastModel = -1; |
479 | return; |
480 | } |
481 | |
482 | QDir dir = QFileInfo(m_dataModel->srcFileName(model)).dir(); |
483 | QString fileName = QDir::cleanPath(path: dir.absoluteFilePath(fileName: messageItem->fileName())); |
484 | if (m_lastFormName != fileName) { |
485 | delete m_form; |
486 | m_form = 0; |
487 | m_lastFormName.clear(); |
488 | m_highlights.clear(); |
489 | destroyTargets(targets: &m_targets); |
490 | |
491 | static QUiLoader *uiLoader; |
492 | if (!uiLoader) { |
493 | uiLoader = new QUiLoader(this); |
494 | uiLoader->setLanguageChangeEnabled(true); |
495 | uiLoader->setTranslationEnabled(false); |
496 | } |
497 | |
498 | QFile file(fileName); |
499 | if (!file.open(flags: QIODevice::ReadOnly)) { |
500 | qDebug() << "CANNOT OPEN FORM" << fileName; |
501 | m_mdiSubWindow->hide(); |
502 | return; |
503 | } |
504 | m_form = uiLoader->load(device: &file, parentWidget: m_mdiSubWindow); |
505 | if (!m_form) { |
506 | qDebug() << "CANNOT LOAD FORM" << fileName; |
507 | m_mdiSubWindow->hide(); |
508 | return; |
509 | } |
510 | file.close(); |
511 | buildTargets(o: m_form, targets: &m_targets); |
512 | |
513 | setToolTip(fileName); |
514 | |
515 | m_form->setWindowFlags(Qt::Widget); |
516 | m_form->setWindowModality(Qt::NonModal); |
517 | m_form->setFocusPolicy(Qt::NoFocus); |
518 | m_form->show(); // needed, otherwide the Qt::NoFocus is not propagated. |
519 | m_mdiSubWindow->setWidget(m_form); |
520 | m_mdiSubWindow->setWindowTitle(m_form->windowTitle()); |
521 | m_mdiSubWindow->show(); |
522 | m_mdiArea->cascadeSubWindows(); |
523 | m_lastFormName = fileName; |
524 | m_lastClassName = messageItem->context(); |
525 | m_lastModel = -1; |
526 | } else { |
527 | highlightTargets(targets: m_highlights, on: false); |
528 | } |
529 | QUiTranslatableStringValue tsv; |
530 | tsv.setValue(messageItem->text().toUtf8()); |
531 | tsv.setQualifier(messageItem->comment().toUtf8()); |
532 | m_highlights = m_targets.value(key: tsv); |
533 | if (m_lastModel != model) { |
534 | for (auto it = m_targets.cbegin(), end = m_targets.cend(); it != end; ++it) |
535 | retranslateTargets(targets: *it, tsv: it.key(), dataModel: m_dataModel->model(i: model), className: m_lastClassName); |
536 | m_lastModel = model; |
537 | } else { |
538 | retranslateTargets(targets: m_highlights, tsv, dataModel: m_dataModel->model(i: model), className: m_lastClassName); |
539 | } |
540 | highlightTargets(targets: m_highlights, on: true); |
541 | } |
542 | |
543 | QT_END_NAMESPACE |
544 | |