widgets/qtextbrowser.cpp

Source codeSwitch to Preprocessed file
LineSource CodeCoverage
1/**************************************************************************** -
2** -
3** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -
4** Contact: http://www.qt-project.org/legal -
5** -
6** This file is part of the QtGui module of the Qt Toolkit. -
7** -
8** $QT_BEGIN_LICENSE:LGPL$ -
9** Commercial License Usage -
10** Licensees holding valid commercial Qt licenses may use this file in -
11** accordance with the commercial license agreement provided with the -
12** Software or, alternatively, in accordance with the terms contained in -
13** a written agreement between you and Digia. For licensing terms and -
14** conditions see http://qt.digia.com/licensing. For further information -
15** use the contact form at http://qt.digia.com/contact-us. -
16** -
17** GNU Lesser General Public License Usage -
18** Alternatively, this file may be used under the terms of the GNU Lesser -
19** General Public License version 2.1 as published by the Free Software -
20** Foundation and appearing in the file LICENSE.LGPL included in the -
21** packaging of this file. Please review the following information to -
22** ensure the GNU Lesser General Public License version 2.1 requirements -
23** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -
24** -
25** In addition, as a special exception, Digia gives you certain additional -
26** rights. These rights are described in the Digia Qt LGPL Exception -
27** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -
28** -
29** GNU General Public License Usage -
30** Alternatively, this file may be used under the terms of the GNU -
31** General Public License version 3.0 as published by the Free Software -
32** Foundation and appearing in the file LICENSE.GPL included in the -
33** packaging of this file. Please review the following information to -
34** ensure the GNU General Public License version 3.0 requirements will be -
35** met: http://www.gnu.org/copyleft/gpl.html. -
36** -
37** -
38** $QT_END_LICENSE$ -
39** -
40****************************************************************************/ -
41 -
42#include "qtextbrowser.h" -
43#include "qtextedit_p.h" -
44 -
45#ifndef QT_NO_TEXTBROWSER -
46 -
47#include <qstack.h> -
48#include <qapplication.h> -
49#include <qevent.h> -
50#include <qdesktopwidget.h> -
51#include <qdebug.h> -
52#include <qabstracttextdocumentlayout.h> -
53#include "private/qtextdocumentlayout_p.h" -
54#include <qtextcodec.h> -
55#include <qpainter.h> -
56#include <qdir.h> -
57#include <qwhatsthis.h> -
58#include <qtextobject.h> -
59#include <qdesktopservices.h> -
60 -
61QT_BEGIN_NAMESPACE -
62 -
63class QTextBrowserPrivate : public QTextEditPrivate -
64{ -
65 Q_DECLARE_PUBLIC(QTextBrowser) -
66public: -
67 inline QTextBrowserPrivate() -
68 : textOrSourceChanged(false), forceLoadOnSourceChange(false), openExternalLinks(false), -
69 openLinks(true) -
70#ifdef QT_KEYPAD_NAVIGATION -
71 , lastKeypadScrollValue(-1) -
72#endif -
73 {}
executed: }
Execution Count:24
24
74 -
75 void init(); -
76 -
77 struct HistoryEntry { -
78 inline HistoryEntry() -
79 : hpos(0), vpos(0), focusIndicatorPosition(-1), -
80 focusIndicatorAnchor(-1) {}
executed: }
Execution Count:103
103
81 QUrl url; -
82 QString title; -
83 int hpos; -
84 int vpos; -
85 int focusIndicatorPosition, focusIndicatorAnchor; -
86 }; -
87 -
88 HistoryEntry history(int i) const -
89 { -
90 if (i <= 0)
evaluated: i <= 0
TRUEFALSE
yes
Evaluation Count:12
yes
Evaluation Count:6
6-12
91 if (-i < stack.count())
evaluated: -i < stack.count()
TRUEFALSE
yes
Evaluation Count:5
yes
Evaluation Count:7
5-7
92 return stack[stack.count()+i-1];
executed: return stack[stack.count()+i-1];
Execution Count:5
5
93 else -
94 return HistoryEntry();
executed: return HistoryEntry();
Execution Count:7
7
95 else -
96 if (i <= forwardStack.count())
evaluated: i <= forwardStack.count()
TRUEFALSE
yes
Evaluation Count:1
yes
Evaluation Count:5
1-5
97 return forwardStack[forwardStack.count()-i];
executed: return forwardStack[forwardStack.count()-i];
Execution Count:1
1
98 else -
99 return HistoryEntry();
executed: return HistoryEntry();
Execution Count:5
5
100 } -
101 -
102 -
103 HistoryEntry createHistoryEntry() const; -
104 void restoreHistoryEntry(const HistoryEntry entry); -
105 -
106 QStack<HistoryEntry> stack; -
107 QStack<HistoryEntry> forwardStack; -
108 QUrl home; -
109 QUrl currentURL; -
110 -
111 QStringList searchPaths; -
112 -
113 /*flag necessary to give the linkClicked() signal some meaningful -
114 semantics when somebody connected to it calls setText() or -
115 setSource() */ -
116 bool textOrSourceChanged; -
117 bool forceLoadOnSourceChange; -
118 -
119 bool openExternalLinks; -
120 bool openLinks; -
121 -
122#ifndef QT_NO_CURSOR -
123 QCursor oldCursor; -
124#endif -
125 -
126 QString findFile(const QUrl &name) const; -
127 -
128 inline void _q_documentModified() -
129 { -
130 textOrSourceChanged = true;
executed (the execution status of this line is deduced): textOrSourceChanged = true;
-
131 forceLoadOnSourceChange = !currentURL.path().isEmpty();
executed (the execution status of this line is deduced): forceLoadOnSourceChange = !currentURL.path().isEmpty();
-
132 }
executed: }
Execution Count:53
53
133 -
134 void _q_activateAnchor(const QString &href); -
135 void _q_highlightLink(const QString &href); -
136 -
137 void setSource(const QUrl &url); -
138 -
139 // re-imlemented from QTextEditPrivate -
140 virtual QUrl resolveUrl(const QUrl &url) const; -
141 inline QUrl resolveUrl(const QString &url) const -
142 { return resolveUrl(QUrl(url)); }
executed: return resolveUrl(QUrl(url));
Execution Count:6
6
143 -
144#ifdef QT_KEYPAD_NAVIGATION -
145 void keypadMove(bool next); -
146 QTextCursor prevFocus; -
147 int lastKeypadScrollValue; -
148#endif -
149}; -
150 -
151QString QTextBrowserPrivate::findFile(const QUrl &name) const -
152{ -
153 QString fileName;
executed (the execution status of this line is deduced): QString fileName;
-
154 if (name.scheme() == QLatin1String("qrc"))
evaluated: name.scheme() == QLatin1String("qrc")
TRUEFALSE
yes
Evaluation Count:3
yes
Evaluation Count:49
3-49
155 fileName = QLatin1String(":/") + name.path();
executed: fileName = QLatin1String(":/") + name.path();
Execution Count:3
3
156 else if (name.scheme().isEmpty())
evaluated: name.scheme().isEmpty()
TRUEFALSE
yes
Evaluation Count:4
yes
Evaluation Count:45
4-45
157 fileName = name.path();
executed: fileName = name.path();
Execution Count:4
4
158 else -
159 fileName = name.toLocalFile();
executed: fileName = name.toLocalFile();
Execution Count:45
45
160 -
161 if (QFileInfo(fileName).isAbsolute())
evaluated: QFileInfo(fileName).isAbsolute()
TRUEFALSE
yes
Evaluation Count:19
yes
Evaluation Count:33
19-33
162 return fileName;
executed: return fileName;
Execution Count:19
19
163 -
164 foreach (QString path, searchPaths) {
never executed (the execution status of this line is deduced): for (QForeachContainer<__typeof__(searchPaths)> _container_(searchPaths); !_container_.brk && _container_.i != _container_.e; __extension__ ({ ++_container_.brk; ++_container_.i; })) for (QString path = *_container_.i;; __extension__ ({--_container_.brk; break;})) {
-
165 if (!path.endsWith(QLatin1Char('/')))
never evaluated: !path.endsWith(QLatin1Char('/'))
0
166 path.append(QLatin1Char('/'));
never executed: path.append(QLatin1Char('/'));
0
167 path.append(fileName);
never executed (the execution status of this line is deduced): path.append(fileName);
-
168 if (QFileInfo(path).isReadable())
never evaluated: QFileInfo(path).isReadable()
0
169 return path;
never executed: return path;
0
170 }
never executed: }
0
171 -
172 return fileName;
executed: return fileName;
Execution Count:33
33
173} -
174 -
175QUrl QTextBrowserPrivate::resolveUrl(const QUrl &url) const -
176{ -
177 if (!url.isRelative())
evaluated: !url.isRelative()
TRUEFALSE
yes
Evaluation Count:131
yes
Evaluation Count:29
29-131
178 return url;
executed: return url;
Execution Count:131
131
179 -
180 // For the second case QUrl can merge "#someanchor" with "foo.html" -
181 // correctly to "foo.html#someanchor" -
182 if (!(currentURL.isRelative()
evaluated: currentURL.isRelative()
TRUEFALSE
yes
Evaluation Count:12
yes
Evaluation Count:17
12-17
183 || (currentURL.scheme() == QLatin1String("file")
evaluated: currentURL.scheme() == QLatin1String("file")
TRUEFALSE
yes
Evaluation Count:13
yes
Evaluation Count:4
4-13
184 && !QFileInfo(currentURL.toLocalFile()).isAbsolute()))
evaluated: !QFileInfo(currentURL.toLocalFile()).isAbsolute()
TRUEFALSE
yes
Evaluation Count:11
yes
Evaluation Count:2
2-11
185 || (url.hasFragment() && url.path().isEmpty())) {
partially evaluated: url.hasFragment()
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:23
never evaluated: url.path().isEmpty()
0-23
186 return currentURL.resolved(url);
executed: return currentURL.resolved(url);
Execution Count:6
6
187 } -
188 -
189 // this is our last resort when current url and new url are both relative -
190 // we try to resolve against the current working directory in the local -
191 // file system. -
192 QFileInfo fi(currentURL.toLocalFile());
executed (the execution status of this line is deduced): QFileInfo fi(currentURL.toLocalFile());
-
193 if (fi.exists()) {
evaluated: fi.exists()
TRUEFALSE
yes
Evaluation Count:11
yes
Evaluation Count:12
11-12
194 return QUrl::fromLocalFile(fi.absolutePath() + QDir::separator()).resolved(url);
executed: return QUrl::fromLocalFile(fi.absolutePath() + QDir::separator()).resolved(url);
Execution Count:11
11
195 } -
196 -
197 return url;
executed: return url;
Execution Count:12
12
198} -
199 -
200void QTextBrowserPrivate::_q_activateAnchor(const QString &href) -
201{ -
202 if (href.isEmpty())
partially evaluated: href.isEmpty()
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:6
0-6
203 return;
never executed: return;
0
204 Q_Q(QTextBrowser);
executed (the execution status of this line is deduced): QTextBrowser * const q = q_func();
-
205 -
206#ifndef QT_NO_CURSOR -
207 viewport->setCursor(oldCursor);
executed (the execution status of this line is deduced): viewport->setCursor(oldCursor);
-
208#endif -
209 -
210 const QUrl url = resolveUrl(href);
executed (the execution status of this line is deduced): const QUrl url = resolveUrl(href);
-
211 -
212 if (!openLinks) {
evaluated: !openLinks
TRUEFALSE
yes
Evaluation Count:1
yes
Evaluation Count:5
1-5
213 emit q->anchorClicked(url);
executed (the execution status of this line is deduced): q->anchorClicked(url);
-
214 return;
executed: return;
Execution Count:1
1
215 } -
216 -
217 textOrSourceChanged = false;
executed (the execution status of this line is deduced): textOrSourceChanged = false;
-
218 -
219#ifndef QT_NO_DESKTOPSERVICES -
220 if ((openExternalLinks
partially evaluated: openExternalLinks
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:5
0-5
221 && url.scheme() != QLatin1String("file")
never evaluated: url.scheme() != QLatin1String("file")
0
222 && url.scheme() != QLatin1String("qrc")
never evaluated: url.scheme() != QLatin1String("qrc")
0
223 && !url.isRelative())
never evaluated: !url.isRelative()
0
224 || (url.isRelative() && !currentURL.isRelative()
partially evaluated: url.isRelative()
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:5
never evaluated: !currentURL.isRelative()
0-5
225 && currentURL.scheme() != QLatin1String("file")
never evaluated: currentURL.scheme() != QLatin1String("file")
0
226 && currentURL.scheme() != QLatin1String("qrc"))) {
never evaluated: currentURL.scheme() != QLatin1String("qrc")
0
227 QDesktopServices::openUrl(url);
never executed (the execution status of this line is deduced): QDesktopServices::openUrl(url);
-
228 return;
never executed: return;
0
229 } -
230#endif -
231 -
232 emit q->anchorClicked(url);
executed (the execution status of this line is deduced): q->anchorClicked(url);
-
233 -
234 if (textOrSourceChanged)
partially evaluated: textOrSourceChanged
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:5
0-5
235 return;
never executed: return;
0
236 -
237 q->setSource(url);
executed (the execution status of this line is deduced): q->setSource(url);
-
238}
executed: }
Execution Count:5
5
239 -
240void QTextBrowserPrivate::_q_highlightLink(const QString &anchor) -
241{ -
242 Q_Q(QTextBrowser);
never executed (the execution status of this line is deduced): QTextBrowser * const q = q_func();
-
243 if (anchor.isEmpty()) {
never evaluated: anchor.isEmpty()
0
244#ifndef QT_NO_CURSOR -
245 if (viewport->cursor().shape() != Qt::PointingHandCursor)
never evaluated: viewport->cursor().shape() != Qt::PointingHandCursor
0
246 oldCursor = viewport->cursor();
never executed: oldCursor = viewport->cursor();
0
247 viewport->setCursor(oldCursor);
never executed (the execution status of this line is deduced): viewport->setCursor(oldCursor);
-
248#endif -
249 emit q->highlighted(QUrl());
never executed (the execution status of this line is deduced): q->highlighted(QUrl());
-
250 emit q->highlighted(QString());
never executed (the execution status of this line is deduced): q->highlighted(QString());
-
251 } else {
never executed: }
0
252#ifndef QT_NO_CURSOR -
253 viewport->setCursor(Qt::PointingHandCursor);
never executed (the execution status of this line is deduced): viewport->setCursor(Qt::PointingHandCursor);
-
254#endif -
255 -
256 const QUrl url = resolveUrl(anchor);
never executed (the execution status of this line is deduced): const QUrl url = resolveUrl(anchor);
-
257 emit q->highlighted(url);
never executed (the execution status of this line is deduced): q->highlighted(url);
-
258 // convenience to ease connecting to QStatusBar::showMessage(const QString &) -
259 emit q->highlighted(url.toString());
never executed (the execution status of this line is deduced): q->highlighted(url.toString());
-
260 }
never executed: }
0
261} -
262 -
263void QTextBrowserPrivate::setSource(const QUrl &url) -
264{ -
265 Q_Q(QTextBrowser);
executed (the execution status of this line is deduced): QTextBrowser * const q = q_func();
-
266#ifndef QT_NO_CURSOR -
267 if (q->isVisible())
evaluated: q->isVisible()
TRUEFALSE
yes
Evaluation Count:51
yes
Evaluation Count:3
3-51
268 QApplication::setOverrideCursor(Qt::WaitCursor);
executed: QApplication::setOverrideCursor(Qt::WaitCursor);
Execution Count:51
51
269#endif -
270 textOrSourceChanged = true;
executed (the execution status of this line is deduced): textOrSourceChanged = true;
-
271 -
272 QString txt;
executed (the execution status of this line is deduced): QString txt;
-
273 -
274 bool doSetText = false;
executed (the execution status of this line is deduced): bool doSetText = false;
-
275 -
276 QUrl currentUrlWithoutFragment = currentURL;
executed (the execution status of this line is deduced): QUrl currentUrlWithoutFragment = currentURL;
-
277 currentUrlWithoutFragment.setFragment(QString());
executed (the execution status of this line is deduced): currentUrlWithoutFragment.setFragment(QString());
-
278 QUrl newUrlWithoutFragment = currentURL.resolved(url);
executed (the execution status of this line is deduced): QUrl newUrlWithoutFragment = currentURL.resolved(url);
-
279 newUrlWithoutFragment.setFragment(QString());
executed (the execution status of this line is deduced): newUrlWithoutFragment.setFragment(QString());
-
280 -
281 if (url.isValid()
partially evaluated: url.isValid()
TRUEFALSE
yes
Evaluation Count:54
no
Evaluation Count:0
0-54
282 && (newUrlWithoutFragment != currentUrlWithoutFragment || forceLoadOnSourceChange)) {
evaluated: newUrlWithoutFragment != currentUrlWithoutFragment
TRUEFALSE
yes
Evaluation Count:48
yes
Evaluation Count:6
partially evaluated: forceLoadOnSourceChange
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:6
0-48
283 QVariant data = q->loadResource(QTextDocument::HtmlResource, resolveUrl(url));
executed (the execution status of this line is deduced): QVariant data = q->loadResource(QTextDocument::HtmlResource, resolveUrl(url));
-
284 if (data.type() == QVariant::String) {
evaluated: data.type() == QVariant::String
TRUEFALSE
yes
Evaluation Count:3
yes
Evaluation Count:45
3-45
285 txt = data.toString();
executed (the execution status of this line is deduced): txt = data.toString();
-
286 } else if (data.type() == QVariant::ByteArray) {
executed: }
Execution Count:3
partially evaluated: data.type() == QVariant::ByteArray
TRUEFALSE
yes
Evaluation Count:45
no
Evaluation Count:0
0-45
287#ifndef QT_NO_TEXTCODEC -
288 QByteArray ba = data.toByteArray();
executed (the execution status of this line is deduced): QByteArray ba = data.toByteArray();
-
289 QTextCodec *codec = Qt::codecForHtml(ba);
executed (the execution status of this line is deduced): QTextCodec *codec = Qt::codecForHtml(ba);
-
290 txt = codec->toUnicode(ba);
executed (the execution status of this line is deduced): txt = codec->toUnicode(ba);
-
291#else -
292 txt = data.toString(); -
293#endif -
294 }
executed: }
Execution Count:45
45
295 if (txt.isEmpty())
partially evaluated: txt.isEmpty()
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:48
0-48
296 qWarning("QTextBrowser: No document for %s", url.toString().toLatin1().constData());
never executed: QMessageLogger("widgets/qtextbrowser.cpp", 296, __PRETTY_FUNCTION__).warning("QTextBrowser: No document for %s", url.toString().toLatin1().constData());
0
297 -
298 if (q->isVisible()) {
evaluated: q->isVisible()
TRUEFALSE
yes
Evaluation Count:45
yes
Evaluation Count:3
3-45
299 QString firstTag = txt.left(txt.indexOf(QLatin1Char('>')) + 1);
executed (the execution status of this line is deduced): QString firstTag = txt.left(txt.indexOf(QLatin1Char('>')) + 1);
-
300 if (firstTag.startsWith(QLatin1String("<qt")) && firstTag.contains(QLatin1String("type")) && firstTag.contains(QLatin1String("detail"))) {
partially evaluated: firstTag.startsWith(QLatin1String("<qt"))
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:45
never evaluated: firstTag.contains(QLatin1String("type"))
never evaluated: firstTag.contains(QLatin1String("detail"))
0-45
301#ifndef QT_NO_CURSOR -
302 QApplication::restoreOverrideCursor();
never executed (the execution status of this line is deduced): QApplication::restoreOverrideCursor();
-
303#endif -
304#ifndef QT_NO_WHATSTHIS -
305 QWhatsThis::showText(QCursor::pos(), txt, q);
never executed (the execution status of this line is deduced): QWhatsThis::showText(QCursor::pos(), txt, q);
-
306#endif -
307 return;
never executed: return;
0
308 } -
309 }
executed: }
Execution Count:45
45
310 -
311 currentURL = resolveUrl(url);
executed (the execution status of this line is deduced): currentURL = resolveUrl(url);
-
312 doSetText = true;
executed (the execution status of this line is deduced): doSetText = true;
-
313 }
executed: }
Execution Count:48
48
314 -
315 if (!home.isValid())
evaluated: !home.isValid()
TRUEFALSE
yes
Evaluation Count:14
yes
Evaluation Count:40
14-40
316 home = url;
executed: home = url;
Execution Count:14
14
317 -
318 if (doSetText) {
evaluated: doSetText
TRUEFALSE
yes
Evaluation Count:48
yes
Evaluation Count:6
6-48
319#ifndef QT_NO_TEXTHTMLPARSER -
320 q->QTextEdit::setHtml(txt);
executed (the execution status of this line is deduced): q->QTextEdit::setHtml(txt);
-
321 q->document()->setMetaInformation(QTextDocument::DocumentUrl, currentURL.toString());
executed (the execution status of this line is deduced): q->document()->setMetaInformation(QTextDocument::DocumentUrl, currentURL.toString());
-
322#else -
323 q->QTextEdit::setPlainText(txt); -
324#endif -
325 -
326#ifdef QT_KEYPAD_NAVIGATION -
327 prevFocus.movePosition(QTextCursor::Start); -
328#endif -
329 }
executed: }
Execution Count:48
48
330 -
331 forceLoadOnSourceChange = false;
executed (the execution status of this line is deduced): forceLoadOnSourceChange = false;
-
332 -
333 if (!url.fragment().isEmpty()) {
evaluated: !url.fragment().isEmpty()
TRUEFALSE
yes
Evaluation Count:4
yes
Evaluation Count:50
4-50
334 q->scrollToAnchor(url.fragment());
executed (the execution status of this line is deduced): q->scrollToAnchor(url.fragment());
-
335 } else {
executed: }
Execution Count:4
4
336 hbar->setValue(0);
executed (the execution status of this line is deduced): hbar->setValue(0);
-
337 vbar->setValue(0);
executed (the execution status of this line is deduced): vbar->setValue(0);
-
338 }
executed: }
Execution Count:50
50
339#ifdef QT_KEYPAD_NAVIGATION -
340 lastKeypadScrollValue = vbar->value(); -
341 emit q->highlighted(QUrl()); -
342 emit q->highlighted(QString()); -
343#endif -
344 -
345#ifndef QT_NO_CURSOR -
346 if (q->isVisible())
evaluated: q->isVisible()
TRUEFALSE
yes
Evaluation Count:51
yes
Evaluation Count:3
3-51
347 QApplication::restoreOverrideCursor();
executed: QApplication::restoreOverrideCursor();
Execution Count:51
51
348#endif -
349 emit q->sourceChanged(url);
executed (the execution status of this line is deduced): q->sourceChanged(url);
-
350}
executed: }
Execution Count:54
54
351 -
352#ifdef QT_KEYPAD_NAVIGATION -
353void QTextBrowserPrivate::keypadMove(bool next) -
354{ -
355 Q_Q(QTextBrowser); -
356 -
357 const int height = viewport->height(); -
358 const int overlap = qBound(20, height / 5, 40); // XXX arbitrary, but a good balance -
359 const int visibleLinkAmount = overlap; // consistent, but maybe not the best choice (?) -
360 int yOffset = vbar->value(); -
361 int scrollYOffset = qBound(0, next ? yOffset + height - overlap : yOffset - height + overlap, vbar->maximum()); -
362 -
363 bool foundNextAnchor = false; -
364 bool focusIt = false; -
365 int focusedPos = -1; -
366 -
367 QTextCursor anchorToFocus; -
368 -
369 QRectF viewRect = QRectF(0, yOffset, control->size().width(), height); -
370 QRectF newViewRect = QRectF(0, scrollYOffset, control->size().width(), height); -
371 QRectF bothViewRects = viewRect.united(newViewRect); -
372 -
373 // If we don't have a previous anchor, pretend that we had the first/last character -
374 // on the screen selected. -
375 if (prevFocus.isNull()) { -
376 if (next) -
377 prevFocus = control->cursorForPosition(QPointF(0, yOffset)); -
378 else -
379 prevFocus = control->cursorForPosition(QPointF(control->size().width(), yOffset + height)); -
380 } -
381 -
382 // First, check to see if someone has moved the scroll bars independently -
383 if (lastKeypadScrollValue != yOffset) { -
384 // Someone (user or programmatically) has moved us, so we might -
385 // need to start looking from the current position instead of prevFocus -
386 -
387 bool findOnScreen = true; -
388 -
389 // If prevFocus is on screen at all, we just use it. -
390 if (prevFocus.hasSelection()) { -
391 QRectF prevRect = control->selectionRect(prevFocus); -
392 if (viewRect.intersects(prevRect)) -
393 findOnScreen = false; -
394 } -
395 -
396 // Otherwise, we find a new anchor that's on screen. -
397 // Basically, create a cursor with the last/first character -
398 // on screen -
399 if (findOnScreen) { -
400 if (next) -
401 prevFocus = control->cursorForPosition(QPointF(0, yOffset)); -
402 else -
403 prevFocus = control->cursorForPosition(QPointF(control->size().width(), yOffset + height)); -
404 } -
405 foundNextAnchor = control->findNextPrevAnchor(prevFocus, next, anchorToFocus); -
406 } else if (prevFocus.hasSelection()) { -
407 // Check the pathological case that the current anchor is higher -
408 // than the screen, and just scroll through it in that case -
409 QRectF prevRect = control->selectionRect(prevFocus); -
410 if ((next && prevRect.bottom() > (yOffset + height)) || -
411 (!next && prevRect.top() < yOffset)) { -
412 anchorToFocus = prevFocus; -
413 focusedPos = scrollYOffset; -
414 focusIt = true; -
415 } else { -
416 // This is the "normal" case - no scroll bar adjustments, no large anchors, -
417 // and no wrapping. -
418 foundNextAnchor = control->findNextPrevAnchor(prevFocus, next, anchorToFocus); -
419 } -
420 } -
421 -
422 // If not found yet, see if we need to wrap -
423 if (!focusIt && !foundNextAnchor) { -
424 if (next) { -
425 if (yOffset == vbar->maximum()) { -
426 prevFocus.movePosition(QTextCursor::Start); -
427 yOffset = scrollYOffset = 0; -
428 -
429 // Refresh the rectangles -
430 viewRect = QRectF(0, yOffset, control->size().width(), height); -
431 newViewRect = QRectF(0, scrollYOffset, control->size().width(), height); -
432 bothViewRects = viewRect.united(newViewRect); -
433 } -
434 } else { -
435 if (yOffset == 0) { -
436 prevFocus.movePosition(QTextCursor::End); -
437 yOffset = scrollYOffset = vbar->maximum(); -
438 -
439 // Refresh the rectangles -
440 viewRect = QRectF(0, yOffset, control->size().width(), height); -
441 newViewRect = QRectF(0, scrollYOffset, control->size().width(), height); -
442 bothViewRects = viewRect.united(newViewRect); -
443 } -
444 } -
445 -
446 // Try looking now -
447 foundNextAnchor = control->findNextPrevAnchor(prevFocus, next, anchorToFocus); -
448 } -
449 -
450 // If we did actually find an anchor to use... -
451 if (foundNextAnchor) { -
452 QRectF desiredRect = control->selectionRect(anchorToFocus); -
453 -
454 // XXX This is an arbitrary heuristic -
455 // Decide to focus an anchor if it will be at least be -
456 // in the middle region of the screen after a scroll. -
457 // This can result in partial anchors with focus, but -
458 // insisting on links being completely visible before -
459 // selecting them causes disparities between links that -
460 // take up 90% of the screen height and those that take -
461 // up e.g. 110% -
462 // Obviously if a link is entirely visible, we still -
463 // focus it. -
464 if(bothViewRects.contains(desiredRect) -
465 || bothViewRects.adjusted(0, visibleLinkAmount, 0, -visibleLinkAmount).intersects(desiredRect)) { -
466 focusIt = true; -
467 -
468 // We aim to put the new link in the middle of the screen, -
469 // unless the link is larger than the screen (we just move to -
470 // display the first page of the link) -
471 if (desiredRect.height() > height) { -
472 if (next) -
473 focusedPos = (int) desiredRect.top(); -
474 else -
475 focusedPos = (int) desiredRect.bottom() - height; -
476 } else -
477 focusedPos = (int) ((desiredRect.top() + desiredRect.bottom()) / 2 - (height / 2)); -
478 -
479 // and clamp it to make sure we don't skip content. -
480 if (next) -
481 focusedPos = qBound(yOffset, focusedPos, scrollYOffset); -
482 else -
483 focusedPos = qBound(scrollYOffset, focusedPos, yOffset); -
484 } -
485 } -
486 -
487 // If we didn't get a new anchor, check if the old one is still on screen when we scroll -
488 // Note that big (larger than screen height) anchors also have some handling at the -
489 // start of this function. -
490 if (!focusIt && prevFocus.hasSelection()) { -
491 QRectF desiredRect = control->selectionRect(prevFocus); -
492 // XXX this may be better off also using the visibleLinkAmount value -
493 if(newViewRect.intersects(desiredRect)) { -
494 focusedPos = scrollYOffset; -
495 focusIt = true; -
496 anchorToFocus = prevFocus; -
497 } -
498 } -
499 -
500 // setTextCursor ensures that the cursor is visible. save & restore -
501 // the scroll bar values therefore -
502 const int savedXOffset = hbar->value(); -
503 -
504 // Now actually process our decision -
505 if (focusIt && control->setFocusToAnchor(anchorToFocus)) { -
506 // Save the focus for next time -
507 prevFocus = control->textCursor(); -
508 -
509 // Scroll -
510 vbar->setValue(focusedPos); -
511 lastKeypadScrollValue = focusedPos; -
512 hbar->setValue(savedXOffset); -
513 -
514 // Ensure that the new selection is highlighted. -
515 const QString href = control->anchorAtCursor(); -
516 QUrl url = resolveUrl(href); -
517 emit q->highlighted(url); -
518 emit q->highlighted(url.toString()); -
519 } else { -
520 // Scroll -
521 vbar->setValue(scrollYOffset); -
522 lastKeypadScrollValue = scrollYOffset; -
523 -
524 // now make sure we don't have a focused anchor -
525 QTextCursor cursor = control->textCursor(); -
526 cursor.clearSelection(); -
527 -
528 control->setTextCursor(cursor); -
529 -
530 hbar->setValue(savedXOffset); -
531 vbar->setValue(scrollYOffset); -
532 -
533 emit q->highlighted(QUrl()); -
534 emit q->highlighted(QString()); -
535 } -
536} -
537#endif -
538 -
539QTextBrowserPrivate::HistoryEntry QTextBrowserPrivate::createHistoryEntry() const -
540{ -
541 HistoryEntry entry;
executed (the execution status of this line is deduced): HistoryEntry entry;
-
542 entry.url = q_func()->source();
executed (the execution status of this line is deduced): entry.url = q_func()->source();
-
543 entry.title = q_func()->documentTitle();
executed (the execution status of this line is deduced): entry.title = q_func()->documentTitle();
-
544 entry.hpos = hbar->value();
executed (the execution status of this line is deduced): entry.hpos = hbar->value();
-
545 entry.vpos = vbar->value();
executed (the execution status of this line is deduced): entry.vpos = vbar->value();
-
546 -
547 const QTextCursor cursor = control->textCursor();
executed (the execution status of this line is deduced): const QTextCursor cursor = control->textCursor();
-
548 if (control->cursorIsFocusIndicator()
evaluated: control->cursorIsFocusIndicator()
TRUEFALSE
yes
Evaluation Count:15
yes
Evaluation Count:39
15-39
549 && cursor.hasSelection()) {
evaluated: cursor.hasSelection()
TRUEFALSE
yes
Evaluation Count:13
yes
Evaluation Count:2
2-13
550 -
551 entry.focusIndicatorPosition = cursor.position();
executed (the execution status of this line is deduced): entry.focusIndicatorPosition = cursor.position();
-
552 entry.focusIndicatorAnchor = cursor.anchor();
executed (the execution status of this line is deduced): entry.focusIndicatorAnchor = cursor.anchor();
-
553 }
executed: }
Execution Count:13
13
554 return entry;
executed: return entry;
Execution Count:54
54
555} -
556 -
557void QTextBrowserPrivate::restoreHistoryEntry(const HistoryEntry entry) -
558{ -
559 setSource(entry.url);
executed (the execution status of this line is deduced): setSource(entry.url);
-
560 hbar->setValue(entry.hpos);
executed (the execution status of this line is deduced): hbar->setValue(entry.hpos);
-
561 vbar->setValue(entry.vpos);
executed (the execution status of this line is deduced): vbar->setValue(entry.vpos);
-
562 if (entry.focusIndicatorAnchor != -1 && entry.focusIndicatorPosition != -1) {
evaluated: entry.focusIndicatorAnchor != -1
TRUEFALSE
yes
Evaluation Count:10
yes
Evaluation Count:6
partially evaluated: entry.focusIndicatorPosition != -1
TRUEFALSE
yes
Evaluation Count:10
no
Evaluation Count:0
0-10
563 QTextCursor cursor(control->document());
executed (the execution status of this line is deduced): QTextCursor cursor(control->document());
-
564 cursor.setPosition(entry.focusIndicatorAnchor);
executed (the execution status of this line is deduced): cursor.setPosition(entry.focusIndicatorAnchor);
-
565 cursor.setPosition(entry.focusIndicatorPosition, QTextCursor::KeepAnchor);
executed (the execution status of this line is deduced): cursor.setPosition(entry.focusIndicatorPosition, QTextCursor::KeepAnchor);
-
566 control->setTextCursor(cursor);
executed (the execution status of this line is deduced): control->setTextCursor(cursor);
-
567 control->setCursorIsFocusIndicator(true);
executed (the execution status of this line is deduced): control->setCursorIsFocusIndicator(true);
-
568 }
executed: }
Execution Count:10
10
569#ifdef QT_KEYPAD_NAVIGATION -
570 lastKeypadScrollValue = vbar->value(); -
571 prevFocus = control->textCursor(); -
572 -
573 Q_Q(QTextBrowser); -
574 const QString href = prevFocus.charFormat().anchorHref(); -
575 QUrl url = resolveUrl(href); -
576 emit q->highlighted(url); -
577 emit q->highlighted(url.toString()); -
578#endif -
579}
executed: }
Execution Count:16
16
580 -
581/*! -
582 \class QTextBrowser -
583 \brief The QTextBrowser class provides a rich text browser with hypertext navigation. -
584 -
585 \ingroup richtext-processing -
586 \inmodule QtWidgets -
587 -
588 This class extends QTextEdit (in read-only mode), adding some navigation -
589 functionality so that users can follow links in hypertext documents. -
590 -
591 If you want to provide your users with an editable rich text editor, -
592 use QTextEdit. If you want a text browser without hypertext navigation -
593 use QTextEdit, and use QTextEdit::setReadOnly() to disable -
594 editing. If you just need to display a small piece of rich text -
595 use QLabel. -
596 -
597 \section1 Document Source and Contents -
598 -
599 The contents of QTextEdit are set with setHtml() or setPlainText(), -
600 but QTextBrowser also implements the setSource() function, making it -
601 possible to use a named document as the source text. The name is looked -
602 up in a list of search paths and in the directory of the current document -
603 factory. -
604 -
605 If a document name ends with -
606 an anchor (for example, "\c #anchor"), the text browser automatically -
607 scrolls to that position (using scrollToAnchor()). When the user clicks -
608 on a hyperlink, the browser will call setSource() itself with the link's -
609 \c href value as argument. You can track the current source by connecting -
610 to the sourceChanged() signal. -
611 -
612 \section1 Navigation -
613 -
614 QTextBrowser provides backward() and forward() slots which you can -
615 use to implement Back and Forward buttons. The home() slot sets -
616 the text to the very first document displayed. The anchorClicked() -
617 signal is emitted when the user clicks an anchor. To override the -
618 default navigation behavior of the browser, call the setSource() -
619 function to supply new document text in a slot connected to this -
620 signal. -
621 -
622 If you want to load documents stored in the Qt resource system use -
623 \c{qrc} as the scheme in the URL to load. For example, for the document -
624 resource path \c{:/docs/index.html} use \c{qrc:/docs/index.html} as -
625 the URL with setSource(). -
626 -
627 \sa QTextEdit, QTextDocument -
628*/ -
629 -
630/*! -
631 \property QTextBrowser::modified -
632 \brief whether the contents of the text browser have been modified -
633*/ -
634 -
635/*! -
636 \property QTextBrowser::readOnly -
637 \brief whether the text browser is read-only -
638 -
639 By default, this property is true. -
640*/ -
641 -
642/*! -
643 \property QTextBrowser::undoRedoEnabled -
644 \brief whether the text browser supports undo/redo operations -
645 -
646 By default, this property is false. -
647*/ -
648 -
649void QTextBrowserPrivate::init() -
650{ -
651 Q_Q(QTextBrowser);
executed (the execution status of this line is deduced): QTextBrowser * const q = q_func();
-
652 control->setTextInteractionFlags(Qt::TextBrowserInteraction);
executed (the execution status of this line is deduced): control->setTextInteractionFlags(Qt::TextBrowserInteraction);
-
653#ifndef QT_NO_CURSOR -
654 viewport->setCursor(oldCursor);
executed (the execution status of this line is deduced): viewport->setCursor(oldCursor);
-
655#endif -
656 q->setUndoRedoEnabled(false);
executed (the execution status of this line is deduced): q->setUndoRedoEnabled(false);
-
657 viewport->setMouseTracking(true);
executed (the execution status of this line is deduced): viewport->setMouseTracking(true);
-
658 QObject::connect(q->document(), SIGNAL(contentsChanged()), q, SLOT(_q_documentModified()));
executed (the execution status of this line is deduced): QObject::connect(q->document(), "2""contentsChanged()", q, "1""_q_documentModified()");
-
659 QObject::connect(control, SIGNAL(linkActivated(QString)),
executed (the execution status of this line is deduced): QObject::connect(control, "2""linkActivated(QString)",
-
660 q, SLOT(_q_activateAnchor(QString)));
executed (the execution status of this line is deduced): q, "1""_q_activateAnchor(QString)");
-
661 QObject::connect(control, SIGNAL(linkHovered(QString)),
executed (the execution status of this line is deduced): QObject::connect(control, "2""linkHovered(QString)",
-
662 q, SLOT(_q_highlightLink(QString)));
executed (the execution status of this line is deduced): q, "1""_q_highlightLink(QString)");
-
663}
executed: }
Execution Count:24
24
664 -
665/*! -
666 Constructs an empty QTextBrowser with parent \a parent. -
667*/ -
668QTextBrowser::QTextBrowser(QWidget *parent) -
669 : QTextEdit(*new QTextBrowserPrivate, parent) -
670{ -
671 Q_D(QTextBrowser);
executed (the execution status of this line is deduced): QTextBrowserPrivate * const d = d_func();
-
672 d->init();
executed (the execution status of this line is deduced): d->init();
-
673}
executed: }
Execution Count:24
24
674 -
675 -
676/*! -
677 \internal -
678*/ -
679QTextBrowser::~QTextBrowser() -
680{ -
681} -
682 -
683/*! -
684 \property QTextBrowser::source -
685 \brief the name of the displayed document. -
686 -
687 This is a an invalid url if no document is displayed or if the -
688 source is unknown. -
689 -
690 When setting this property QTextBrowser tries to find a document -
691 with the specified name in the paths of the searchPaths property -
692 and directory of the current source, unless the value is an absolute -
693 file path. It also checks for optional anchors and scrolls the document -
694 accordingly -
695 -
696 If the first tag in the document is \c{<qt type=detail>}, the -
697 document is displayed as a popup rather than as new document in -
698 the browser window itself. Otherwise, the document is displayed -
699 normally in the text browser with the text set to the contents of -
700 the named document with setHtml(). -
701 -
702 By default, this property contains an empty URL. -
703*/ -
704QUrl QTextBrowser::source() const -
705{ -
706 Q_D(const QTextBrowser);
executed (the execution status of this line is deduced): const QTextBrowserPrivate * const d = d_func();
-
707 if (d->stack.isEmpty())
evaluated: d->stack.isEmpty()
TRUEFALSE
yes
Evaluation Count:32
yes
Evaluation Count:78
32-78
708 return QUrl();
executed: return QUrl();
Execution Count:32
32
709 else -
710 return d->stack.top().url;
executed: return d->stack.top().url;
Execution Count:78
78
711} -
712 -
713/*! -
714 \property QTextBrowser::searchPaths -
715 \brief the search paths used by the text browser to find supporting -
716 content -
717 -
718 QTextBrowser uses this list to locate images and documents. -
719 -
720 By default, this property contains an empty string list. -
721*/ -
722 -
723QStringList QTextBrowser::searchPaths() const -
724{ -
725 Q_D(const QTextBrowser);
never executed (the execution status of this line is deduced): const QTextBrowserPrivate * const d = d_func();
-
726 return d->searchPaths;
never executed: return d->searchPaths;
0
727} -
728 -
729void QTextBrowser::setSearchPaths(const QStringList &paths) -
730{ -
731 Q_D(QTextBrowser);
never executed (the execution status of this line is deduced): QTextBrowserPrivate * const d = d_func();
-
732 d->searchPaths = paths;
never executed (the execution status of this line is deduced): d->searchPaths = paths;
-
733}
never executed: }
0
734 -
735/*! -
736 Reloads the current set source. -
737*/ -
738void QTextBrowser::reload() -
739{ -
740 Q_D(QTextBrowser);
never executed (the execution status of this line is deduced): QTextBrowserPrivate * const d = d_func();
-
741 QUrl s = d->currentURL;
never executed (the execution status of this line is deduced): QUrl s = d->currentURL;
-
742 d->currentURL = QUrl();
never executed (the execution status of this line is deduced): d->currentURL = QUrl();
-
743 setSource(s);
never executed (the execution status of this line is deduced): setSource(s);
-
744}
never executed: }
0
745 -
746void QTextBrowser::setSource(const QUrl &url) -
747{ -
748 Q_D(QTextBrowser);
executed (the execution status of this line is deduced): QTextBrowserPrivate * const d = d_func();
-
749 -
750 const QTextBrowserPrivate::HistoryEntry historyEntry = d->createHistoryEntry();
executed (the execution status of this line is deduced): const QTextBrowserPrivate::HistoryEntry historyEntry = d->createHistoryEntry();
-
751 -
752 d->setSource(url);
executed (the execution status of this line is deduced): d->setSource(url);
-
753 -
754 if (!url.isValid())
partially evaluated: !url.isValid()
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:38
0-38
755 return;
never executed: return;
0
756 -
757 // the same url you are already watching? -
758 if (!d->stack.isEmpty() && d->stack.top().url == url)
evaluated: !d->stack.isEmpty()
TRUEFALSE
yes
Evaluation Count:24
yes
Evaluation Count:14
evaluated: d->stack.top().url == url
TRUEFALSE
yes
Evaluation Count:1
yes
Evaluation Count:23
1-24
759 return;
executed: return;
Execution Count:1
1
760 -
761 if (!d->stack.isEmpty())
evaluated: !d->stack.isEmpty()
TRUEFALSE
yes
Evaluation Count:23
yes
Evaluation Count:14
14-23
762 d->stack.top() = historyEntry;
executed: d->stack.top() = historyEntry;
Execution Count:23
23
763 -
764 QTextBrowserPrivate::HistoryEntry entry;
executed (the execution status of this line is deduced): QTextBrowserPrivate::HistoryEntry entry;
-
765 entry.url = url;
executed (the execution status of this line is deduced): entry.url = url;
-
766 entry.title = documentTitle();
executed (the execution status of this line is deduced): entry.title = documentTitle();
-
767 entry.hpos = 0;
executed (the execution status of this line is deduced): entry.hpos = 0;
-
768 entry.vpos = 0;
executed (the execution status of this line is deduced): entry.vpos = 0;
-
769 d->stack.push(entry);
executed (the execution status of this line is deduced): d->stack.push(entry);
-
770 -
771 emit backwardAvailable(d->stack.count() > 1);
executed (the execution status of this line is deduced): backwardAvailable(d->stack.count() > 1);
-
772 -
773 if (!d->forwardStack.isEmpty() && d->forwardStack.top().url == url) {
evaluated: !d->forwardStack.isEmpty()
TRUEFALSE
yes
Evaluation Count:2
yes
Evaluation Count:35
evaluated: d->forwardStack.top().url == url
TRUEFALSE
yes
Evaluation Count:1
yes
Evaluation Count:1
1-35
774 d->forwardStack.pop();
executed (the execution status of this line is deduced): d->forwardStack.pop();
-
775 emit forwardAvailable(d->forwardStack.count() > 0);
executed (the execution status of this line is deduced): forwardAvailable(d->forwardStack.count() > 0);
-
776 } else {
executed: }
Execution Count:1
1
777 d->forwardStack.clear();
executed (the execution status of this line is deduced): d->forwardStack.clear();
-
778 emit forwardAvailable(false);
executed (the execution status of this line is deduced): forwardAvailable(false);
-
779 }
executed: }
Execution Count:36
36
780 -
781 emit historyChanged();
executed (the execution status of this line is deduced): historyChanged();
-
782}
executed: }
Execution Count:37
37
783 -
784/*! -
785 \fn void QTextBrowser::backwardAvailable(bool available) -
786 -
787 This signal is emitted when the availability of backward() -
788 changes. \a available is false when the user is at home(); -
789 otherwise it is true. -
790*/ -
791 -
792/*! -
793 \fn void QTextBrowser::forwardAvailable(bool available) -
794 -
795 This signal is emitted when the availability of forward() changes. -
796 \a available is true after the user navigates backward() and false -
797 when the user navigates or goes forward(). -
798*/ -
799 -
800/*! -
801 \fn void QTextBrowser::historyChanged() -
802 \since 4.4 -
803 -
804 This signal is emitted when the history changes. -
805 -
806 \sa historyTitle(), historyUrl() -
807*/ -
808 -
809/*! -
810 \fn void QTextBrowser::sourceChanged(const QUrl &src) -
811 -
812 This signal is emitted when the source has changed, \a src -
813 being the new source. -
814 -
815 Source changes happen both programmatically when calling -
816 setSource(), forward(), backword() or home() or when the user -
817 clicks on links or presses the equivalent key sequences. -
818*/ -
819 -
820/*! \fn void QTextBrowser::highlighted(const QUrl &link) -
821 -
822 This signal is emitted when the user has selected but not -
823 activated an anchor in the document. The URL referred to by the -
824 anchor is passed in \a link. -
825*/ -
826 -
827/*! \fn void QTextBrowser::highlighted(const QString &link) -
828 \overload -
829 -
830 Convenience signal that allows connecting to a slot -
831 that takes just a QString, like for example QStatusBar's -
832 message(). -
833*/ -
834 -
835 -
836/*! -
837 \fn void QTextBrowser::anchorClicked(const QUrl &link) -
838 -
839 This signal is emitted when the user clicks an anchor. The -
840 URL referred to by the anchor is passed in \a link. -
841 -
842 Note that the browser will automatically handle navigation to the -
843 location specified by \a link unless the openLinks property -
844 is set to false or you call setSource() in a slot connected. -
845 This mechanism is used to override the default navigation features of the browser. -
846*/ -
847 -
848/*! -
849 Changes the document displayed to the previous document in the -
850 list of documents built by navigating links. Does nothing if there -
851 is no previous document. -
852 -
853 \sa forward(), backwardAvailable() -
854*/ -
855void QTextBrowser::backward() -
856{ -
857 Q_D(QTextBrowser);
executed (the execution status of this line is deduced): QTextBrowserPrivate * const d = d_func();
-
858 if (d->stack.count() <= 1)
evaluated: d->stack.count() <= 1
TRUEFALSE
yes
Evaluation Count:2
yes
Evaluation Count:11
2-11
859 return;
executed: return;
Execution Count:2
2
860 -
861 // Update the history entry -
862 d->forwardStack.push(d->createHistoryEntry());
executed (the execution status of this line is deduced): d->forwardStack.push(d->createHistoryEntry());
-
863 d->stack.pop(); // throw away the old version of the current entry
executed (the execution status of this line is deduced): d->stack.pop();
-
864 d->restoreHistoryEntry(d->stack.top()); // previous entry
executed (the execution status of this line is deduced): d->restoreHistoryEntry(d->stack.top());
-
865 emit backwardAvailable(d->stack.count() > 1);
executed (the execution status of this line is deduced): backwardAvailable(d->stack.count() > 1);
-
866 emit forwardAvailable(true);
executed (the execution status of this line is deduced): forwardAvailable(true);
-
867 emit historyChanged();
executed (the execution status of this line is deduced): historyChanged();
-
868}
executed: }
Execution Count:11
11
869 -
870/*! -
871 Changes the document displayed to the next document in the list of -
872 documents built by navigating links. Does nothing if there is no -
873 next document. -
874 -
875 \sa backward(), forwardAvailable() -
876*/ -
877void QTextBrowser::forward() -
878{ -
879 Q_D(QTextBrowser);
executed (the execution status of this line is deduced): QTextBrowserPrivate * const d = d_func();
-
880 if (d->forwardStack.isEmpty())
partially evaluated: d->forwardStack.isEmpty()
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:5
0-5
881 return;
never executed: return;
0
882 if (!d->stack.isEmpty()) {
partially evaluated: !d->stack.isEmpty()
TRUEFALSE
yes
Evaluation Count:5
no
Evaluation Count:0
0-5
883 // Update the history entry -
884 d->stack.top() = d->createHistoryEntry();
executed (the execution status of this line is deduced): d->stack.top() = d->createHistoryEntry();
-
885 }
executed: }
Execution Count:5
5
886 d->stack.push(d->forwardStack.pop());
executed (the execution status of this line is deduced): d->stack.push(d->forwardStack.pop());
-
887 d->restoreHistoryEntry(d->stack.top());
executed (the execution status of this line is deduced): d->restoreHistoryEntry(d->stack.top());
-
888 emit backwardAvailable(true);
executed (the execution status of this line is deduced): backwardAvailable(true);
-
889 emit forwardAvailable(!d->forwardStack.isEmpty());
executed (the execution status of this line is deduced): forwardAvailable(!d->forwardStack.isEmpty());
-
890 emit historyChanged();
executed (the execution status of this line is deduced): historyChanged();
-
891}
executed: }
Execution Count:5
5
892 -
893/*! -
894 Changes the document displayed to be the first document from -
895 the history. -
896*/ -
897void QTextBrowser::home() -
898{ -
899 Q_D(QTextBrowser);
executed (the execution status of this line is deduced): QTextBrowserPrivate * const d = d_func();
-
900 if (d->home.isValid())
partially evaluated: d->home.isValid()
TRUEFALSE
yes
Evaluation Count:1
no
Evaluation Count:0
0-1
901 setSource(d->home);
executed: setSource(d->home);
Execution Count:1
1
902}
executed: }
Execution Count:1
1
903 -
904/*! -
905 The event \a ev is used to provide the following keyboard shortcuts: -
906 \table -
907 \header \li Keypress \li Action -
908 \row \li Alt+Left Arrow \li \l backward() -
909 \row \li Alt+Right Arrow \li \l forward() -
910 \row \li Alt+Up Arrow \li \l home() -
911 \endtable -
912*/ -
913void QTextBrowser::keyPressEvent(QKeyEvent *ev) -
914{ -
915#ifdef QT_KEYPAD_NAVIGATION -
916 Q_D(QTextBrowser); -
917 switch (ev->key()) { -
918 case Qt::Key_Select: -
919 if (QApplication::keypadNavigationEnabled()) { -
920 if (!hasEditFocus()) { -
921 setEditFocus(true); -
922 return; -
923 } else { -
924 QTextCursor cursor = d->control->textCursor(); -
925 QTextCharFormat charFmt = cursor.charFormat(); -
926 if (!cursor.hasSelection() || charFmt.anchorHref().isEmpty()) { -
927 ev->accept(); -
928 return; -
929 } -
930 } -
931 } -
932 break; -
933 case Qt::Key_Back: -
934 if (QApplication::keypadNavigationEnabled()) { -
935 if (hasEditFocus()) { -
936 setEditFocus(false); -
937 ev->accept(); -
938 return; -
939 } -
940 } -
941 QTextEdit::keyPressEvent(ev); -
942 return; -
943 default: -
944 if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) { -
945 ev->ignore(); -
946 return; -
947 } -
948 } -
949#endif -
950 -
951 if (ev->modifiers() & Qt::AltModifier) {
partially evaluated: ev->modifiers() & Qt::AltModifier
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:6
0-6
952 switch (ev->key()) { -
953 case Qt::Key_Right: -
954 forward();
never executed (the execution status of this line is deduced): forward();
-
955 ev->accept();
never executed (the execution status of this line is deduced): ev->accept();
-
956 return;
never executed: return;
0
957 case Qt::Key_Left: -
958 backward();
never executed (the execution status of this line is deduced): backward();
-
959 ev->accept();
never executed (the execution status of this line is deduced): ev->accept();
-
960 return;
never executed: return;
0
961 case Qt::Key_Up: -
962 home();
never executed (the execution status of this line is deduced): home();
-
963 ev->accept();
never executed (the execution status of this line is deduced): ev->accept();
-
964 return;
never executed: return;
0
965 } -
966 }
never executed: }
0
967#ifdef QT_KEYPAD_NAVIGATION -
968 else { -
969 if (ev->key() == Qt::Key_Up) { -
970 d->keypadMove(false); -
971 return; -
972 } else if (ev->key() == Qt::Key_Down) { -
973 d->keypadMove(true); -
974 return; -
975 } -
976 } -
977#endif -
978 QTextEdit::keyPressEvent(ev);
executed (the execution status of this line is deduced): QTextEdit::keyPressEvent(ev);
-
979}
executed: }
Execution Count:6
6
980 -
981/*! -
982 \reimp -
983*/ -
984void QTextBrowser::mouseMoveEvent(QMouseEvent *e) -
985{ -
986 QTextEdit::mouseMoveEvent(e);
never executed (the execution status of this line is deduced): QTextEdit::mouseMoveEvent(e);
-
987}
never executed: }
0
988 -
989/*! -
990 \reimp -
991*/ -
992void QTextBrowser::mousePressEvent(QMouseEvent *e) -
993{ -
994 QTextEdit::mousePressEvent(e);
never executed (the execution status of this line is deduced): QTextEdit::mousePressEvent(e);
-
995}
never executed: }
0
996 -
997/*! -
998 \reimp -
999*/ -
1000void QTextBrowser::mouseReleaseEvent(QMouseEvent *e) -
1001{ -
1002 QTextEdit::mouseReleaseEvent(e);
never executed (the execution status of this line is deduced): QTextEdit::mouseReleaseEvent(e);
-
1003}
never executed: }
0
1004 -
1005/*! -
1006 \reimp -
1007*/ -
1008void QTextBrowser::focusOutEvent(QFocusEvent *ev) -
1009{ -
1010#ifndef QT_NO_CURSOR -
1011 Q_D(QTextBrowser);
executed (the execution status of this line is deduced): QTextBrowserPrivate * const d = d_func();
-
1012 d->viewport->setCursor((!(d->control->textInteractionFlags() & Qt::TextEditable)) ? d->oldCursor : Qt::IBeamCursor);
executed (the execution status of this line is deduced): d->viewport->setCursor((!(d->control->textInteractionFlags() & Qt::TextEditable)) ? d->oldCursor : Qt::IBeamCursor);
-
1013#endif -
1014 QTextEdit::focusOutEvent(ev);
executed (the execution status of this line is deduced): QTextEdit::focusOutEvent(ev);
-
1015}
executed: }
Execution Count:4
4
1016 -
1017/*! -
1018 \reimp -
1019*/ -
1020bool QTextBrowser::focusNextPrevChild(bool next) -
1021{ -
1022 Q_D(QTextBrowser);
executed (the execution status of this line is deduced): QTextBrowserPrivate * const d = d_func();
-
1023 if (d->control->setFocusToNextOrPreviousAnchor(next)) {
evaluated: d->control->setFocusToNextOrPreviousAnchor(next)
TRUEFALSE
yes
Evaluation Count:10
yes
Evaluation Count:1
1-10
1024#ifdef QT_KEYPAD_NAVIGATION -
1025 // Might need to synthesize a highlight event. -
1026 if (d->prevFocus != d->control->textCursor() && d->control->textCursor().hasSelection()) { -
1027 const QString href = d->control->anchorAtCursor(); -
1028 QUrl url = d->resolveUrl(href); -
1029 emit highlighted(url); -
1030 emit highlighted(url.toString()); -
1031 } -
1032 d->prevFocus = d->control->textCursor(); -
1033#endif -
1034 return true;
executed: return true;
Execution Count:10
10
1035 } else { -
1036#ifdef QT_KEYPAD_NAVIGATION -
1037 // We assume we have no highlight now. -
1038 emit highlighted(QUrl()); -
1039 emit highlighted(QString()); -
1040#endif -
1041 }
executed: }
Execution Count:1
1
1042 return QTextEdit::focusNextPrevChild(next);
executed: return QTextEdit::focusNextPrevChild(next);
Execution Count:1
1
1043} -
1044 -
1045/*! -
1046 \reimp -
1047*/ -
1048void QTextBrowser::paintEvent(QPaintEvent *e) -
1049{ -
1050 Q_D(QTextBrowser);
executed (the execution status of this line is deduced): QTextBrowserPrivate * const d = d_func();
-
1051 QPainter p(d->viewport);
executed (the execution status of this line is deduced): QPainter p(d->viewport);
-
1052 d->paint(&p, e);
executed (the execution status of this line is deduced): d->paint(&p, e);
-
1053}
executed: }
Execution Count:26
26
1054 -
1055/*! -
1056 This function is called when the document is loaded and for -
1057 each image in the document. The \a type indicates the type of resource -
1058 to be loaded. An invalid QVariant is returned if the resource cannot be -
1059 loaded. -
1060 -
1061 The default implementation ignores \a type and tries to locate -
1062 the resources by interpreting \a name as a file name. If it is -
1063 not an absolute path it tries to find the file in the paths of -
1064 the \l searchPaths property and in the same directory as the -
1065 current source. On success, the result is a QVariant that stores -
1066 a QByteArray with the contents of the file. -
1067 -
1068 If you reimplement this function, you can return other QVariant -
1069 types. The table below shows which variant types are supported -
1070 depending on the resource type: -
1071 -
1072 \table -
1073 \header \li ResourceType \li QVariant::Type -
1074 \row \li QTextDocument::HtmlResource \li QString or QByteArray -
1075 \row \li QTextDocument::ImageResource \li QImage, QPixmap or QByteArray -
1076 \row \li QTextDocument::StyleSheetResource \li QString or QByteArray -
1077 \endtable -
1078*/ -
1079QVariant QTextBrowser::loadResource(int /*type*/, const QUrl &name) -
1080{ -
1081 Q_D(QTextBrowser);
executed (the execution status of this line is deduced): QTextBrowserPrivate * const d = d_func();
-
1082 -
1083 QByteArray data;
executed (the execution status of this line is deduced): QByteArray data;
-
1084 QString fileName = d->findFile(d->resolveUrl(name));
executed (the execution status of this line is deduced): QString fileName = d->findFile(d->resolveUrl(name));
-
1085 QFile f(fileName);
executed (the execution status of this line is deduced): QFile f(fileName);
-
1086 if (f.open(QFile::ReadOnly)) {
evaluated: f.open(QFile::ReadOnly)
TRUEFALSE
yes
Evaluation Count:46
yes
Evaluation Count:6
6-46
1087 data = f.readAll();
executed (the execution status of this line is deduced): data = f.readAll();
-
1088 f.close();
executed (the execution status of this line is deduced): f.close();
-
1089 } else {
executed: }
Execution Count:46
46
1090 return QVariant();
executed: return QVariant();
Execution Count:6
6
1091 } -
1092 -
1093 return data;
executed: return data;
Execution Count:46
46
1094} -
1095 -
1096/*! -
1097 \since 4.2 -
1098 -
1099 Returns true if the text browser can go backward in the document history -
1100 using backward(). -
1101 -
1102 \sa backwardAvailable(), backward() -
1103*/ -
1104bool QTextBrowser::isBackwardAvailable() const -
1105{ -
1106 Q_D(const QTextBrowser);
executed (the execution status of this line is deduced): const QTextBrowserPrivate * const d = d_func();
-
1107 return d->stack.count() > 1;
executed: return d->stack.count() > 1;
Execution Count:13
13
1108} -
1109 -
1110/*! -
1111 \since 4.2 -
1112 -
1113 Returns true if the text browser can go forward in the document history -
1114 using forward(). -
1115 -
1116 \sa forwardAvailable(), forward() -
1117*/ -
1118bool QTextBrowser::isForwardAvailable() const -
1119{ -
1120 Q_D(const QTextBrowser);
executed (the execution status of this line is deduced): const QTextBrowserPrivate * const d = d_func();
-
1121 return !d->forwardStack.isEmpty();
executed: return !d->forwardStack.isEmpty();
Execution Count:13
13
1122} -
1123 -
1124/*! -
1125 \since 4.2 -
1126 -
1127 Clears the history of visited documents and disables the forward and -
1128 backward navigation. -
1129 -
1130 \sa backward(), forward() -
1131*/ -
1132void QTextBrowser::clearHistory() -
1133{ -
1134 Q_D(QTextBrowser);
executed (the execution status of this line is deduced): QTextBrowserPrivate * const d = d_func();
-
1135 d->forwardStack.clear();
executed (the execution status of this line is deduced): d->forwardStack.clear();
-
1136 if (!d->stack.isEmpty()) {
evaluated: !d->stack.isEmpty()
TRUEFALSE
yes
Evaluation Count:1
yes
Evaluation Count:1
1
1137 QTextBrowserPrivate::HistoryEntry historyEntry = d->stack.top();
executed (the execution status of this line is deduced): QTextBrowserPrivate::HistoryEntry historyEntry = d->stack.top();
-
1138 d->stack.resize(0);
executed (the execution status of this line is deduced): d->stack.resize(0);
-
1139 d->stack.push(historyEntry);
executed (the execution status of this line is deduced): d->stack.push(historyEntry);
-
1140 d->home = historyEntry.url;
executed (the execution status of this line is deduced): d->home = historyEntry.url;
-
1141 }
executed: }
Execution Count:1
1
1142 emit forwardAvailable(false);
executed (the execution status of this line is deduced): forwardAvailable(false);
-
1143 emit backwardAvailable(false);
executed (the execution status of this line is deduced): backwardAvailable(false);
-
1144 emit historyChanged();
executed (the execution status of this line is deduced): historyChanged();
-
1145}
executed: }
Execution Count:2
2
1146 -
1147/*! -
1148 Returns the url of the HistoryItem. -
1149 -
1150 \table -
1151 \header \li Input \li Return -
1152 \row \li \a{i} < 0 \li \l backward() history -
1153 \row \li\a{i} == 0 \li current, see QTextBrowser::source() -
1154 \row \li \a{i} > 0 \li \l forward() history -
1155 \endtable -
1156 -
1157 \since 4.4 -
1158*/ -
1159QUrl QTextBrowser::historyUrl(int i) const -
1160{ -
1161 Q_D(const QTextBrowser);
executed (the execution status of this line is deduced): const QTextBrowserPrivate * const d = d_func();
-
1162 return d->history(i).url;
executed: return d->history(i).url;
Execution Count:1
1
1163} -
1164 -
1165/*! -
1166 Returns the documentTitle() of the HistoryItem. -
1167 -
1168 \table -
1169 \header \li Input \li Return -
1170 \row \li \a{i} < 0 \li \l backward() history -
1171 \row \li \a{i} == 0 \li current, see QTextBrowser::source() -
1172 \row \li \a{i} > 0 \li \l forward() history -
1173 \endtable -
1174 -
1175 \snippet code/src_gui_widgets_qtextbrowser.cpp 0 -
1176 -
1177 \since 4.4 -
1178*/ -
1179QString QTextBrowser::historyTitle(int i) const -
1180{ -
1181 Q_D(const QTextBrowser);
executed (the execution status of this line is deduced): const QTextBrowserPrivate * const d = d_func();
-
1182 return d->history(i).title;
executed: return d->history(i).title;
Execution Count:17
17
1183} -
1184 -
1185 -
1186/*! -
1187 Returns the number of locations forward in the history. -
1188 -
1189 \since 4.4 -
1190*/ -
1191int QTextBrowser::forwardHistoryCount() const -
1192{ -
1193 Q_D(const QTextBrowser);
never executed (the execution status of this line is deduced): const QTextBrowserPrivate * const d = d_func();
-
1194 return d->forwardStack.count();
never executed: return d->forwardStack.count();
0
1195} -
1196 -
1197/*! -
1198 Returns the number of locations backward in the history. -
1199 -
1200 \since 4.4 -
1201*/ -
1202int QTextBrowser::backwardHistoryCount() const -
1203{ -
1204 Q_D(const QTextBrowser);
never executed (the execution status of this line is deduced): const QTextBrowserPrivate * const d = d_func();
-
1205 return d->stack.count()-1;
never executed: return d->stack.count()-1;
0
1206} -
1207 -
1208/*! -
1209 \property QTextBrowser::openExternalLinks -
1210 \since 4.2 -
1211 -
1212 Specifies whether QTextBrowser should automatically open links to external -
1213 sources using QDesktopServices::openUrl() instead of emitting the -
1214 anchorClicked signal. Links are considered external if their scheme is -
1215 neither file or qrc. -
1216 -
1217 The default value is false. -
1218*/ -
1219bool QTextBrowser::openExternalLinks() const -
1220{ -
1221 Q_D(const QTextBrowser);
never executed (the execution status of this line is deduced): const QTextBrowserPrivate * const d = d_func();
-
1222 return d->openExternalLinks;
never executed: return d->openExternalLinks;
0
1223} -
1224 -
1225void QTextBrowser::setOpenExternalLinks(bool open) -
1226{ -
1227 Q_D(QTextBrowser);
never executed (the execution status of this line is deduced): QTextBrowserPrivate * const d = d_func();
-
1228 d->openExternalLinks = open;
never executed (the execution status of this line is deduced): d->openExternalLinks = open;
-
1229}
never executed: }
0
1230 -
1231/*! -
1232 \property QTextBrowser::openLinks -
1233 \since 4.3 -
1234 -
1235 This property specifies whether QTextBrowser should automatically open links the user tries to -
1236 activate by mouse or keyboard. -
1237 -
1238 Regardless of the value of this property the anchorClicked signal is always emitted. -
1239 -
1240 The default value is true. -
1241*/ -
1242 -
1243bool QTextBrowser::openLinks() const -
1244{ -
1245 Q_D(const QTextBrowser);
never executed (the execution status of this line is deduced): const QTextBrowserPrivate * const d = d_func();
-
1246 return d->openLinks;
never executed: return d->openLinks;
0
1247} -
1248 -
1249void QTextBrowser::setOpenLinks(bool open) -
1250{ -
1251 Q_D(QTextBrowser);
executed (the execution status of this line is deduced): QTextBrowserPrivate * const d = d_func();
-
1252 d->openLinks = open;
executed (the execution status of this line is deduced): d->openLinks = open;
-
1253}
executed: }
Execution Count:1
1
1254 -
1255/*! \reimp */ -
1256bool QTextBrowser::event(QEvent *e) -
1257{ -
1258 return QTextEdit::event(e);
executed: return QTextEdit::event(e);
Execution Count:828
828
1259} -
1260 -
1261QT_END_NAMESPACE -
1262 -
1263#include "moc_qtextbrowser.cpp" -
1264 -
1265#endif // QT_NO_TEXTBROWSER -
1266 -
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial