Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qwindowsuiatextrangeprovider.cpp
Go to the documentation of this file.
1// Copyright (C) 2017 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
4#include <QtGui/qtguiglobal.h>
5#if QT_CONFIG(accessibility)
6
9#include "qwindowsuiautils.h"
10#include "qwindowscontext.h"
11
12#include <QtGui/qaccessible.h>
13#include <QtCore/qloggingcategory.h>
14#include <QtCore/qstring.h>
15#include <QtCore/qvarlengtharray.h>
16
18
19using namespace QWindowsUiAutomation;
20
21
22QWindowsUiaTextRangeProvider::QWindowsUiaTextRangeProvider(QAccessible::Id id, int startOffset, int endOffset) :
23 QWindowsUiaBaseProvider(id),
24 m_startOffset(startOffset),
25 m_endOffset(endOffset)
26{
27 qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this << startOffset << endOffset;
28}
29
30QWindowsUiaTextRangeProvider::~QWindowsUiaTextRangeProvider()
31{
32 qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this;
33}
34
35HRESULT QWindowsUiaTextRangeProvider::AddToSelection()
36{
37 qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this;
38 return Select();
39}
40
41HRESULT QWindowsUiaTextRangeProvider::Clone(ITextRangeProvider **pRetVal)
42{
43 qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this;
44
45 if (!pRetVal)
46 return E_INVALIDARG;
47
48 *pRetVal = new QWindowsUiaTextRangeProvider(id(), m_startOffset, m_endOffset);
49 return S_OK;
50}
51
52// Two ranges are considered equal if their start/end points are the same.
53HRESULT QWindowsUiaTextRangeProvider::Compare(ITextRangeProvider *range, BOOL *pRetVal)
54{
55 qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this;
56
57 if (!range || !pRetVal)
58 return E_INVALIDARG;
59
60 auto *targetProvider = static_cast<QWindowsUiaTextRangeProvider *>(range);
61 *pRetVal = ((targetProvider->m_startOffset == m_startOffset) && (targetProvider->m_endOffset == m_endOffset));
62 return S_OK;
63}
64
65// Compare different endpoinds between two providers.
66HRESULT QWindowsUiaTextRangeProvider::CompareEndpoints(TextPatternRangeEndpoint endpoint,
67 ITextRangeProvider *targetRange,
68 TextPatternRangeEndpoint targetEndpoint,
69 int *pRetVal)
70{
71 qCDebug(lcQpaUiAutomation) << __FUNCTION__
72 << "endpoint=" << endpoint << "targetRange=" << targetRange
73 << "targetEndpoint=" << targetEndpoint << "this: " << this;
74
75 if (!targetRange || !pRetVal)
76 return E_INVALIDARG;
77
78 auto *targetProvider = static_cast<QWindowsUiaTextRangeProvider *>(targetRange);
79
80 int point = (endpoint == TextPatternRangeEndpoint_Start) ? m_startOffset : m_endOffset;
81 int targetPoint = (targetEndpoint == TextPatternRangeEndpoint_Start) ?
82 targetProvider->m_startOffset : targetProvider->m_endOffset;
83 *pRetVal = point - targetPoint;
84 return S_OK;
85}
86
87// Expands/normalizes the range for a given text unit.
88HRESULT QWindowsUiaTextRangeProvider::ExpandToEnclosingUnit(TextUnit unit)
89{
90 qCDebug(lcQpaUiAutomation) << __FUNCTION__ << "unit=" << unit << "this: " << this;
91
92 QAccessibleInterface *accessible = accessibleInterface();
93 if (!accessible)
94 return UIA_E_ELEMENTNOTAVAILABLE;
95
96 QAccessibleTextInterface *textInterface = accessible->textInterface();
97 if (!textInterface)
98 return UIA_E_ELEMENTNOTAVAILABLE;
99
100 int len = textInterface->characterCount();
101 if (len < 1) {
102 m_startOffset = 0;
103 m_endOffset = 0;
104 } else {
105 if (unit == TextUnit_Character) {
106 m_startOffset = qBound(0, m_startOffset, len - 1);
107 m_endOffset = m_startOffset + 1;
108 } else {
109 QString text = textInterface->text(0, len);
110 const int start = m_startOffset >= 0 && m_startOffset < len
111 ? m_startOffset : len - 1;
112 for (int t = start; t >= 0; --t) {
113 if (!isTextUnitSeparator(unit, text[t]) && ((t == 0) || isTextUnitSeparator(unit, text[t - 1]))) {
114 m_startOffset = t;
115 break;
116 }
117 }
118 for (int t = m_startOffset; t < len; ++t) {
119 if ((t == len - 1) || (isTextUnitSeparator(unit, text[t]) && ((unit == TextUnit_Word) || !isTextUnitSeparator(unit, text[t + 1])))) {
120 m_endOffset = t + 1;
121 break;
122 }
123 }
124 }
125 }
126 return S_OK;
127}
128
129// Not supported.
130HRESULT QWindowsUiaTextRangeProvider::FindAttribute(TEXTATTRIBUTEID /* attributeId */,
131 VARIANT /* val */, BOOL /* backward */,
132 ITextRangeProvider **pRetVal)
133{
134 if (!pRetVal)
135 return E_INVALIDARG;
136 *pRetVal = nullptr;
137 return S_OK;
138}
139
140// Returns the value of a given attribute.
141HRESULT STDMETHODCALLTYPE QWindowsUiaTextRangeProvider::GetAttributeValue(TEXTATTRIBUTEID attributeId,
142 VARIANT *pRetVal)
143{
144 qCDebug(lcQpaUiAutomation) << __FUNCTION__ << "attributeId=" << attributeId << "this: " << this;
145
146 if (!pRetVal)
147 return E_INVALIDARG;
148 clearVariant(pRetVal);
149
150 QAccessibleInterface *accessible = accessibleInterface();
151 if (!accessible)
152 return UIA_E_ELEMENTNOTAVAILABLE;
153
154 QAccessibleTextInterface *textInterface = accessible->textInterface();
155 if (!textInterface)
156 return UIA_E_ELEMENTNOTAVAILABLE;
157
158 switch (attributeId) {
159 case UIA_IsReadOnlyAttributeId:
160 setVariantBool(accessible->state().readOnly, pRetVal);
161 break;
162 case UIA_CaretPositionAttributeId:
163 if (textInterface->cursorPosition() == 0)
164 setVariantI4(CaretPosition_BeginningOfLine, pRetVal);
165 else if (textInterface->cursorPosition() == textInterface->characterCount())
166 setVariantI4(CaretPosition_EndOfLine, pRetVal);
167 else
168 setVariantI4(CaretPosition_Unknown, pRetVal);
169 break;
170 case UIA_StrikethroughStyleAttributeId:
171 {
172 const QString value = valueForIA2Attribute(textInterface, QStringLiteral("text-line-through-type"));
173 if (value.isEmpty())
174 break;
175 const TextDecorationLineStyle uiaLineStyle = uiaLineStyleForIA2LineStyle(value);
176 setVariantI4(uiaLineStyle, pRetVal);
177 break;
178 }
179 default:
180 break;
181 }
182 return S_OK;
183}
184
185// Returns an array of bounding rectangles for text lines within the range.
186HRESULT QWindowsUiaTextRangeProvider::GetBoundingRectangles(SAFEARRAY **pRetVal)
187{
188 qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this;
189
190 if (!pRetVal)
191 return E_INVALIDARG;
192
193 QAccessibleInterface *accessible = accessibleInterface();
194 if (!accessible)
195 return UIA_E_ELEMENTNOTAVAILABLE;
196
197 QAccessibleTextInterface *textInterface = accessible->textInterface();
198 if (!textInterface)
199 return UIA_E_ELEMENTNOTAVAILABLE;
200
201 QWindow *window = windowForAccessible(accessible);
202 if (!window)
203 return UIA_E_ELEMENTNOTAVAILABLE;
204
205 int len = textInterface->characterCount();
206 QVarLengthArray<QRect> rectList;
207
208 if ((m_startOffset >= 0) && (m_endOffset <= len) && (m_startOffset < m_endOffset)) {
209 int start, end;
210 textInterface->textAtOffset(m_startOffset, QAccessible::LineBoundary, &start, &end);
211 while ((start >= 0) && (end >= 0)) {
212 int startRange = qMax(start, m_startOffset);
213 int endRange = qMin(end, m_endOffset);
214 if (startRange < endRange) {
215 // Calculates a bounding rectangle for the line and adds it to the list.
216 const QRect startRect = textInterface->characterRect(startRange);
217 const QRect endRect = textInterface->characterRect(endRange - 1);
218 const QRect lineRect(qMin(startRect.x(), endRect.x()),
219 qMin(startRect.y(), endRect.y()),
220 qMax(startRect.x() + startRect.width(), endRect.x() + endRect.width()) - qMin(startRect.x(), endRect.x()),
221 qMax(startRect.y() + startRect.height(), endRect.y() + endRect.height()) - qMin(startRect.y(), endRect.y()));
222 rectList.append(lineRect);
223 }
224 if (end >= len) break;
225 textInterface->textAfterOffset(end + 1, QAccessible::LineBoundary, &start, &end);
226 }
227 }
228
229 if ((*pRetVal = SafeArrayCreateVector(VT_R8, 0, 4 * rectList.size()))) {
230 for (int i = 0; i < rectList.size(); ++i) {
231 // Scale rect for high DPI screens.
232 UiaRect uiaRect;
233 rectToNativeUiaRect(rectList[i], window, &uiaRect);
234 double coords[4] = { uiaRect.left, uiaRect.top, uiaRect.width, uiaRect.height };
235 for (int j = 0; j < 4; ++j) {
236 LONG idx = 4 * i + j;
237 SafeArrayPutElement(*pRetVal, &idx, &coords[j]);
238 }
239 }
240 }
241 return S_OK;
242}
243
244// Returns an array of children elements embedded within the range.
245HRESULT QWindowsUiaTextRangeProvider::GetChildren(SAFEARRAY **pRetVal)
246{
247 qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this;
248
249 if (!pRetVal)
250 return E_INVALIDARG;
251 // Not supporting any children.
252 *pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, 0);
253 return S_OK;
254}
255
256// Returns a provider for the enclosing element (text to which the range belongs).
257HRESULT QWindowsUiaTextRangeProvider::GetEnclosingElement(IRawElementProviderSimple **pRetVal)
258{
259 qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this;
260
261 if (!pRetVal)
262 return E_INVALIDARG;
263
264 QAccessibleInterface *accessible = accessibleInterface();
265 if (!accessible)
266 return UIA_E_ELEMENTNOTAVAILABLE;
267
268 *pRetVal = QWindowsUiaMainProvider::providerForAccessible(accessible);
269 return S_OK;
270}
271
272// Gets the text within the range.
273HRESULT QWindowsUiaTextRangeProvider::GetText(int maxLength, BSTR *pRetVal)
274{
275 qCDebug(lcQpaUiAutomation) << __FUNCTION__ << maxLength << "this: " << this;
276
277 if (!pRetVal)
278 return E_INVALIDARG;
279 *pRetVal = nullptr;
280
281 QAccessibleInterface *accessible = accessibleInterface();
282 if (!accessible)
283 return UIA_E_ELEMENTNOTAVAILABLE;
284
285 QAccessibleTextInterface *textInterface = accessible->textInterface();
286 if (!textInterface)
287 return UIA_E_ELEMENTNOTAVAILABLE;
288
289 int len = textInterface->characterCount();
290 QString rangeText;
291 if ((m_startOffset >= 0) && (m_endOffset <= len) && (m_startOffset < m_endOffset))
292 rangeText = textInterface->text(m_startOffset, m_endOffset);
293
294 if ((maxLength > -1) && (rangeText.size() > maxLength))
295 rangeText.truncate(maxLength);
296 *pRetVal = bStrFromQString(rangeText);
297 return S_OK;
298}
299
300// Moves the range a specified number of units (and normalizes it).
301HRESULT QWindowsUiaTextRangeProvider::Move(TextUnit unit, int count, int *pRetVal)
302{
303 qCDebug(lcQpaUiAutomation) << __FUNCTION__ << "unit=" << unit << "count=" << count << "this: " << this;
304
305 if (!pRetVal)
306 return E_INVALIDARG;
307 *pRetVal = 0;
308
309 QAccessibleInterface *accessible = accessibleInterface();
310 if (!accessible)
311 return UIA_E_ELEMENTNOTAVAILABLE;
312
313 QAccessibleTextInterface *textInterface = accessible->textInterface();
314 if (!textInterface)
315 return UIA_E_ELEMENTNOTAVAILABLE;
316
317 int len = textInterface->characterCount();
318
319 if (len < 1 || count == 0) // MSDN: "Zero has no effect."
320 return S_OK;
321
322 if (unit == TextUnit_Character) {
323 // Moves the start point, ensuring it lies within the bounds.
324 int start = qBound(0, m_startOffset + count, len);
325 // If range was initially empty, leaves it as is; otherwise, normalizes it to one char.
326 m_endOffset = (m_endOffset > m_startOffset) ? qMin(start + 1, len) : start;
327 *pRetVal = start - m_startOffset; // Returns the actually moved distance.
328 m_startOffset = start;
329 } else {
330 if (count > 0) {
331 MoveEndpointByUnit(TextPatternRangeEndpoint_End, unit, count, pRetVal);
332 MoveEndpointByUnit(TextPatternRangeEndpoint_Start, unit, count, pRetVal);
333 } else {
334 MoveEndpointByUnit(TextPatternRangeEndpoint_Start, unit, count, pRetVal);
335 MoveEndpointByUnit(TextPatternRangeEndpoint_End, unit, count, pRetVal);
336 }
337 }
338 return S_OK;
339}
340
341// Copies the value of an end point from one range to another.
342HRESULT QWindowsUiaTextRangeProvider::MoveEndpointByRange(TextPatternRangeEndpoint endpoint,
343 ITextRangeProvider *targetRange,
344 TextPatternRangeEndpoint targetEndpoint)
345{
346 if (!targetRange)
347 return E_INVALIDARG;
348
349 qCDebug(lcQpaUiAutomation) << __FUNCTION__
350 << "endpoint=" << endpoint << "targetRange=" << targetRange << "targetEndpoint=" << targetEndpoint << "this: " << this;
351
352 auto *targetProvider = static_cast<QWindowsUiaTextRangeProvider *>(targetRange);
353
354 int targetPoint = (targetEndpoint == TextPatternRangeEndpoint_Start) ?
355 targetProvider->m_startOffset : targetProvider->m_endOffset;
356
357 // If the moved endpoint crosses the other endpoint, that one is moved too.
358 if (endpoint == TextPatternRangeEndpoint_Start) {
359 m_startOffset = targetPoint;
360 if (m_endOffset < m_startOffset)
361 m_endOffset = m_startOffset;
362 } else {
363 m_endOffset = targetPoint;
364 if (m_endOffset < m_startOffset)
365 m_startOffset = m_endOffset;
366 }
367 return S_OK;
368}
369
370// Moves an endpoint an specific number of units.
371HRESULT QWindowsUiaTextRangeProvider::MoveEndpointByUnit(TextPatternRangeEndpoint endpoint,
372 TextUnit unit, int count,
373 int *pRetVal)
374{
375 qCDebug(lcQpaUiAutomation) << __FUNCTION__
376 << "endpoint=" << endpoint << "unit=" << unit << "count=" << count << "this: " << this;
377
378 if (!pRetVal)
379 return E_INVALIDARG;
380 *pRetVal = 0;
381
382 QAccessibleInterface *accessible = accessibleInterface();
383 if (!accessible)
384 return UIA_E_ELEMENTNOTAVAILABLE;
385
386 QAccessibleTextInterface *textInterface = accessible->textInterface();
387 if (!textInterface)
388 return UIA_E_ELEMENTNOTAVAILABLE;
389
390 int len = textInterface->characterCount();
391
392 if (len < 1)
393 return S_OK;
394
395 if (unit == TextUnit_Character) {
396 if (endpoint == TextPatternRangeEndpoint_Start) {
397 int boundedValue = qBound(0, m_startOffset + count, len);
398 *pRetVal = boundedValue - m_startOffset;
399 m_startOffset = boundedValue;
400 m_endOffset = qBound(m_startOffset, m_endOffset, len);
401 } else {
402 int boundedValue = qBound(0, m_endOffset + count, len);
403 *pRetVal = boundedValue - m_endOffset;
404 m_endOffset = boundedValue;
405 m_startOffset = qBound(0, m_startOffset, m_endOffset);
406 }
407 } else {
408 QString text = textInterface->text(0, len);
409 int moved = 0;
410
411 if (endpoint == TextPatternRangeEndpoint_Start) {
412 if (count > 0) {
413 for (int t = m_startOffset; (t < len - 1) && (moved < count); ++t) {
414 if (isTextUnitSeparator(unit, text[t]) && !isTextUnitSeparator(unit, text[t + 1])) {
415 m_startOffset = t + 1;
416 ++moved;
417 }
418 }
419 m_endOffset = qBound(m_startOffset, m_endOffset, len);
420 } else {
421 const int start = m_startOffset >= 0 && m_startOffset <= len
422 ? m_startOffset : len;
423 for (int t = start - 1; (t >= 0) && (moved > count); --t) {
424 if (!isTextUnitSeparator(unit, text[t]) && ((t == 0) || isTextUnitSeparator(unit, text[t - 1]))) {
425 m_startOffset = t;
426 --moved;
427 }
428 }
429 }
430 } else {
431 if (count > 0) {
432 for (int t = m_endOffset; (t < len) && (moved < count); ++t) {
433 if ((t == len - 1) || (isTextUnitSeparator(unit, text[t]) && ((unit == TextUnit_Word) || !isTextUnitSeparator(unit, text[t + 1])))) {
434 m_endOffset = t + 1;
435 ++moved;
436 }
437 }
438 } else {
439 int end = 0;
440 for (int t = m_endOffset - 2; (t > 0) && (moved > count); --t) {
441 if (isTextUnitSeparator(unit, text[t]) && ((unit == TextUnit_Word) || !isTextUnitSeparator(unit, text[t + 1]))) {
442 end = t + 1;
443 --moved;
444 }
445 }
446 m_endOffset = end;
447 m_startOffset = qBound(0, m_startOffset, m_endOffset);
448 }
449 }
450 *pRetVal = moved;
451 }
452 return S_OK;
453}
454
455HRESULT QWindowsUiaTextRangeProvider::RemoveFromSelection()
456{
457 qCDebug(lcQpaUiAutomation) << __FUNCTION__;
458 // unselects all
459 return unselect();
460}
461
462// Scrolls the range into view.
463HRESULT QWindowsUiaTextRangeProvider::ScrollIntoView(BOOL alignToTop)
464{
465 qCDebug(lcQpaUiAutomation) << __FUNCTION__ << "alignToTop=" << alignToTop << "this: " << this;
466
467 QAccessibleInterface *accessible = accessibleInterface();
468 if (!accessible)
469 return UIA_E_ELEMENTNOTAVAILABLE;
470
471 QAccessibleTextInterface *textInterface = accessible->textInterface();
472 if (!textInterface)
473 return UIA_E_ELEMENTNOTAVAILABLE;
474
475 textInterface->scrollToSubstring(m_startOffset, m_endOffset);
476 return S_OK;
477}
478
479// Selects the range.
480HRESULT QWindowsUiaTextRangeProvider::Select()
481{
482 qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this;
483
484 QAccessibleInterface *accessible = accessibleInterface();
485 if (!accessible)
486 return UIA_E_ELEMENTNOTAVAILABLE;
487
488 QAccessibleTextInterface *textInterface = accessible->textInterface();
489 if (!textInterface)
490 return UIA_E_ELEMENTNOTAVAILABLE;
491
492 // unselects all and adds a new selection
493 unselect();
494 textInterface->addSelection(m_startOffset, m_endOffset);
495 return S_OK;
496}
497
498// Not supported.
499HRESULT QWindowsUiaTextRangeProvider::FindText(BSTR /* text */, BOOL /* backward */,
500 BOOL /* ignoreCase */,
501 ITextRangeProvider **pRetVal)
502{
503 if (!pRetVal)
504 return E_INVALIDARG;
505 *pRetVal = nullptr;
506 return S_OK;
507}
508
509// Removes all selected ranges from the text element.
510HRESULT QWindowsUiaTextRangeProvider::unselect()
511{
512 qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this;
513
514 QAccessibleInterface *accessible = accessibleInterface();
515 if (!accessible)
516 return UIA_E_ELEMENTNOTAVAILABLE;
517
518 QAccessibleTextInterface *textInterface = accessible->textInterface();
519 if (!textInterface)
520 return UIA_E_ELEMENTNOTAVAILABLE;
521
522 int selCount = textInterface->selectionCount();
523
524 for (int i = selCount - 1; i >= 0; --i)
525 textInterface->removeSelection(i);
526 return S_OK;
527}
528
529// helper method to retrieve the value of the given IAccessible2 text attribute,
530// or an empty string if not set
531QString QWindowsUiaTextRangeProvider::valueForIA2Attribute(QAccessibleTextInterface *textInterface,
532 const QString &key)
533{
534 Q_ASSERT(textInterface);
535
536 int startOffset;
537 int endOffset;
538 const QString attributes = textInterface->attributes(m_startOffset, &startOffset, &endOffset);
539 // don't report if attributes don't apply for the whole range
540 if (startOffset > m_startOffset || endOffset < m_endOffset)
541 return {};
542
543 for (auto attr : QStringTokenizer{attributes, u';'})
544 {
545 const QList<QStringView> items = attr.split(u':', Qt::SkipEmptyParts, Qt::CaseSensitive);
546 if (items.count() == 2 && items[0] == key)
547 return items[1].toString();
548 }
549
550 return {};
551}
552
553TextDecorationLineStyle QWindowsUiaTextRangeProvider::uiaLineStyleForIA2LineStyle(const QString &ia2LineStyle)
554{
555 if (ia2LineStyle == QStringLiteral("none"))
556 return TextDecorationLineStyle_None;
557 if (ia2LineStyle == QStringLiteral("single"))
558 return TextDecorationLineStyle_Single;
559 if (ia2LineStyle == QStringLiteral("double"))
560 return TextDecorationLineStyle_Double;
561
562 return TextDecorationLineStyle_Other;
563}
564
566
567#endif // QT_CONFIG(accessibility)
qsizetype count() const noexcept
Definition qlist.h:398
\inmodule QtCore\reentrant
Definition qrect.h:30
constexpr int height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:239
constexpr int x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:185
constexpr int width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:236
constexpr int y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:188
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
\inmodule QtGui
Definition qwindow.h:63
QString text
constexpr uint8_t Select
Combined button and popup list for selecting options.
@ CaseSensitive
@ SkipEmptyParts
Definition qnamespace.h:128
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define qCDebug(category,...)
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qBound(const T &min, const T &val, const T &max)
Definition qminmax.h:44
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
GLuint64 key
GLuint GLuint end
GLsizei const GLubyte GLsizei GLenum const void * coords
GLenum GLuint id
[7]
GLenum GLenum GLsizei count
GLsizei range
GLuint start
GLsizei maxLength
GLdouble GLdouble t
Definition qopenglext.h:243
GLenum GLsizei len
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define QStringLiteral(str)
long HRESULT
QList< QTreeWidgetItem * > items
aWidget window() -> setWindowTitle("New Window Title")
[2]