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
phrase.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 "phrase.h"
5#include "translator.h"
6#include "xmlparser.h"
7
8#include <QApplication>
9#include <QFile>
10#include <QFileInfo>
11#include <QMessageBox>
12#include <QTextStream>
13#include <QXmlStreamReader>
14
16
17using namespace Qt::Literals::StringLiterals;
18
19static QString xmlProtect(const QString & str)
20{
21 QString p = str;
22 p.replace(u'&', "&amp;"_L1);
23 p.replace(u'\"', "&quot;"_L1);
24 p.replace(u'>', "&gt;"_L1);
25 p.replace(u'<', "&lt;"_L1);
26 p.replace(QLatin1Char('\''), "&apos;"_L1);
27 return p;
28}
29
31 : shrtc(-1), m_phraseBook(0)
32{
33}
34
35Phrase::Phrase(const QString &source, const QString &target, const QString &definition,
36 const Candidate &candidate, int sc)
37 : shrtc(sc), s(source), t(target), d(definition), cand(candidate), m_phraseBook(0)
38{
39}
40
41Phrase::Phrase(const QString &source, const QString &target,
42 const QString &definition, PhraseBook *phraseBook)
43 : shrtc(-1), s(source), t(target), d(definition),
44 m_phraseBook(phraseBook)
45{
46}
47
48void Phrase::setSource(const QString &ns)
49{
50 if (s == ns)
51 return;
52 s = ns;
53 if (m_phraseBook)
54 m_phraseBook->phraseChanged(this);
55}
56
57void Phrase::setTarget(const QString &nt)
58{
59 if (t == nt)
60 return;
61 t = nt;
62 if (m_phraseBook)
63 m_phraseBook->phraseChanged(this);
64}
65
66void Phrase::setDefinition(const QString &nd)
67{
68 if (d == nd)
69 return;
70 d = nd;
71 if (m_phraseBook)
72 m_phraseBook->phraseChanged(this);
73}
74
75bool operator==(const Phrase &p, const Phrase &q)
76{
77 return p.source() == q.source() && p.target() == q.target() &&
78 p.definition() == q.definition() && p.phraseBook() == q.phraseBook();
79}
80
81class QphHandler : public XmlParser
82{
83public:
84 QphHandler(PhraseBook *phraseBook, QXmlStreamReader &reader)
85 : XmlParser(reader), pb(phraseBook), ferrorCount(0)
86 {
87 }
88 ~QphHandler() override = default;
89
90 QString language() const { return m_language; }
91 QString sourceLanguage() const { return m_sourceLanguage; }
92
93private:
94 bool startElement(QStringView namespaceURI, QStringView localName,
95 QStringView qName, const QXmlStreamAttributes &atts) override;
96 bool endElement(QStringView namespaceURI, QStringView localName,
97 QStringView qName) override;
98 bool characters(QStringView ch) override;
99 bool fatalError(qint64 line, qint64 column, const QString &message) override;
100
101 PhraseBook *pb;
102 QString source;
103 QString target;
104 QString definition;
105 QString m_language;
106 QString m_sourceLanguage;
107
108 QString accum;
109 int ferrorCount;
110};
111
112bool QphHandler::startElement(QStringView namespaceURI, QStringView localName,
113 QStringView qName, const QXmlStreamAttributes &atts)
114{
115 Q_UNUSED(namespaceURI);
116 Q_UNUSED(localName);
117
118 if (qName == "QPH"_L1) {
119 m_language = atts.value("language"_L1).toString();
120 m_sourceLanguage = atts.value("sourcelanguage"_L1).toString();
121 } else if (qName == "phrase"_L1) {
122 source.truncate(0);
123 target.truncate(0);
124 definition.truncate(0);
125 }
126 accum.truncate(0);
127 return true;
128}
129
130bool QphHandler::endElement(QStringView namespaceURI, QStringView localName,
131 QStringView qName)
132{
133 Q_UNUSED(namespaceURI);
134 Q_UNUSED(localName);
135
136 if (qName == "source"_L1)
137 source = accum;
138 else if (qName == "target"_L1)
139 target = accum;
140 else if (qName == "definition"_L1)
141 definition = accum;
142 else if (qName == "phrase"_L1)
143 pb->m_phrases.append(new Phrase(source, target, definition, pb));
144 return true;
145}
146
147bool QphHandler::characters(QStringView ch)
148{
149 accum += ch;
150 return true;
151}
152
153bool QphHandler::fatalError(qint64 line, qint64 column, const QString &message)
154{
155 if (ferrorCount++ == 0) {
156 QString msg = PhraseBook::tr("Parse error at line %1, column %2 (%3).")
157 .arg(line)
158 .arg(column)
159 .arg(message);
160 QMessageBox::information(nullptr, QObject::tr("Qt Linguist"), msg);
161 }
162 return false;
163}
164
165PhraseBook::PhraseBook() :
166 m_changed(false),
167 m_language(QLocale::C),
168 m_sourceLanguage(QLocale::C),
169 m_territory(QLocale::AnyTerritory),
170 m_sourceTerritory(QLocale::AnyTerritory)
171{
172}
173
175{
176 qDeleteAll(m_phrases);
177}
178
179void PhraseBook::setLanguageAndTerritory(QLocale::Language lang, QLocale::Territory territory)
180{
181 if (m_language == lang && m_territory == territory)
182 return;
183 m_language = lang;
184 m_territory = territory;
185 setModified(true);
186}
187
188void PhraseBook::setSourceLanguageAndTerritory(QLocale::Language lang, QLocale::Territory territory)
189{
190 if (m_sourceLanguage == lang && m_sourceTerritory == territory)
191 return;
192 m_sourceLanguage = lang;
193 m_sourceTerritory = territory;
194 setModified(true);
195}
196
197bool PhraseBook::load(const QString &fileName, bool *langGuessed)
198{
199 QFile f(fileName);
200 if (!f.open(QIODevice::ReadOnly))
201 return false;
202
203 m_fileName = fileName;
204
205 QXmlStreamReader reader(&f);
206 QphHandler *hand = new QphHandler(this, reader);
207 reader.setNamespaceProcessing(false);
208 bool ok = hand->parse();
209
210 Translator::languageAndTerritory(hand->language(), &m_language, &m_territory);
211 *langGuessed = false;
212 if (m_language == QLocale::C) {
213 QLocale sys;
214 m_language = sys.language();
215 m_territory = sys.territory();
216 *langGuessed = true;
217 }
218
219 QString lang = hand->sourceLanguage();
220 if (lang.isEmpty()) {
221 m_sourceLanguage = QLocale::C;
222 m_sourceTerritory = QLocale::AnyTerritory;
223 } else {
224 Translator::languageAndTerritory(lang, &m_sourceLanguage, &m_sourceTerritory);
225 }
226
227 delete hand;
228 f.close();
229 if (!ok) {
230 qDeleteAll(m_phrases);
231 m_phrases.clear();
232 } else {
233 emit listChanged();
234 }
235
236 return ok;
237}
238
239bool PhraseBook::save(const QString &fileName)
240{
241 QFile f(fileName);
242 if (!f.open(QIODevice::WriteOnly))
243 return false;
244
245 m_fileName = fileName;
246
247 QTextStream t(&f);
248
249 t << "<!DOCTYPE QPH>\n<QPH";
250 if (sourceLanguage() != QLocale::C)
251 t << " sourcelanguage=\""
252 << Translator::makeLanguageCode(sourceLanguage(), sourceTerritory()) << '"';
253 if (language() != QLocale::C)
254 t << " language=\"" << Translator::makeLanguageCode(language(), territory()) << '"';
255 t << ">\n";
256 for (Phrase *p : std::as_const(m_phrases)) {
257 t << "<phrase>\n";
258 t << " <source>" << xmlProtect( p->source() ) << "</source>\n";
259 t << " <target>" << xmlProtect( p->target() ) << "</target>\n";
260 if (!p->definition().isEmpty())
261 t << " <definition>" << xmlProtect( p->definition() )
262 << "</definition>\n";
263 t << "</phrase>\n";
264 }
265 t << "</QPH>\n";
266 f.close();
267 setModified(false);
268 return true;
269}
270
272{
273 m_phrases.append(phrase);
274 phrase->setPhraseBook(this);
275 setModified(true);
276 emit listChanged();
277}
278
280{
281 m_phrases.removeOne(phrase);
282 phrase->setPhraseBook(0);
283 setModified(true);
284 emit listChanged();
285}
286
287void PhraseBook::setModified(bool modified)
288 {
289 if (m_changed != modified) {
290 emit modifiedChanged(modified);
291 m_changed = modified;
292 }
293}
294
295void PhraseBook::phraseChanged(Phrase *p)
296{
297 Q_UNUSED(p);
298
299 setModified(true);
300}
301
303{
304 if (!m_fileName.isEmpty())
305 return QFileInfo(m_fileName).fileName();
306 return QString();
307}
308
309QT_END_NAMESPACE
void append(Phrase *phrase)
Definition phrase.cpp:271
QString friendlyPhraseBookName() const
Definition phrase.cpp:302
bool load(const QString &fileName, bool *langGuessed)
Definition phrase.cpp:197
bool save(const QString &fileName)
Definition phrase.cpp:239
void remove(Phrase *phrase)
Definition phrase.cpp:279
void setPhraseBook(PhraseBook *book)
Definition phrase.h:36
PhraseBook * phraseBook() const
Definition phrase.h:35
void setDefinition(const QString &nd)
Definition phrase.cpp:66
void setSource(const QString &ns)
Definition phrase.cpp:48
Phrase()
Definition phrase.cpp:30
Phrase(const QString &source, const QString &target, const QString &definition, PhraseBook *phraseBook)
Definition phrase.cpp:41
Phrase(const QString &source, const QString &target, const QString &definition, const Candidate &candidate, int sc=-1)
Definition phrase.cpp:35
void setTarget(const QString &nt)
Definition phrase.cpp:57
bool fatalError(qint64 line, qint64 column, const QString &message) override
Definition phrase.cpp:153
QphHandler(PhraseBook *phraseBook, QXmlStreamReader &reader)
Definition phrase.cpp:84
QString sourceLanguage() const
Definition phrase.cpp:91
bool endElement(QStringView namespaceURI, QStringView localName, QStringView qName) override
Definition phrase.cpp:130
~QphHandler() override=default
bool startElement(QStringView namespaceURI, QStringView localName, QStringView qName, const QXmlStreamAttributes &atts) override
Definition phrase.cpp:112
QString language() const
Definition phrase.cpp:90
bool characters(QStringView ch) override
Definition phrase.cpp:147
bool parse()
Definition xmlparser.cpp:8
static QString xmlProtect(const QString &str)
Definition phrase.cpp:19
bool operator==(const Phrase &p, const Phrase &q)
Definition phrase.cpp:75