Qt 4.8
qtextbrowser.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 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>
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 
62 
64 {
66 public:
69  openLinks(true)
70 #ifdef QT_KEYPAD_NAVIGATION
71  , lastKeypadScrollValue(-1)
72 #endif
73  {}
74 
75  void init();
76 
77  struct HistoryEntry {
78  inline HistoryEntry()
79  : hpos(0), vpos(0), focusIndicatorPosition(-1),
83  int hpos;
84  int vpos;
86  };
87 
88  HistoryEntry history(int i) const
89  {
90  if (i <= 0)
91  if (-i < stack.count())
92  return stack[stack.count()+i-1];
93  else
94  return HistoryEntry();
95  else
96  if (i <= forwardStack.count())
97  return forwardStack[forwardStack.count()-i];
98  else
99  return HistoryEntry();
100  }
101 
102 
104  void restoreHistoryEntry(const HistoryEntry entry);
105 
110 
112 
113  /*flag necessary to give the linkClicked() signal some meaningful
114  semantics when somebody connected to it calls setText() or
115  setSource() */
118 
120  bool openLinks;
121 
122 #ifndef QT_NO_CURSOR
124 #endif
125 
126  QString findFile(const QUrl &name) const;
127 
128  inline void _q_documentModified()
129  {
130  textOrSourceChanged = true;
131  forceLoadOnSourceChange = !currentURL.path().isEmpty();
132  }
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::fromEncoded(url.toUtf8())); }
143 
144 #ifdef QT_KEYPAD_NAVIGATION
145  void keypadMove(bool next);
146  QTextCursor prevFocus;
147  int lastKeypadScrollValue;
148 #endif
149 };
150 
152 {
154  if (name.scheme() == QLatin1String("qrc"))
155  fileName = QLatin1String(":/") + name.path();
156  else
157  fileName = name.toLocalFile();
158 
159  if (QFileInfo(fileName).isAbsolute())
160  return fileName;
161 
162  foreach (QString path, searchPaths) {
163  if (!path.endsWith(QLatin1Char('/')))
164  path.append(QLatin1Char('/'));
165  path.append(fileName);
166  if (QFileInfo(path).isReadable())
167  return path;
168  }
169 
170  return fileName;
171 }
172 
174 {
175  if (!url.isRelative())
176  return url;
177 
178  // For the second case QUrl can merge "#someanchor" with "foo.html"
179  // correctly to "foo.html#someanchor"
180  if (!(currentURL.isRelative()
181  || (currentURL.scheme() == QLatin1String("file")
182  && !QFileInfo(currentURL.toLocalFile()).isAbsolute()))
183  || (url.hasFragment() && url.path().isEmpty())) {
184  return currentURL.resolved(url);
185  }
186 
187  // this is our last resort when current url and new url are both relative
188  // we try to resolve against the current working directory in the local
189  // file system.
191  if (fi.exists()) {
192  return QUrl::fromLocalFile(fi.absolutePath() + QDir::separator()).resolved(url);
193  }
194 
195  return url;
196 }
197 
199 {
200  if (href.isEmpty())
201  return;
202  Q_Q(QTextBrowser);
203 
204 #ifndef QT_NO_CURSOR
206 #endif
207 
208  const QUrl url = resolveUrl(href);
209 
210  if (!openLinks) {
211  emit q->anchorClicked(url);
212  return;
213  }
214 
215  textOrSourceChanged = false;
216 
217 #ifndef QT_NO_DESKTOPSERVICES
218  if ((openExternalLinks
219  && url.scheme() != QLatin1String("file")
220  && url.scheme() != QLatin1String("qrc")
221  && !url.isRelative())
222  || (url.isRelative() && !currentURL.isRelative()
223  && currentURL.scheme() != QLatin1String("file")
224  && currentURL.scheme() != QLatin1String("qrc"))) {
226  return;
227  }
228 #endif
229 
230  emit q->anchorClicked(url);
231 
233  return;
234 
235  q->setSource(url);
236 }
237 
239 {
240  Q_Q(QTextBrowser);
241  if (anchor.isEmpty()) {
242 #ifndef QT_NO_CURSOR
246 #endif
247  emit q->highlighted(QUrl());
248  emit q->highlighted(QString());
249  } else {
250 #ifndef QT_NO_CURSOR
252 #endif
253 
254  const QUrl url = resolveUrl(anchor);
255  emit q->highlighted(url);
256  // convenience to ease connecting to QStatusBar::showMessage(const QString &)
257  emit q->highlighted(url.toString());
258  }
259 }
260 
262 {
263  Q_Q(QTextBrowser);
264 #ifndef QT_NO_CURSOR
265  if (q->isVisible())
267 #endif
268  textOrSourceChanged = true;
269 
270  QString txt;
271 
272  bool doSetText = false;
273 
274  QUrl currentUrlWithoutFragment = currentURL;
275  currentUrlWithoutFragment.setFragment(QString());
276  QUrl newUrlWithoutFragment = currentURL.resolved(url);
277  newUrlWithoutFragment.setFragment(QString());
278 
279  if (url.isValid()
280  && (newUrlWithoutFragment != currentUrlWithoutFragment || forceLoadOnSourceChange)) {
281  QVariant data = q->loadResource(QTextDocument::HtmlResource, resolveUrl(url));
282  if (data.type() == QVariant::String) {
283  txt = data.toString();
284  } else if (data.type() == QVariant::ByteArray) {
285 #ifndef QT_NO_TEXTCODEC
286  QByteArray ba = data.toByteArray();
288  txt = codec->toUnicode(ba);
289 #else
290  txt = data.toString();
291 #endif
292  }
293  if (txt.isEmpty())
294  qWarning("QTextBrowser: No document for %s", url.toString().toLatin1().constData());
295 
296  if (q->isVisible()) {
297  QString firstTag = txt.left(txt.indexOf(QLatin1Char('>')) + 1);
298  if (firstTag.startsWith(QLatin1String("<qt")) && firstTag.contains(QLatin1String("type")) && firstTag.contains(QLatin1String("detail"))) {
299 #ifndef QT_NO_CURSOR
301 #endif
302 #ifndef QT_NO_WHATSTHIS
304 #endif
305  return;
306  }
307  }
308 
309  currentURL = resolveUrl(url);
310  doSetText = true;
311  }
312 
313  if (!home.isValid())
314  home = url;
315 
316  if (doSetText) {
317 #ifndef QT_NO_TEXTHTMLPARSER
318  q->QTextEdit::setHtml(txt);
319  q->document()->setMetaInformation(QTextDocument::DocumentUrl, currentURL.toString());
320 #else
321  q->QTextEdit::setPlainText(txt);
322 #endif
323 
324 #ifdef QT_KEYPAD_NAVIGATION
325  prevFocus.movePosition(QTextCursor::Start);
326 #endif
327  }
328 
329  forceLoadOnSourceChange = false;
330 
331  if (!url.fragment().isEmpty()) {
332  q->scrollToAnchor(url.fragment());
333  } else {
334  hbar->setValue(0);
335  vbar->setValue(0);
336  }
337 #ifdef QT_KEYPAD_NAVIGATION
338  lastKeypadScrollValue = vbar->value();
339  emit q->highlighted(QUrl());
340  emit q->highlighted(QString());
341 #endif
342 
343 #ifndef QT_NO_CURSOR
344  if (q->isVisible())
346 #endif
347  emit q->sourceChanged(url);
348 }
349 
350 #ifdef QT_KEYPAD_NAVIGATION
351 void QTextBrowserPrivate::keypadMove(bool next)
352 {
353  Q_Q(QTextBrowser);
354 
355  const int height = viewport->height();
356  const int overlap = qBound(20, height / 5, 40); // XXX arbitrary, but a good balance
357  const int visibleLinkAmount = overlap; // consistent, but maybe not the best choice (?)
358  int yOffset = vbar->value();
359  int scrollYOffset = qBound(0, next ? yOffset + height - overlap : yOffset - height + overlap, vbar->maximum());
360 
361  bool foundNextAnchor = false;
362  bool focusIt = false;
363  int focusedPos = -1;
364 
365  QTextCursor anchorToFocus;
366 
367  QRectF viewRect = QRectF(0, yOffset, control->size().width(), height);
368  QRectF newViewRect = QRectF(0, scrollYOffset, control->size().width(), height);
369  QRectF bothViewRects = viewRect.united(newViewRect);
370 
371  // If we don't have a previous anchor, pretend that we had the first/last character
372  // on the screen selected.
373  if (prevFocus.isNull()) {
374  if (next)
375  prevFocus = control->cursorForPosition(QPointF(0, yOffset));
376  else
377  prevFocus = control->cursorForPosition(QPointF(control->size().width(), yOffset + height));
378  }
379 
380  // First, check to see if someone has moved the scroll bars independently
381  if (lastKeypadScrollValue != yOffset) {
382  // Someone (user or programmatically) has moved us, so we might
383  // need to start looking from the current position instead of prevFocus
384 
385  bool findOnScreen = true;
386 
387  // If prevFocus is on screen at all, we just use it.
388  if (prevFocus.hasSelection()) {
389  QRectF prevRect = control->selectionRect(prevFocus);
390  if (viewRect.intersects(prevRect))
391  findOnScreen = false;
392  }
393 
394  // Otherwise, we find a new anchor that's on screen.
395  // Basically, create a cursor with the last/first character
396  // on screen
397  if (findOnScreen) {
398  if (next)
399  prevFocus = control->cursorForPosition(QPointF(0, yOffset));
400  else
401  prevFocus = control->cursorForPosition(QPointF(control->size().width(), yOffset + height));
402  }
403  foundNextAnchor = control->findNextPrevAnchor(prevFocus, next, anchorToFocus);
404  } else if (prevFocus.hasSelection()) {
405  // Check the pathological case that the current anchor is higher
406  // than the screen, and just scroll through it in that case
407  QRectF prevRect = control->selectionRect(prevFocus);
408  if ((next && prevRect.bottom() > (yOffset + height)) ||
409  (!next && prevRect.top() < yOffset)) {
410  anchorToFocus = prevFocus;
411  focusedPos = scrollYOffset;
412  focusIt = true;
413  } else {
414  // This is the "normal" case - no scroll bar adjustments, no large anchors,
415  // and no wrapping.
416  foundNextAnchor = control->findNextPrevAnchor(prevFocus, next, anchorToFocus);
417  }
418  }
419 
420  // If not found yet, see if we need to wrap
421  if (!focusIt && !foundNextAnchor) {
422  if (next) {
423  if (yOffset == vbar->maximum()) {
424  prevFocus.movePosition(QTextCursor::Start);
425  yOffset = scrollYOffset = 0;
426 
427  // Refresh the rectangles
428  viewRect = QRectF(0, yOffset, control->size().width(), height);
429  newViewRect = QRectF(0, scrollYOffset, control->size().width(), height);
430  bothViewRects = viewRect.united(newViewRect);
431  }
432  } else {
433  if (yOffset == 0) {
434  prevFocus.movePosition(QTextCursor::End);
435  yOffset = scrollYOffset = vbar->maximum();
436 
437  // Refresh the rectangles
438  viewRect = QRectF(0, yOffset, control->size().width(), height);
439  newViewRect = QRectF(0, scrollYOffset, control->size().width(), height);
440  bothViewRects = viewRect.united(newViewRect);
441  }
442  }
443 
444  // Try looking now
445  foundNextAnchor = control->findNextPrevAnchor(prevFocus, next, anchorToFocus);
446  }
447 
448  // If we did actually find an anchor to use...
449  if (foundNextAnchor) {
450  QRectF desiredRect = control->selectionRect(anchorToFocus);
451 
452  // XXX This is an arbitrary heuristic
453  // Decide to focus an anchor if it will be at least be
454  // in the middle region of the screen after a scroll.
455  // This can result in partial anchors with focus, but
456  // insisting on links being completely visible before
457  // selecting them causes disparities between links that
458  // take up 90% of the screen height and those that take
459  // up e.g. 110%
460  // Obviously if a link is entirely visible, we still
461  // focus it.
462  if(bothViewRects.contains(desiredRect)
463  || bothViewRects.adjusted(0, visibleLinkAmount, 0, -visibleLinkAmount).intersects(desiredRect)) {
464  focusIt = true;
465 
466  // We aim to put the new link in the middle of the screen,
467  // unless the link is larger than the screen (we just move to
468  // display the first page of the link)
469  if (desiredRect.height() > height) {
470  if (next)
471  focusedPos = (int) desiredRect.top();
472  else
473  focusedPos = (int) desiredRect.bottom() - height;
474  } else
475  focusedPos = (int) ((desiredRect.top() + desiredRect.bottom()) / 2 - (height / 2));
476 
477  // and clamp it to make sure we don't skip content.
478  if (next)
479  focusedPos = qBound(yOffset, focusedPos, scrollYOffset);
480  else
481  focusedPos = qBound(scrollYOffset, focusedPos, yOffset);
482  }
483  }
484 
485  // If we didn't get a new anchor, check if the old one is still on screen when we scroll
486  // Note that big (larger than screen height) anchors also have some handling at the
487  // start of this function.
488  if (!focusIt && prevFocus.hasSelection()) {
489  QRectF desiredRect = control->selectionRect(prevFocus);
490  // XXX this may be better off also using the visibleLinkAmount value
491  if(newViewRect.intersects(desiredRect)) {
492  focusedPos = scrollYOffset;
493  focusIt = true;
494  anchorToFocus = prevFocus;
495  }
496  }
497 
498  // setTextCursor ensures that the cursor is visible. save & restore
499  // the scroll bar values therefore
500  const int savedXOffset = hbar->value();
501 
502  // Now actually process our decision
503  if (focusIt && control->setFocusToAnchor(anchorToFocus)) {
504  // Save the focus for next time
505  prevFocus = control->textCursor();
506 
507  // Scroll
508  vbar->setValue(focusedPos);
509  lastKeypadScrollValue = focusedPos;
510  hbar->setValue(savedXOffset);
511 
512  // Ensure that the new selection is highlighted.
513  const QString href = control->anchorAtCursor();
514  QUrl url = resolveUrl(href);
515  emit q->highlighted(url);
516  emit q->highlighted(url.toString());
517  } else {
518  // Scroll
519  vbar->setValue(scrollYOffset);
520  lastKeypadScrollValue = scrollYOffset;
521 
522  // now make sure we don't have a focused anchor
523  QTextCursor cursor = control->textCursor();
524  cursor.clearSelection();
525 
526  control->setTextCursor(cursor);
527 
528  hbar->setValue(savedXOffset);
529  vbar->setValue(scrollYOffset);
530 
531  emit q->highlighted(QUrl());
532  emit q->highlighted(QString());
533  }
534 }
535 #endif
536 
538 {
539  HistoryEntry entry;
540  entry.url = q_func()->source();
541  entry.title = q_func()->documentTitle();
542  entry.hpos = hbar->value();
543  entry.vpos = vbar->value();
544 
545  const QTextCursor cursor = control->textCursor();
547  && cursor.hasSelection()) {
548 
549  entry.focusIndicatorPosition = cursor.position();
550  entry.focusIndicatorAnchor = cursor.anchor();
551  }
552  return entry;
553 }
554 
556 {
557  setSource(entry.url);
558  hbar->setValue(entry.hpos);
559  vbar->setValue(entry.vpos);
560  if (entry.focusIndicatorAnchor != -1 && entry.focusIndicatorPosition != -1) {
561  QTextCursor cursor(control->document());
562  cursor.setPosition(entry.focusIndicatorAnchor);
563  cursor.setPosition(entry.focusIndicatorPosition, QTextCursor::KeepAnchor);
564  control->setTextCursor(cursor);
566  }
567 #ifdef QT_KEYPAD_NAVIGATION
568  lastKeypadScrollValue = vbar->value();
569  prevFocus = control->textCursor();
570 
571  Q_Q(QTextBrowser);
572  const QString href = prevFocus.charFormat().anchorHref();
573  QUrl url = resolveUrl(href);
574  emit q->highlighted(url);
575  emit q->highlighted(url.toString());
576 #endif
577 }
578 
660 {
661  Q_Q(QTextBrowser);
663 #ifndef QT_NO_CURSOR
665 #endif
666  q->setUndoRedoEnabled(false);
667  viewport->setMouseTracking(true);
668  QObject::connect(q->document(), SIGNAL(contentsChanged()), q, SLOT(_q_documentModified()));
669  QObject::connect(control, SIGNAL(linkActivated(QString)),
671  QObject::connect(control, SIGNAL(linkHovered(QString)),
673 }
674 
679  : QTextEdit(*new QTextBrowserPrivate, parent)
680 {
681  Q_D(QTextBrowser);
682  d->init();
683 }
684 
685 #ifdef QT3_SUPPORT
686 
691  : QTextEdit(*new QTextBrowserPrivate, parent)
692 {
694  Q_D(QTextBrowser);
695  d->init();
696 }
697 #endif
698 
703 {
704 }
705 
731 {
732  Q_D(const QTextBrowser);
733  if (d->stack.isEmpty())
734  return QUrl();
735  else
736  return d->stack.top().url;
737 }
738 
753 {
754  Q_D(const QTextBrowser);
755  return d->searchPaths;
756 }
757 
759 {
760  Q_D(QTextBrowser);
761  d->searchPaths = paths;
762 }
763 
768 {
769  Q_D(QTextBrowser);
770  QUrl s = d->currentURL;
771  d->currentURL = QUrl();
772  setSource(s);
773 }
774 
776 {
777  Q_D(QTextBrowser);
778 
779  const QTextBrowserPrivate::HistoryEntry historyEntry = d->createHistoryEntry();
780 
781  d->setSource(url);
782 
783  if (!url.isValid())
784  return;
785 
786  // the same url you are already watching?
787  if (!d->stack.isEmpty() && d->stack.top().url == url)
788  return;
789 
790  if (!d->stack.isEmpty())
791  d->stack.top() = historyEntry;
792 
794  entry.url = url;
795  entry.title = documentTitle();
796  entry.hpos = 0;
797  entry.vpos = 0;
798  d->stack.push(entry);
799 
800  emit backwardAvailable(d->stack.count() > 1);
801 
802  if (!d->forwardStack.isEmpty() && d->forwardStack.top().url == url) {
803  d->forwardStack.pop();
804  emit forwardAvailable(d->forwardStack.count() > 0);
805  } else {
806  d->forwardStack.clear();
807  emit forwardAvailable(false);
808  }
809 
811 }
812 
906 {
907  Q_D(QTextBrowser);
908  if (d->stack.count() <= 1)
909  return;
910 
911  // Update the history entry
912  d->forwardStack.push(d->createHistoryEntry());
913  d->stack.pop(); // throw away the old version of the current entry
914  d->restoreHistoryEntry(d->stack.top()); // previous entry
915  emit backwardAvailable(d->stack.count() > 1);
916  emit forwardAvailable(true);
918 }
919 
928 {
929  Q_D(QTextBrowser);
930  if (d->forwardStack.isEmpty())
931  return;
932  if (!d->stack.isEmpty()) {
933  // Update the history entry
934  d->stack.top() = d->createHistoryEntry();
935  }
936  d->stack.push(d->forwardStack.pop());
937  d->restoreHistoryEntry(d->stack.top());
938  emit backwardAvailable(true);
939  emit forwardAvailable(!d->forwardStack.isEmpty());
941 }
942 
948 {
949  Q_D(QTextBrowser);
950  if (d->home.isValid())
951  setSource(d->home);
952 }
953 
964 {
965 #ifdef QT_KEYPAD_NAVIGATION
966  Q_D(QTextBrowser);
967  switch (ev->key()) {
968  case Qt::Key_Select:
969  if (QApplication::keypadNavigationEnabled()) {
970  if (!hasEditFocus()) {
971  setEditFocus(true);
972  return;
973  } else {
974  QTextCursor cursor = d->control->textCursor();
975  QTextCharFormat charFmt = cursor.charFormat();
976  if (!cursor.hasSelection() || charFmt.anchorHref().isEmpty()) {
977  ev->accept();
978  return;
979  }
980  }
981  }
982  break;
983  case Qt::Key_Back:
984  if (QApplication::keypadNavigationEnabled()) {
985  if (hasEditFocus()) {
986  setEditFocus(false);
987  ev->accept();
988  return;
989  }
990  }
992  return;
993  default:
994  if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) {
995  ev->ignore();
996  return;
997  }
998  }
999 #endif
1000 
1001  if (ev->modifiers() & Qt::AltModifier) {
1002  switch (ev->key()) {
1003  case Qt::Key_Right:
1004  forward();
1005  ev->accept();
1006  return;
1007  case Qt::Key_Left:
1008  backward();
1009  ev->accept();
1010  return;
1011  case Qt::Key_Up:
1012  home();
1013  ev->accept();
1014  return;
1015  }
1016  }
1017 #ifdef QT_KEYPAD_NAVIGATION
1018  else {
1019  if (ev->key() == Qt::Key_Up) {
1020  d->keypadMove(false);
1021  return;
1022  } else if (ev->key() == Qt::Key_Down) {
1023  d->keypadMove(true);
1024  return;
1025  }
1026  }
1027 #endif
1029 }
1030 
1035 {
1037 }
1038 
1043 {
1045 }
1046 
1051 {
1053 }
1054 
1059 {
1060 #ifndef QT_NO_CURSOR
1061  Q_D(QTextBrowser);
1062  d->viewport->setCursor((!(d->control->textInteractionFlags() & Qt::TextEditable)) ? d->oldCursor : Qt::IBeamCursor);
1063 #endif
1065 }
1066 
1071 {
1072  Q_D(QTextBrowser);
1073  if (d->control->setFocusToNextOrPreviousAnchor(next)) {
1074 #ifdef QT_KEYPAD_NAVIGATION
1075  // Might need to synthesize a highlight event.
1076  if (d->prevFocus != d->control->textCursor() && d->control->textCursor().hasSelection()) {
1077  const QString href = d->control->anchorAtCursor();
1078  QUrl url = d->resolveUrl(href);
1079  emit highlighted(url);
1080  emit highlighted(url.toString());
1081  }
1082  d->prevFocus = d->control->textCursor();
1083 #endif
1084  return true;
1085  } else {
1086 #ifdef QT_KEYPAD_NAVIGATION
1087  // We assume we have no highlight now.
1088  emit highlighted(QUrl());
1090 #endif
1091  }
1092  return QTextEdit::focusNextPrevChild(next);
1093 }
1094 
1099 {
1100  Q_D(QTextBrowser);
1101  QPainter p(d->viewport);
1102  d->paint(&p, e);
1103 }
1104 
1130 {
1131  Q_D(QTextBrowser);
1132 
1133  QByteArray data;
1134  QString fileName = d->findFile(d->resolveUrl(name));
1135  QFile f(fileName);
1136  if (f.open(QFile::ReadOnly)) {
1137  data = f.readAll();
1138  f.close();
1139  } else {
1140  return QVariant();
1141  }
1142 
1143  return data;
1144 }
1145 
1158 {
1159  Q_D(const QTextBrowser);
1160  return d->stack.count() > 1;
1161 }
1162 
1175 {
1176  Q_D(const QTextBrowser);
1177  return !d->forwardStack.isEmpty();
1178 }
1179 
1192 {
1193  Q_D(QTextBrowser);
1194  d->forwardStack.clear();
1195  if (!d->stack.isEmpty()) {
1196  QTextBrowserPrivate::HistoryEntry historyEntry = d->stack.top();
1197  d->stack.resize(0);
1198  d->stack.push(historyEntry);
1199  d->home = historyEntry.url;
1200  }
1201  emit forwardAvailable(false);
1202  emit backwardAvailable(false);
1203  emit historyChanged();
1204 }
1205 
1219 {
1220  Q_D(const QTextBrowser);
1221  return d->history(i).url;
1222 }
1223 
1239 {
1240  Q_D(const QTextBrowser);
1241  return d->history(i).title;
1242 }
1243 
1244 
1251 {
1252  Q_D(const QTextBrowser);
1253  return d->forwardStack.count();
1254 }
1255 
1262 {
1263  Q_D(const QTextBrowser);
1264  return d->stack.count()-1;
1265 }
1266 
1282 {
1283  Q_D(const QTextBrowser);
1284  return d->openExternalLinks;
1285 }
1286 
1288 {
1289  Q_D(QTextBrowser);
1290  d->openExternalLinks = open;
1291 }
1292 
1308 bool QTextBrowser::openLinks() const
1309 {
1310  Q_D(const QTextBrowser);
1311  return d->openLinks;
1312 }
1313 
1315 {
1316  Q_D(QTextBrowser);
1317  d->openLinks = open;
1318 }
1319 
1322 {
1323  return QTextEdit::event(e);
1324 }
1325 
1327 
1328 #include "moc_qtextbrowser.cpp"
1329 
1330 #endif // QT_NO_TEXTBROWSER
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:92
QBool contains(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.h:904
The QPainter class performs low-level painting on widgets and other paint devices.
Definition: qpainter.h:86
double d
Definition: qnumeric_p.h:62
virtual bool event(QEvent *e)
Definition: qtextedit.cpp:1071
int anchor() const
Returns the anchor position; this is the same as position() unless there is a selection in which case...
HistoryEntry history(int i) const
The QKeyEvent class describes a key event.
Definition: qevent.h:224
bool findNextPrevAnchor(const QTextCursor &from, bool next, QTextCursor &newAnchor)
virtual void paintEvent(QPaintEvent *e)
Reimplemented Function
bool isValid() const
Returns true if the URL is valid; otherwise returns false.
Definition: qurl.cpp:4303
The QTextCharFormat class provides formatting information for characters in a QTextDocument.
Definition: qtextformat.h:372
The QCursor class provides a mouse cursor with an arbitrary shape.
Definition: qcursor.h:89
QTextCharFormat charFormat() const
Returns the format of the character immediately before the cursor position().
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
virtual void forward()
Changes the document displayed to the next document in the list of documents built by navigating link...
static QString fromAscii(const char *, int size=-1)
Returns a QString initialized with the first size characters from the string str. ...
Definition: qstring.cpp:4276
QCursor cursor() const
virtual void focusOutEvent(QFocusEvent *ev)
Reimplemented Function
QString anchorAtCursor() const
void setTextCursor(const QTextCursor &cursor)
QString toString(FormattingOptions options=None) const
Returns the human-displayable string representation of the URL.
Definition: qurl.cpp:5896
QSizeF size() const
QUrl source() const
bool open(OpenMode flags)
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition: qfile.cpp:1064
void setTextInteractionFlags(Qt::TextInteractionFlags flags)
void setOpenExternalLinks(bool open)
QByteArray toUtf8() const Q_REQUIRED_RESULT
Returns a UTF-8 representation of the string as a QByteArray.
Definition: qstring.cpp:4074
qreal width() const
Returns the width.
Definition: qsize.h:284
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
virtual void keyPressEvent(QKeyEvent *ev)
The event ev is used to provide the following keyboard shortcuts:
void setOpenLinks(bool open)
#define SLOT(a)
Definition: qobjectdefs.h:226
The QPointF class defines a point in the plane using floating point precision.
Definition: qpoint.h:214
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:150
QString toString() const
Returns the variant as a QString if the variant has type() String , Bool , ByteArray ...
Definition: qvariant.cpp:2270
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition: qstring.cpp:3734
virtual bool focusNextPrevChild(bool next)
Reimplemented Function
Definition: qtextedit.cpp:1627
QStringList searchPaths() const
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
The QStack class is a template class that provides a stack.
Definition: qcontainerfwd.h:63
QString anchorHref() const
Returns the text format&#39;s hypertext link, or an empty string if none has been set.
Definition: qtextformat.h:506
QStringList searchPaths
virtual void mousePressEvent(QMouseEvent *e)
Reimplemented Function
Definition: qtextedit.cpp:1575
bool intersects(const QRectF &r) const
Returns true if this rectangle intersects with the given rectangle (i.
Definition: qrect.cpp:2744
The QUrl class provides a convenient interface for working with URLs.
Definition: qurl.h:61
The QString class provides a Unicode character string.
Definition: qstring.h:83
int forwardHistoryCount() const
Returns the number of locations forward in the history.
QUrl resolveUrl(const QString &url) const
virtual void mousePressEvent(QMouseEvent *ev)
Reimplemented Function
virtual QVariant loadResource(int type, const QUrl &name)
This function is called when the document is loaded and for each image in the document.
void setSource(const QUrl &url)
#define Q_D(Class)
Definition: qglobal.h:2482
QString fragment() const
Returns the fragment of the URL.
Definition: qurl.cpp:5687
static QChar separator()
Returns the native directory separator: "/" under Unix (including Mac OS X) and "\\" under Windows...
Definition: qdir.cpp:1831
bool isRelative() const
Returns true if the URL is relative; otherwise returns false.
Definition: qurl.cpp:5880
QByteArray toByteArray() const
Returns the variant as a QByteArray if the variant has type() ByteArray or String (converted using QS...
Definition: qvariant.cpp:2383
QString documentTitle() const
Definition: qtextedit.h:170
QTextCursor textCursor() const
void setSearchPaths(const QStringList &paths)
virtual ~QTextBrowser()
QString path() const
Returns the path of the URL.
Definition: qurl.cpp:4977
void setObjectName(const QString &name)
Definition: qobject.cpp:1112
#define Q_Q(Class)
Definition: qglobal.h:2483
QWidgetData data
Definition: qwidget_p.h:755
Qt::KeyboardModifiers modifiers() const
Returns the keyboard modifier flags that existed immediately after the event occurred.
Definition: qevent.cpp:999
int key() const
Returns the code of the key that was pressed or released.
Definition: qevent.h:231
#define SIGNAL(a)
Definition: qobjectdefs.h:227
virtual void home()
Changes the document displayed to be the first document from the history.
int value() const
bool openLinks() const
virtual void setSource(const QUrl &name)
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
void _q_highlightLink(const QString &href)
The QRectF class defines a rectangle in the plane using floating point precision. ...
Definition: qrect.h:511
virtual void mouseMoveEvent(QMouseEvent *e)
Reimplemented Function
Definition: qtextedit.cpp:1587
QString left(int n) const Q_REQUIRED_RESULT
Returns a substring that contains the n leftmost characters of the string.
Definition: qstring.cpp:3664
bool hasSelection() const
Returns true if the cursor contains a selection; otherwise returns false.
virtual void reload()
Reloads the current set source.
int height
the height of the widget excluding any window frame
Definition: qwidget.h:167
static bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
Creates a connection of the given type from the signal in the sender object to the method in the rece...
Definition: qobject.cpp:2580
virtual void mouseReleaseEvent(QMouseEvent *e)
Reimplemented Function
Definition: qtextedit.cpp:1604
void historyChanged()
This signal is emitted when the history changes.
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
The QTextCursor class offers an API to access and modify QTextDocuments.
Definition: qtextcursor.h:70
qreal height() const
Returns the height of the rectangle.
Definition: qrect.h:710
const char * name
#define emit
Definition: qobjectdefs.h:76
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
virtual bool focusNextPrevChild(bool next)
Reimplemented Function
bool isBackwardAvailable() const
Returns true if the text browser can go backward in the document history using backward().
QWidgetData * data
Definition: qwidget.h:815
Q_CORE_EXPORT void qWarning(const char *,...)
QStack< HistoryEntry > stack
int indexOf(QChar c, int from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.cpp:2838
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal...
Definition: qstring.h:654
static QTextCodec * codec(MYSQL *mysql)
Definition: qsql_mysql.cpp:220
QTextEdit(QWidget *parent=0)
Constructs an empty QTextEdit with parent parent.
Definition: qtextedit.cpp:608
void setCursor(const QCursor &)
Definition: qwidget.cpp:5290
QStack< HistoryEntry > forwardStack
QCursor cursor
the cursor shape for this widget
Definition: qwidget.h:183
QByteArray toLatin1() const Q_REQUIRED_RESULT
Returns a Latin-1 representation of the string as a QByteArray.
Definition: qstring.cpp:3993
int position() const
Returns the absolute position of the cursor within the document.
void restoreHistoryEntry(const HistoryEntry entry)
virtual QUrl resolveUrl(const QUrl &url) const
virtual void focusOutEvent(QFocusEvent *e)
Reimplemented Function
Definition: qtextedit.cpp:1758
QString toLocalFile() const
Returns the path of this URL formatted as a local file path.
Definition: qurl.cpp:6412
void setFragment(const QString &fragment)
Sets the fragment of the URL to fragment.
Definition: qurl.cpp:5669
void clearSelection()
Clears the current selection by setting the anchor to the cursor position.
HistoryEntry createHistoryEntry() const
QTextDocument * document() const
QRectF selectionRect(const QTextCursor &cursor) const
virtual void backward()
Changes the document displayed to the previous document in the list of documents built by navigating ...
void setMouseTracking(bool enable)
Definition: qwidget.h:990
The QMouseEvent class contains parameters that describe a mouse event.
Definition: qevent.h:85
void highlighted(const QUrl &)
This signal is emitted when the user has selected but not activated an anchor in the document...
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
QString toUnicode(const QByteArray &) const
Converts a from the encoding of this codec to Unicode, and returns the result in a QString...
virtual void mouseMoveEvent(QMouseEvent *ev)
Reimplemented Function
void setCursorIsFocusIndicator(bool b)
QString scheme() const
Returns the scheme of the URL.
Definition: qurl.cpp:4550
#define Q_DECLARE_PUBLIC(Class)
Definition: qglobal.h:2477
QString & append(QChar c)
Definition: qstring.cpp:1777
The QFile class provides an interface for reading from and writing to files.
Definition: qfile.h:65
bool openExternalLinks() const
QString findFile(const QUrl &name) const
Type type() const
Returns the storage type of the value stored in the variant.
Definition: qvariant.cpp:1901
QObject * parent() const
Returns a pointer to the parent object.
Definition: qobject.h:273
QRectF united(const QRectF &other) const
Returns the bounding rectangle of this rectangle and the given rectangle.
Definition: qrect.h:828
Q_DECL_CONSTEXPR const T & qBound(const T &min, const T &val, const T &max)
Definition: qglobal.h:1219
The QTextBrowser class provides a rich text browser with hypertext navigation.
Definition: qtextbrowser.h:58
void _q_activateAnchor(const QString &href)
bool event(QEvent *e)
Reimplemented Function
QTextControl * control
Definition: qtextedit_p.h:109
bool hasFragment() const
Returns true if this URL contains a fragment (i.
Definition: qurl.cpp:5773
QByteArray readAll()
Reads all available data from the device, and returns it as a QByteArray.
Definition: qiodevice.cpp:1025
int backwardHistoryCount() const
Returns the number of locations backward in the history.
bool setFocusToAnchor(const QTextCursor &newCursor)
QObject * parent
Definition: qobject.h:92
QTextCursor cursorForPosition(const QPointF &pos) const
void setPosition(int pos, MoveMode mode=MoveAnchor)
Moves the cursor to the absolute position in the document specified by pos using a MoveMode specified...
static void setOverrideCursor(const QCursor &)
Use changeOverrideCursor(cursor) (if replace is true) or setOverrideCursor(cursor) (if replace is fal...
qreal top() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:526
static QUrl fromLocalFile(const QString &localfile)
Returns a QUrl representation of localFile, interpreted as a local file.
Definition: qurl.cpp:6374
void ignore()
Clears the accept flag parameter of the event object, the equivalent of calling setAccepted(false).
Definition: qcoreevent.h:310
void accept()
Sets the accept flag of the event object, the equivalent of calling setAccepted(true).
Definition: qcoreevent.h:309
bool isForwardAvailable() const
Returns true if the text browser can go forward in the document history using forward().
QString historyTitle(int) const
Returns the documentTitle() of the HistoryItem.
QUrl historyUrl(int) const
Returns the url of the HistoryItem.
qreal bottom() const
Returns the y-coordinate of the rectangle&#39;s bottom edge.
Definition: qrect.h:528
static void restoreOverrideCursor()
Undoes the last setOverrideCursor().
static QUrl fromEncoded(const QByteArray &url)
Parses input and returns the corresponding QUrl.
Definition: qurl.cpp:5964
The QTextCodec class provides conversions between text encodings.
Definition: qtextcodec.h:62
static void showText(const QPoint &pos, const QString &text, QWidget *w=0)
Shows text as a "What&#39;s This?" window, at global position pos.
Definition: qwhatsthis.cpp:754
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
Definition: qstring.cpp:3796
QUrl resolved(const QUrl &relative) const
Returns the result of the merge of this URL with relative.
Definition: qurl.cpp:5819
The QFileInfo class provides system-independent file information.
Definition: qfileinfo.h:60
bool cursorIsFocusIndicator() const
The QPaintEvent class contains event parameters for paint events.
Definition: qevent.h:298
int maximum() const
void backwardAvailable(bool)
This signal is emitted when the availability of backward() changes.
virtual void mouseReleaseEvent(QMouseEvent *ev)
Reimplemented Function
virtual void close()
Calls QFile::flush() and closes the file.
Definition: qfile.cpp:1680
void clearHistory()
Clears the history of visited documents and disables the forward and backward navigation.
void forwardAvailable(bool)
This signal is emitted when the availability of forward() changes.
The QEvent class is the base class of all event classes.
Definition: qcoreevent.h:56
static QString fileName(const QString &fileUrl)
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
virtual void keyPressEvent(QKeyEvent *e)
Reimplemented Function
Definition: qtextedit.cpp:1210
The QFocusEvent class contains event parameters for widget focus events.
Definition: qevent.h:275
The QTextEdit class provides a widget that is used to edit and display both plain and rich text...
Definition: qtextedit.h:70
QTextBrowser(QWidget *parent=0)
Constructs an empty QTextBrowser with parent parent.
int open(const char *, int,...)
static QPoint pos()
Returns the position of the cursor (hot spot) in global screen coordinates.
Definition: qcursor_mac.mm:310
static bool openUrl(const QUrl &url)
Opens the given url in the appropriate Web browser for the user&#39;s desktop environment, and returns true if successful; otherwise returns false.
Qt::CursorShape shape() const
Returns the cursor shape identifier.
Definition: qcursor.cpp:469
Q_GUI_EXPORT QTextCodec * codecForHtml(const QByteArray &ba)
This function is defined in the <QTextDocument> header file.