Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
ui.cpp
Go to the documentation of this file.
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 "lupdate.h"
5
6#include <translator.h>
7#include <xmlparser.h>
8
9#include <QtCore/QCoreApplication>
10#include <QtCore/QDebug>
11#include <QtCore/QFile>
12#include <QtCore/QString>
13#include <QtCore/QXmlStreamReader>
14
16
17using namespace Qt::StringLiterals;
18
19class UiReader : public XmlParser
20{
21public:
22 UiReader(Translator &translator, ConversionData &cd, QXmlStreamReader &reader)
23 : XmlParser(reader),
24 m_translator(translator),
25 m_cd(cd),
26 m_lineNumber(-1),
27 m_isTrString(false),
28 m_insideStringList(false)
29 {
30 }
31 ~UiReader() override = default;
32
33private:
34 bool startElement(QStringView namespaceURI, QStringView localName,
35 QStringView qName, const QXmlStreamAttributes &atts) override;
36 bool endElement(QStringView namespaceURI, QStringView localName,
37 QStringView qName) override;
38 bool characters(QStringView ch) override;
39 bool fatalError(qint64 line, qint64 column, const QString &message) override;
40
41 void flush();
42 void readTranslationAttributes(const QXmlStreamAttributes &atts);
43
44 Translator &m_translator;
45 ConversionData &m_cd;
46 QString m_context;
47 QString m_source;
48 QString m_comment;
49 QString m_extracomment;
50 QString m_id;
51 QString m_label;
52
53 QString m_accum;
54 int m_lineNumber;
55 bool m_isTrString;
56 bool m_insideStringList;
57};
58
59bool UiReader::startElement(QStringView namespaceURI, QStringView localName,
60 QStringView qName, const QXmlStreamAttributes &atts)
61{
62 Q_UNUSED(namespaceURI);
63 Q_UNUSED(localName);
64
65 if (qName == "string"_L1) {
66 flush();
67 if (!m_insideStringList)
68 readTranslationAttributes(atts);
69 } else if (qName == "stringlist"_L1) {
70 flush();
71 m_insideStringList = true;
72 readTranslationAttributes(atts);
73 } else if (qName == "ui"_L1) {
74 m_label = QString(atts.value("label"));
75 }
76 m_accum.clear();
77 return true;
78}
79
80bool UiReader::endElement(QStringView namespaceURI, QStringView localName,
81 QStringView qName)
82{
83 Q_UNUSED(namespaceURI);
84 Q_UNUSED(localName);
85
86 m_accum.replace("\r\n"_L1, "\n"_L1);
87
88 if (qName == "class"_L1) { // UI "header"
89 if (m_context.isEmpty())
90 m_context = m_accum;
91 } else if (qName == "string"_L1 && m_isTrString) {
92 m_source = m_accum;
93 } else if (qName == "comment"_L1) { // FIXME: what's that?
94 m_comment = m_accum;
95 flush();
96 } else if (qName == "stringlist"_L1) {
97 m_insideStringList = false;
98 } else {
99 flush();
100 }
101 return true;
102}
103
104bool UiReader::characters(QStringView ch)
105{
106 m_accum += ch.toString();
107 return true;
108}
109
110bool UiReader::fatalError(qint64 line, qint64 column, const QString &message)
111{
112 QString msg = QStringLiteral("XML error: Parse error at line %1, column %2 (%3).")
113 .arg(line)
114 .arg(column)
115 .arg(message);
116 m_cd.appendError(msg);
117 return false;
118}
119
120void UiReader::flush()
121{
122 if ((!m_context.isEmpty() || !m_id.isEmpty()) && !m_source.isEmpty()) {
123 TranslatorMessage msg(m_context, m_source,
124 m_comment, QString(), m_cd.m_sourceFileName,
125 m_lineNumber, QStringList());
126 msg.setExtraComment(m_extracomment);
127 msg.setLabel(m_label);
128 msg.setId(m_id);
129 if (!m_id.isEmpty())
130 msg.setContext({});
131 m_translator.extend(msg, m_cd);
132 }
133 m_source.clear();
134 if (!m_insideStringList) {
135 m_comment.clear();
136 m_extracomment.clear();
137 m_id.clear();
138 }
139}
140
141void UiReader::readTranslationAttributes(const QXmlStreamAttributes &atts)
142{
143 const auto notr = atts.value(QStringLiteral("notr"));
144 if (notr.isEmpty() || notr != QStringLiteral("true")) {
145 m_isTrString = true;
146 m_comment = atts.value(QStringLiteral("comment")).toString();
147 m_extracomment = atts.value(QStringLiteral("extracomment")).toString();
148 m_id = atts.value(QStringLiteral("id")).toString();
149 if (m_id.isEmpty())
150 m_label.clear();
151 if (!m_cd.m_noUiLines)
152 m_lineNumber = static_cast<int>(reader.lineNumber());
153 } else {
154 m_isTrString = false;
155 }
156}
157
158bool loadUI(Translator &translator, const QString &filename, ConversionData &cd)
159{
160 cd.m_sourceFileName = filename;
161 QFile file(filename);
162 if (!file.open(QIODevice::ReadOnly)) {
163 cd.appendError("Cannot open %1: %2"_L1.arg(filename, file.errorString()));
164 return false;
165 }
166
167 QXmlStreamReader reader(&file);
168 reader.setNamespaceProcessing(false);
169
170 UiReader uiReader(translator, cd, reader);
171 bool result = uiReader.parse();
172 if (!result)
173 cd.appendError(u"Parse error in UI file"_s);
174 return result;
175}
176
177QT_END_NAMESPACE
void extend(const TranslatorMessage &msg, ConversionData &cd)
UiReader(Translator &translator, ConversionData &cd, QXmlStreamReader &reader)
Definition ui.cpp:22
bool fatalError(qint64 line, qint64 column, const QString &message) override
Definition ui.cpp:110
bool startElement(QStringView namespaceURI, QStringView localName, QStringView qName, const QXmlStreamAttributes &atts) override
Definition ui.cpp:59
bool endElement(QStringView namespaceURI, QStringView localName, QStringView qName) override
Definition ui.cpp:80
bool characters(QStringView ch) override
Definition ui.cpp:104
~UiReader() override=default
bool parse()
Definition xmlparser.cpp:8
bool loadUI(Translator &translator, const QString &filename, ConversionData &cd)
Definition ui.cpp:158