Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qqmldebugtranslationservice.cpp
Go to the documentation of this file.
1
// Copyright (C) 2020 The Qt Company Ltd.
2
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
// Qt-Security score:significant
4
5
#
include
"qqmldebugtranslationservice.h"
6
#
include
"proxytranslator.h"
7
#
include
"qqmlpreviewservice.h"
8
9
#
include
<
QtCore
/
qtranslator
.
h
>
10
#
include
<
QtCore
/
qdebug
.
h
>
11
#
include
<
QtCore
/
qlibraryinfo
.
h
>
12
#
include
<
QtCore
/
qdir
.
h
>
13
#
include
<
QtCore
/
qfile
.
h
>
14
#
include
<
QtCore
/
qtimer
.
h
>
15
#
include
<
QtCore
/
qhash
.
h
>
16
#
include
<
QtCore
/
qpointer
.
h
>
17
18
#
include
<
private
/
qqmldebugtranslationprotocol_p
.
h
>
19
#
include
<
private
/
qqmldebugconnector_p
.
h
>
20
#
include
<
private
/
qversionedpacket_p
.
h
>
21
22
#
include
<
private
/
qqmlbinding_p
.
h
>
23
#
include
<
private
/
qqmlbinding_p
.
h
>
24
#
include
<
private
/
qquickstategroup_p
.
h
>
25
#
include
<
private
/
qquickitem_p
.
h
>
26
#
include
<
private
/
qquicktext_p
.
h
>
27
#
include
<
private
/
qdebug_p
.
h
>
28
29
#
include
<
QtQuick
/
qquickitem
.
h
>
30
31
#
include
<
qquickview
.
h
>
32
33
QT_BEGIN_NAMESPACE
34
35
using
namespace
QQmlDebugTranslation;
36
37
QDebug
operator
<<(QDebug debug,
const
TranslationBindingInformation &translationBindingInformation)
38
{
39
QQmlError error;
40
error.setUrl(translationBindingInformation.compilationUnit->url());
41
error.setLine(translationBindingInformation.line);
42
error.setColumn(translationBindingInformation.column);
43
error.setDescription(
44
QString(QLatin1String(
45
"QDebug translation binding"
46
)));
47
return
debug << qPrintable(error.toString());
48
}
49
50
static
QString
translationIdString
(
const
QQmlTranslation::QsTrData &data)
51
{
52
return
QString::fromUtf8(data.text());
53
}
54
55
static
QString
translationIdString
(
const
QQmlTranslation::QsTrIdData &data)
56
{
57
return
QString::fromUtf8(data.id());
58
}
59
60
static
QString
translationIdString
(
const
QQmlTranslation &translation)
61
{
62
return
translation.visit(
63
[](
auto
&&arg) -> QString {
64
using
T = std::decay_t<
decltype
(arg)>;
65
if
constexpr
(!std::is_same_v<T, std::nullptr_t>)
66
return
translationIdString(arg);
67
else
{
68
Q_ASSERT_X(
false
,
"QQmlTranslation"
,
"Uninitialized Translation"
);
69
return
{};
70
}
71
});
72
}
73
74
class
QQmlDebugTranslationServicePrivate
:
public
QObject
75
{
76
Q_OBJECT
77
public
:
78
QQmlDebugTranslationServicePrivate
(
QQmlDebugTranslationServiceImpl
*
parent
)
79
:
q
(
parent
)
80
,
proxyTranslator
(
new
ProxyTranslator
)
81
{
82
connect
(&
translatableTextOccurrenceTimer
, &
QTimer
::
timeout
,
83
this
, &
QQmlDebugTranslationServicePrivate
::
sendTranslatableTextOccurrences
);
84
}
85
86
void
setState
(
const
QString
&
stateName
)
87
{
88
if
(
QQuickItem
*
rootItem
=
currentRootItem
()) {
89
QQuickStateGroup
*
stateGroup
=
QQuickItemPrivate
::
get
(
rootItem
)->
_states
();
90
if
(
stateGroup
->
findState
(
stateName
)) {
91
connect
(
stateGroup
, &
QQuickStateGroup
::
stateChanged
,
92
this
, &
QQmlDebugTranslationServicePrivate
::
sendStateChanged
,
93
Qt
::
ConnectionType
(
Qt
::
QueuedConnection
|
Qt
::
UniqueConnection
));
94
stateGroup
->
setState
(
stateName
);
95
}
96
else
97
qWarning
() <<
"Could not switch the state"
<<
stateName
<<
"at"
<<
rootItem
;
98
}
99
}
100
101
void
sendStateChanged
()
102
{
103
if
(
QQuickStateGroup
*
stateGroup
=
qobject_cast
<
QQuickStateGroup
*>(
sender
()))
104
currentStateName
=
stateGroup
->
state
();
105
QVersionedPacket
<
QQmlDebugConnector
>
packet
;
106
packet
<<
Reply
::
StateChanged
<<
currentStateName
;
107
emit
q
->
messageToClient
(
q
->
name
(),
packet
.
data
());
108
}
109
110
void
sendStateList
()
111
{
112
QVersionedPacket
<
QQmlDebugConnector
>
packet
;
113
packet
<<
Reply
::
StateList
;
114
QList
<
QmlState
>
qmlStates
;
115
116
if
(
QQuickItem
*
rootItem
=
currentRootItem
()) {
117
QQuickStateGroup
*
stateGroup
=
QQuickItemPrivate
::
get
(
rootItem
)->
_states
();
118
119
QList
<
QQuickState
*>
states
=
stateGroup
->
states
();
120
121
for
(
QQuickState
*
state
:
states
) {
122
QmlState
qmlState
;
123
qmlState
.
name
=
state
->
name
();
124
qmlStates
.
append
(
qmlState
);
125
}
126
}
127
128
packet
<<
qmlStates
;
129
emit
q
->
messageToClient
(
q
->
name
(),
packet
.
data
());
130
}
131
132
void
setWatchTextElides
(
bool
s
)
133
{
134
// TODO: for disabling we need to keep track which one were enabled
135
if
(
s
==
false
)
136
qWarning
() <<
"disable WatchTextElides is not implemented"
;
137
watchTextElides
=
s
;
138
for
(
auto
&&
information
:
std
::
as_const
(
objectTranslationBindingMultiMap
)) {
139
QObject
*
scopeObject
=
information
.
scopeObject
;
140
int
elideIndex
=
scopeObject
->
metaObject
()->
indexOfProperty
(
"elide"
);
141
if
(
elideIndex
>= 0) {
142
auto
elideProperty
=
scopeObject
->
metaObject
()->
property
(
elideIndex
);
143
elideProperty
.
write
(
scopeObject
,
Qt
::
ElideRight
);
144
}
145
}
146
}
147
148
QString
getStyleNameForFont
(
const
QFont
&
font
)
149
{
150
if
(
font
.
styleName
() !=
""
)
151
return
font
.
styleName
();
152
QString
styleName
;
153
if
(
font
.
bold
())
154
styleName
.
append
(
"Bold "
);
155
if
(
font
.
italic
())
156
styleName
.
append
(
"Italic "
);
157
if
(
font
.
strikeOut
())
158
styleName
.
append
(
"StrikeThrough "
);
159
if
(
font
.
underline
())
160
styleName
.
append
(
"Underline "
);
161
return
styleName
.
trimmed
();
162
}
163
164
void
sendTranslatableTextOccurrences
()
165
{
166
167
QVersionedPacket
<
QQmlDebugConnector
>
packet
;
168
packet
<<
Reply
::
TranslatableTextOccurrences
;
169
170
QList
<
QmlElement
>
qmlElements
;
171
172
for
(
auto
&&
information
:
std
::
as_const
(
objectTranslationBindingMultiMap
)) {
173
174
QObject
*
scopeObject
=
information
.
scopeObject
;
175
auto
compilationUnit
=
information
.
compilationUnit
;
176
auto
metaObject
=
scopeObject
->
metaObject
();
177
178
int
textIndex
=
metaObject
->
indexOfProperty
(
information
.
propertyName
.
toLatin1
());
179
if
(
textIndex
>= 0) {
180
181
QmlElement
qmlElement
;
182
183
qmlElement
.
codeMarker
=
codeMarker
(
information
);
184
185
auto
textProperty
=
scopeObject
->
metaObject
()->
property
(
textIndex
);
186
qmlElement
.
propertyName
=
textProperty
.
name
();
187
qmlElement
.
translationId
=
translationIdString
(
information
.
translation
);
188
qmlElement
.
translatedText
=
textProperty
.
read
(
scopeObject
).
toString
();
189
qmlElement
.
elementId
=
qmlContext
(
scopeObject
)->
nameForObject
(
scopeObject
);
190
191
QFont
font
=
scopeObject
->
property
(
"font"
).
value
<
QFont
>();
192
qmlElement
.
fontFamily
=
font
.
family
();
193
qmlElement
.
fontPointSize
=
font
.
pointSize
();
194
qmlElement
.
fontPixelSize
=
font
.
pixelSize
();
195
qmlElement
.
fontStyleName
=
getStyleNameForFont
(
font
);
196
qmlElement
.
horizontalAlignment
=
197
scopeObject
->
property
(
"horizontalAlignment"
).
toInt
();
198
qmlElement
.
verticalAlignment
=
scopeObject
->
property
(
"verticalAlignment"
).
toInt
();
199
200
QQmlType
qmlType
=
QQmlMetaType
::
qmlType
(
metaObject
);
201
qmlElement
.
elementType
=
qmlType
.
qmlTypeName
() +
"/"
+
qmlType
.
typeName
();
202
qmlElement
.
stateName
=
currentStateName
;
203
qmlElements
.
append
(
qmlElement
);
204
205
}
else
{
206
QString
warningMessage
=
"(QQmlDebugTranslationService can not resolve %1 - %2:"
207
" this should never happen)"
;
208
const
QString
id
=
qmlContext
(
scopeObject
)->
nameForObject
(
scopeObject
);
209
qWarning
().
noquote
() <<
warningMessage
.
arg
(
id
,
information
.
propertyName
);
210
}
211
}
212
std
::
sort
(
qmlElements
.
begin
(),
qmlElements
.
end
(), [](
const
auto
&
l1
,
const
auto
&
l2
){
213
return
l1
.
codeMarker
<
l2
.
codeMarker
;
214
});
215
216
packet
<<
qmlElements
;
217
emit
q
->
messageToClient
(
q
->
name
(),
packet
.
data
());
218
}
219
220
void
sendLanguageChanged
()
221
{
222
QVersionedPacket
<
QQmlDebugConnector
>
packet
;
223
packet
<<
Reply
::
LanguageChanged
;
224
emit
q
->
messageToClient
(
q
->
name
(),
packet
.
data
());
225
}
226
227
void
sendTranslationIssues
()
228
{
229
QVersionedPacket
<
QQmlDebugConnector
>
packet
;
230
packet
<<
Reply
::
TranslationIssues
;
231
232
QList
<
TranslationIssue
>
issues
;
233
for
(
auto
&&
information
:
std
::
as_const
(
objectTranslationBindingMultiMap
)) {
234
if
(!
proxyTranslator
->
hasTranslation
(
information
)) {
235
TranslationIssue
issue
;
236
issue
.
type
=
TranslationIssue
::
Type
::
Missing
;
237
issue
.
codeMarker
=
codeMarker
(
information
);
238
issue
.
language
=
proxyTranslator
->
currentUILanguages
();
239
issues
.
append
(
issue
);
240
}
241
242
QObject
*
scopeObject
=
information
.
scopeObject
;
243
QQuickText
*
quickText
=
static_cast
<
QQuickText
*>(
scopeObject
);
244
if
(
quickText
) {
245
if
(
quickText
->
truncated
()) {
246
TranslationIssue
issue
;
247
issue
.
type
=
TranslationIssue
::
Type
::
Elided
;
248
issue
.
codeMarker
=
codeMarker
(
information
);
249
issue
.
language
=
proxyTranslator
->
currentUILanguages
();
250
issues
.
append
(
issue
);
251
}
252
}
253
}
254
std
::
sort
(
issues
.
begin
(),
issues
.
end
(), [](
const
auto
&
l1
,
const
auto
&
l2
){
255
return
l1
.
codeMarker
<
l2
.
codeMarker
;
256
});
257
packet
<<
issues
;
258
emit
q
->
messageToClient
(
q
->
name
(),
packet
.
data
());
259
}
260
261
QQmlDebugTranslationServiceImpl
*
q
;
262
263
bool
watchTextElides
=
false
;
264
QMultiMap
<
QObject
*,
TranslationBindingInformation
>
objectTranslationBindingMultiMap
;
265
QHash
<
QObject
*,
QList
<
QMetaObject
::
Connection
>>
elideConnections
;
266
ProxyTranslator *
proxyTranslator
;
267
268
bool
enableWatchTranslations
=
false
;
269
QTimer
translatableTextOccurrenceTimer
;
270
QList
<
QPointer
<
QQuickItem
>>
translatableTextOccurrences
;
271
272
QQuickItem *
currentRootItem
()
273
{
274
if
(
QQmlPreviewServiceImpl
*service = QQmlDebugConnector::service<QQmlPreviewServiceImpl>())
275
return
service
->
currentRootItem
(
)
;
276
if
(currentQuickView)
277
return
currentQuickView->rootObject();
278
return
nullptr
;
279
}
280
QQuickView
*
currentQuickView
=
nullptr
;
281
282
private
:
283
CodeMarker codeMarker(
const
TranslationBindingInformation &information)
284
{
285
CodeMarker c;
286
c.url = information.compilationUnit->url();
287
c.line = information.line;
288
c.column = information.column;
289
return
c;
290
}
291
QString currentStateName;
292
};
293
294
QQmlDebugTranslationServiceImpl
::QQmlDebugTranslationServiceImpl(QObject *parent)
295
: QQmlDebugTranslationService(1, parent)
296
{
297
d =
new
QQmlDebugTranslationServicePrivate(
this
);
298
299
connect(
this
, &
QQmlDebugTranslationServiceImpl
::
watchTextElides
,
300
d, &QQmlDebugTranslationServicePrivate::setWatchTextElides,
301
Qt::QueuedConnection);
302
303
connect(
this
, &QQmlDebugTranslationServiceImpl::language,
304
d
->
proxyTranslator
, &ProxyTranslator::setLanguage,
305
Qt::QueuedConnection);
306
307
connect(
this
, &QQmlDebugTranslationServiceImpl::state,
308
d, &QQmlDebugTranslationServicePrivate::setState,
309
Qt::QueuedConnection);
310
311
connect(
this
, &
QQmlDebugTranslationServiceImpl
::
stateList
,
312
d, &QQmlDebugTranslationServicePrivate::sendStateList,
313
Qt::QueuedConnection);
314
315
connect(d
->
proxyTranslator
, &ProxyTranslator::languageChanged,
316
d, &QQmlDebugTranslationServicePrivate::sendLanguageChanged,
317
Qt::QueuedConnection);
318
319
connect(
this
, &
QQmlDebugTranslationServiceImpl
::
translationIssues
,
320
d, &QQmlDebugTranslationServicePrivate::sendTranslationIssues,
321
Qt::QueuedConnection);
322
323
connect(
this
, &
QQmlDebugTranslationServiceImpl
::
sendTranslatableTextOccurrences
,
324
d, &QQmlDebugTranslationServicePrivate::sendTranslatableTextOccurrences,
325
Qt::QueuedConnection);
326
}
327
328
QQmlDebugTranslationServiceImpl
::~
QQmlDebugTranslationServiceImpl
()
329
{
330
delete
d
->
proxyTranslator
;
331
d
->
proxyTranslator
= {};
332
delete
d;
333
}
334
335
void
QQmlDebugTranslationServiceImpl
::
messageReceived
(
const
QByteArray &message)
336
{
337
QVersionedPacket<QQmlDebugConnector> packet(message);
338
QQmlDebugTranslation::Request command;
339
340
packet >> command;
341
switch
(command) {
342
case
QQmlDebugTranslation::Request::ChangeLanguage: {
343
QUrl context;
344
QString locale;
345
packet >> context >> locale;
346
emit language(context, QLocale(locale));
347
break
;
348
}
349
case
QQmlDebugTranslation::Request::ChangeState: {
350
QString stateName;
351
packet >> stateName;
352
emit state(stateName);
353
break
;
354
}
355
case
QQmlDebugTranslation::Request::StateList: {
356
emit stateList();
357
break
;
358
}
359
case
QQmlDebugTranslation::Request::TranslationIssues: {
360
emit translationIssues();
361
break
;
362
}
363
case
QQmlDebugTranslation::Request::TranslatableTextOccurrences: {
364
emit sendTranslatableTextOccurrences();
365
break
;
366
}
367
case
QQmlDebugTranslation::Request::WatchTextElides: {
368
emit watchTextElides(
true
);
369
break
;
370
}
371
case
QQmlDebugTranslation::Request::DisableWatchTextElides: {
372
emit watchTextElides(
false
);
373
break
;
374
}
375
default
: {
376
qWarning() <<
"DebugTranslationService: received unknown command: "
<<
static_cast
<
int
>(command);
377
break
;
378
}
379
}
// switch (command)
380
}
381
382
void
QQmlDebugTranslationServiceImpl
::
engineAboutToBeAdded
(QJSEngine *engine)
383
{
384
if
(QQmlEngine *qmlEngine = qobject_cast<QQmlEngine *>(engine))
385
d
->
proxyTranslator
->addEngine(qmlEngine);
386
387
if
(engine->parent())
388
d->currentQuickView = qobject_cast<QQuickView*>(engine->parent());
389
390
emit attachedToEngine(engine);
391
}
392
393
void
QQmlDebugTranslationServiceImpl
::
engineAboutToBeRemoved
(QJSEngine *engine)
394
{
395
if
(QQmlEngine *qmlEngine = qobject_cast<QQmlEngine *>(engine))
396
d
->
proxyTranslator
->removeEngine(qmlEngine);
397
emit detachedFromEngine(engine);
398
}
399
400
void
QQmlDebugTranslationServiceImpl
::
foundTranslationBinding
(
const
TranslationBindingInformation &translationBindingInformation)
401
{
402
QObject *scopeObject = translationBindingInformation.scopeObject;
403
connect(scopeObject, &QObject::destroyed,
this
, [
this
, scopeObject] () {
404
this
->d->objectTranslationBindingMultiMap.remove(scopeObject);
405
});
406
407
d->objectTranslationBindingMultiMap.insert(scopeObject, translationBindingInformation);
408
}
409
410
QT_END_NAMESPACE
411
412
#
include
"moc_qqmldebugtranslationservice.cpp"
413
414
#
include
<
qqmldebugtranslationservice
.
moc
>
QQmlDebugTranslationServiceImpl
Definition
qqmldebugtranslationservice.h:30
QQmlDebugTranslationServiceImpl::messageReceived
void messageReceived(const QByteArray &message) override
Definition
qqmldebugtranslationservice.cpp:335
QQmlDebugTranslationServiceImpl::foundTranslationBinding
void foundTranslationBinding(const TranslationBindingInformation &translationBindingInformation) override
Definition
qqmldebugtranslationservice.cpp:400
QQmlDebugTranslationServiceImpl::engineAboutToBeAdded
void engineAboutToBeAdded(QJSEngine *engine) override
Definition
qqmldebugtranslationservice.cpp:382
QQmlDebugTranslationServiceImpl::stateList
void stateList()
QQmlDebugTranslationServiceImpl::~QQmlDebugTranslationServiceImpl
~QQmlDebugTranslationServiceImpl()
Definition
qqmldebugtranslationservice.cpp:328
QQmlDebugTranslationServiceImpl::translationIssues
void translationIssues()
QQmlDebugTranslationServiceImpl::engineAboutToBeRemoved
void engineAboutToBeRemoved(QJSEngine *engine) override
Definition
qqmldebugtranslationservice.cpp:393
QQmlDebugTranslationServiceImpl::watchTextElides
void watchTextElides(bool)
QQmlDebugTranslationServiceImpl::sendTranslatableTextOccurrences
void sendTranslatableTextOccurrences()
QQmlDebugTranslationServicePrivate
Definition
qqmldebugtranslationservice.cpp:75
QQmlDebugTranslationServicePrivate::currentRootItem
QQuickItem * currentRootItem()
Definition
qqmldebugtranslationservice.cpp:272
QQmlDebugTranslationServicePrivate::objectTranslationBindingMultiMap
QMultiMap< QObject *, TranslationBindingInformation > objectTranslationBindingMultiMap
Definition
qqmldebugtranslationservice.cpp:264
QQmlDebugTranslationServicePrivate::currentQuickView
QQuickView * currentQuickView
Definition
qqmldebugtranslationservice.cpp:280
QQmlDebugTranslationServicePrivate::translatableTextOccurrences
QList< QPointer< QQuickItem > > translatableTextOccurrences
Definition
qqmldebugtranslationservice.cpp:270
QQmlDebugTranslationServicePrivate::proxyTranslator
ProxyTranslator * proxyTranslator
Definition
qqmldebugtranslationservice.cpp:266
QQmlDebugTranslationServicePrivate::enableWatchTranslations
bool enableWatchTranslations
Definition
qqmldebugtranslationservice.cpp:268
QQmlDebugTranslationServicePrivate::watchTextElides
bool watchTextElides
Definition
qqmldebugtranslationservice.cpp:263
QQmlDebugTranslationServicePrivate::translatableTextOccurrenceTimer
QTimer translatableTextOccurrenceTimer
Definition
qqmldebugtranslationservice.cpp:269
QQmlPreviewServiceImpl
Definition
qqmlpreviewservice.h:31
QQmlPreviewServiceImpl::currentRootItem
QQuickItem * currentRootItem()
Definition
qqmlpreviewservice.cpp:226
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
operator<<
QDebug operator<<(QDebug dbg, const QFileInfo &fi)
Definition
qfileinfo.cpp:1830
translationIdString
static QString translationIdString(const QQmlTranslation::QsTrData &data)
Definition
qqmldebugtranslationservice.cpp:50
qtdeclarative
src
plugins
qmltooling
qmldbg_preview
qqmldebugtranslationservice.cpp
Generated on
for Qt by
1.18.0