source: trunk/src/gui/kernel/qwhatsthis.cpp

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 22.8 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qwhatsthis.h"
43#ifndef QT_NO_WHATSTHIS
44#include "qpointer.h"
45#include "qapplication.h"
46#include "qdesktopwidget.h"
47#include "qevent.h"
48#include "qpixmap.h"
49#include "qpainter.h"
50#include "qtimer.h"
51#include "qhash.h"
52#include "qaction.h"
53#include "qcursor.h"
54#include "qbitmap.h"
55#include "qtextdocument.h"
56#include "../text/qtextdocumentlayout_p.h"
57#include "qtoolbutton.h"
58#include "qdebug.h"
59#ifndef QT_NO_ACCESSIBILITY
60#include "qaccessible.h"
61#endif
62#if defined(Q_WS_WIN)
63#include "qt_windows.h"
64#ifndef SPI_GETDROPSHADOW
65#define SPI_GETDROPSHADOW 0x1024
66#endif
67#endif
68#if defined(Q_WS_X11)
69#include "qx11info_x11.h"
70#include <qwidget.h>
71#endif
72
73QT_BEGIN_NAMESPACE
74
75/*!
76 \class QWhatsThis
77 \brief The QWhatsThis class provides a simple description of any
78 widget, i.e. answering the question "What's This?".
79
80 \ingroup helpsystem
81
82
83 "What's This?" help is part of an application's online help
84 system, and provides users with information about the
85 functionality and usage of a particular widget. "What's This?"
86 help texts are typically longer and more detailed than \link
87 QToolTip tooltips\endlink, but generally provide less information
88 than that supplied by separate help windows.
89
90 QWhatsThis provides a single window with an explanatory text that
91 pops up when the user asks "What's This?". The default way for
92 users to ask the question is to move the focus to the relevant
93 widget and press Shift+F1. The help text appears immediately; it
94 goes away as soon as the user does something else.
95 (Note that if there is a shortcut for Shift+F1, this mechanism
96 will not work.) Some dialogs provide a "?" button that users can
97 click to enter "What's This?" mode; they then click the relevant
98 widget to pop up the "What's This?" window. It is also possible to
99 provide a a menu option or toolbar button to switch into "What's
100 This?" mode.
101
102 To add "What's This?" text to a widget or an action, you simply
103 call QWidget::setWhatsThis() or QAction::setWhatsThis().
104
105 The text can be either rich text or plain text. If you specify a
106 rich text formatted string, it will be rendered using the default
107 stylesheet, making it possible to embed images in the displayed
108 text. To be as fast as possible, the default stylesheet uses a
109 simple method to determine whether the text can be rendered as
110 plain text. See Qt::mightBeRichText() for details.
111
112 \snippet doc/src/snippets/whatsthis/whatsthis.cpp 0
113
114 An alternative way to enter "What's This?" mode is to call
115 createAction(), and add the returned QAction to either a menu or
116 a tool bar. By invoking this context help action (in the picture
117 below, the button with the arrow and question mark icon) the user
118 switches into "What's This?" mode. If they now click on a widget
119 the appropriate help text is shown. The mode is left when help is
120 given or when the user presses Esc.
121
122 \img whatsthis.png
123
124 You can enter "What's This?" mode programmatically with
125 enterWhatsThisMode(), check the mode with inWhatsThisMode(), and
126 return to normal mode with leaveWhatsThisMode().
127
128 If you want to control the "What's This?" behavior of a widget
129 manually see Qt::WA_CustomWhatsThis.
130
131 It is also possible to show different help texts for different
132 regions of a widget, by using a QHelpEvent of type
133 QEvent::WhatsThis. Intercept the help event in your widget's
134 QWidget::event() function and call QWhatsThis::showText() with the
135 text you want to display for the position specified in
136 QHelpEvent::pos(). If the text is rich text and the user clicks
137 on a link, the widget also receives a QWhatsThisClickedEvent with
138 the link's reference as QWhatsThisClickedEvent::href(). If a
139 QWhatsThisClickedEvent is handled (i.e. QWidget::event() returns
140 true), the help window remains visible. Call
141 QWhatsThis::hideText() to hide it explicitly.
142
143 \sa QToolTip
144*/
145
146Q_CORE_EXPORT void qDeleteInEventHandler(QObject *o);
147
148class QWhatsThat : public QWidget
149{
150 Q_OBJECT
151
152public:
153 QWhatsThat(const QString& txt, QWidget* parent, QWidget *showTextFor);
154 ~QWhatsThat() ;
155
156 static QWhatsThat *instance;
157
158protected:
159 void showEvent(QShowEvent *e);
160 void mousePressEvent(QMouseEvent*);
161 void mouseReleaseEvent(QMouseEvent*);
162 void mouseMoveEvent(QMouseEvent*);
163 void keyPressEvent(QKeyEvent*);
164 void paintEvent(QPaintEvent*);
165
166private:
167 QPointer<QWidget>widget;
168 bool pressed;
169 QString text;
170 QTextDocument* doc;
171 QString anchor;
172 QPixmap background;
173};
174
175QWhatsThat *QWhatsThat::instance = 0;
176
177// shadowWidth not const, for XP drop-shadow-fu turns it to 0
178static int shadowWidth = 6; // also used as '5' and '6' and even '8' below
179static const int vMargin = 8;
180static const int hMargin = 12;
181
182QWhatsThat::QWhatsThat(const QString& txt, QWidget* parent, QWidget *showTextFor)
183 : QWidget(parent, Qt::Popup),
184 widget(showTextFor), pressed(false), text(txt)
185{
186 delete instance;
187 instance = this;
188 setAttribute(Qt::WA_DeleteOnClose, true);
189 setAttribute(Qt::WA_NoSystemBackground, true);
190 if (parent)
191 setPalette(parent->palette());
192 setMouseTracking(true);
193 setFocusPolicy(Qt::StrongFocus);
194#ifndef QT_NO_CURSOR
195 setCursor(Qt::ArrowCursor);
196#endif
197 QRect r;
198 doc = 0;
199 ensurePolished(); // Ensures style sheet font before size calc
200 if (Qt::mightBeRichText(text)) {
201 doc = new QTextDocument();
202 doc->setUndoRedoEnabled(false);
203 doc->setDefaultFont(QApplication::font(this));
204#ifdef QT_NO_TEXTHTMLPARSER
205 doc->setPlainText(text);
206#else
207 doc->setHtml(text);
208#endif
209 doc->setUndoRedoEnabled(false);
210 doc->adjustSize();
211 r.setTop(0);
212 r.setLeft(0);
213 r.setSize(doc->size().toSize());
214 }
215 else
216 {
217 int sw = QApplication::desktop()->width() / 3;
218 if (sw < 200)
219 sw = 200;
220 else if (sw > 300)
221 sw = 300;
222
223 r = fontMetrics().boundingRect(0, 0, sw, 1000,
224 Qt::AlignLeft + Qt::AlignTop
225 + Qt::TextWordWrap + Qt::TextExpandTabs,
226 text);
227 }
228#if defined(Q_WS_WIN)
229 if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP
230 && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based))
231 {
232 BOOL shadow;
233 SystemParametersInfo(SPI_GETDROPSHADOW, 0, &shadow, 0);
234 shadowWidth = shadow ? 0 : 6;
235 }
236#endif
237 resize(r.width() + 2*hMargin + shadowWidth, r.height() + 2*vMargin + shadowWidth);
238}
239
240QWhatsThat::~QWhatsThat()
241{
242 instance = 0;
243 if (doc)
244 delete doc;
245}
246
247void QWhatsThat::showEvent(QShowEvent *)
248{
249 background = QPixmap::grabWindow(QApplication::desktop()->internalWinId(),
250 x(), y(), width(), height());
251}
252
253void QWhatsThat::mousePressEvent(QMouseEvent* e)
254{
255 pressed = true;
256 if (e->button() == Qt::LeftButton && rect().contains(e->pos())) {
257 if (doc)
258 anchor = doc->documentLayout()->anchorAt(e->pos() - QPoint(hMargin, vMargin));
259 return;
260 }
261 close();
262}
263
264void QWhatsThat::mouseReleaseEvent(QMouseEvent* e)
265{
266 if (!pressed)
267 return;
268 if (widget && e->button() == Qt::LeftButton && doc && rect().contains(e->pos())) {
269 QString a = doc->documentLayout()->anchorAt(e->pos() - QPoint(hMargin, vMargin));
270 QString href;
271 if (anchor == a)
272 href = a;
273 anchor.clear();
274 if (!href.isEmpty()) {
275 QWhatsThisClickedEvent e(href);
276 if (QApplication::sendEvent(widget, &e))
277 return;
278 }
279 }
280 close();
281}
282
283void QWhatsThat::mouseMoveEvent(QMouseEvent* e)
284{
285#ifdef QT_NO_CURSOR
286 Q_UNUSED(e);
287#else
288 if (!doc)
289 return;
290 QString a = doc->documentLayout()->anchorAt(e->pos() - QPoint(hMargin, vMargin));
291 if (!a.isEmpty())
292 setCursor(Qt::PointingHandCursor);
293 else
294 setCursor(Qt::ArrowCursor);
295#endif
296}
297
298void QWhatsThat::keyPressEvent(QKeyEvent*)
299{
300 close();
301}
302
303void QWhatsThat::paintEvent(QPaintEvent*)
304{
305 bool drawShadow = true;
306#if defined(Q_WS_WIN)
307 if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP
308 && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based))
309 {
310 BOOL shadow;
311 SystemParametersInfo(SPI_GETDROPSHADOW, 0, &shadow, 0);
312 drawShadow = !shadow;
313 }
314#elif defined(Q_WS_MAC) || defined(Q_WS_QWS)
315 drawShadow = false; // never draw it on OS X or QWS, as we get it for free
316#endif
317
318 QRect r = rect();
319 r.adjust(0, 0, -1, -1);
320 if (drawShadow)
321 r.adjust(0, 0, -shadowWidth, -shadowWidth);
322 QPainter p(this);
323 p.drawPixmap(0, 0, background);
324 p.setPen(QPen(palette().toolTipText(), 0));
325 p.setBrush(palette().toolTipBase());
326 p.drawRect(r);
327 int w = r.width();
328 int h = r.height();
329 p.setPen(palette().brush(QPalette::Dark).color());
330 p.drawRect(1, 1, w-2, h-2);
331 if (drawShadow) {
332 p.setPen(palette().shadow().color());
333 p.drawPoint(w + 5, 6);
334 p.drawLine(w + 3, 6, w + 5, 8);
335 p.drawLine(w + 1, 6, w + 5, 10);
336 int i;
337 for(i=7; i < h; i += 2)
338 p.drawLine(w, i, w + 5, i + 5);
339 for(i = w - i + h; i > 6; i -= 2)
340 p.drawLine(i, h, i + 5, h + 5);
341 for(; i > 0 ; i -= 2)
342 p.drawLine(6, h + 6 - i, i + 5, h + 5);
343 }
344 r.adjust(0, 0, 1, 1);
345 p.setPen(palette().toolTipText().color());
346 r.adjust(hMargin, vMargin, -hMargin, -vMargin);
347
348 if (doc) {
349 p.translate(r.x(), r.y());
350 QRect rect = r;
351 rect.translate(-r.x(), -r.y());
352 p.setClipRect(rect);
353 QAbstractTextDocumentLayout::PaintContext context;
354 context.palette.setBrush(QPalette::Text, context.palette.toolTipText());
355 doc->documentLayout()->draw(&p, context);
356 }
357 else
358 {
359 p.drawText(r, Qt::AlignLeft + Qt::AlignTop + Qt::TextWordWrap + Qt::TextExpandTabs, text);
360 }
361}
362
363static const char * const button_image[] = {
364"16 16 3 1",
365" c None",
366"o c #000000",
367"a c #000080",
368"o aaaaa ",
369"oo aaa aaa ",
370"ooo aaa aaa",
371"oooo aa aa",
372"ooooo aa aa",
373"oooooo a aaa",
374"ooooooo aaa ",
375"oooooooo aaa ",
376"ooooooooo aaa ",
377"ooooo aaa ",
378"oo ooo ",
379"o ooo aaa ",
380" ooo aaa ",
381" ooo ",
382" ooo ",
383" ooo "};
384
385class QWhatsThisPrivate : public QObject
386{
387 public:
388 QWhatsThisPrivate();
389 ~QWhatsThisPrivate();
390 static QWhatsThisPrivate *instance;
391 bool eventFilter(QObject *, QEvent *);
392 QPointer<QAction> action;
393#ifdef QT3_SUPPORT
394 QPointer<QToolButton> button;
395#endif
396 static void say(QWidget *, const QString &, int x = 0, int y = 0);
397 static void notifyToplevels(QEvent *e);
398 bool leaveOnMouseRelease;
399};
400
401void QWhatsThisPrivate::notifyToplevels(QEvent *e)
402{
403 QWidgetList toplevels = QApplication::topLevelWidgets();
404 for (int i = 0; i < toplevels.count(); ++i) {
405 register QWidget *w = toplevels.at(i);
406 QApplication::sendEvent(w, e);
407 }
408}
409
410QWhatsThisPrivate *QWhatsThisPrivate::instance = 0;
411
412QWhatsThisPrivate::QWhatsThisPrivate()
413 : leaveOnMouseRelease(false)
414{
415 instance = this;
416 qApp->installEventFilter(this);
417
418 QPoint pos = QCursor::pos();
419 if (QWidget *w = QApplication::widgetAt(pos)) {
420 QHelpEvent e(QEvent::QueryWhatsThis, w->mapFromGlobal(pos), pos);
421 bool sentEvent = QApplication::sendEvent(w, &e);
422#ifdef QT_NO_CURSOR
423 Q_UNUSED(sentEvent);
424#else
425 QApplication::setOverrideCursor((!sentEvent || !e.isAccepted())?
426 Qt::ForbiddenCursor:Qt::WhatsThisCursor);
427 } else {
428 QApplication::setOverrideCursor(Qt::WhatsThisCursor);
429#endif
430 }
431#ifndef QT_NO_ACCESSIBILITY
432 QAccessible::updateAccessibility(this, 0, QAccessible::ContextHelpStart);
433#endif
434}
435
436QWhatsThisPrivate::~QWhatsThisPrivate()
437{
438 if (action)
439 action->setChecked(false);
440#ifdef QT3_SUPPORT
441 if (button)
442 button->setChecked(false);
443#endif
444#ifndef QT_NO_CURSOR
445 QApplication::restoreOverrideCursor();
446#endif
447#ifndef QT_NO_ACCESSIBILITY
448 QAccessible::updateAccessibility(this, 0, QAccessible::ContextHelpEnd);
449#endif
450 instance = 0;
451}
452
453bool QWhatsThisPrivate::eventFilter(QObject *o, QEvent *e)
454{
455 if (!o->isWidgetType())
456 return false;
457 QWidget * w = static_cast<QWidget *>(o);
458 bool customWhatsThis = w->testAttribute(Qt::WA_CustomWhatsThis);
459 switch (e->type()) {
460 case QEvent::MouseButtonPress:
461 {
462 QMouseEvent *me = static_cast<QMouseEvent*>(e);
463 if (me->button() == Qt::RightButton || customWhatsThis)
464 return false;
465 QHelpEvent e(QEvent::WhatsThis, me->pos(), me->globalPos());
466 if (!QApplication::sendEvent(w, &e) || !e.isAccepted())
467 leaveOnMouseRelease = true;
468
469 } break;
470
471 case QEvent::MouseMove:
472 {
473 QMouseEvent *me = static_cast<QMouseEvent*>(e);
474 QHelpEvent e(QEvent::QueryWhatsThis, me->pos(), me->globalPos());
475 bool sentEvent = QApplication::sendEvent(w, &e);
476#ifdef QT_NO_CURSOR
477 Q_UNUSED(sentEvent);
478#else
479 QApplication::changeOverrideCursor((!sentEvent || !e.isAccepted())?
480 Qt::ForbiddenCursor:Qt::WhatsThisCursor);
481#endif
482 }
483 // fall through
484 case QEvent::MouseButtonRelease:
485 case QEvent::MouseButtonDblClick:
486 if (leaveOnMouseRelease && e->type() == QEvent::MouseButtonRelease)
487 QWhatsThis::leaveWhatsThisMode();
488 if (static_cast<QMouseEvent*>(e)->button() == Qt::RightButton || customWhatsThis)
489 return false; // ignore RMB release
490 break;
491 case QEvent::KeyPress:
492 {
493 QKeyEvent* kev = (QKeyEvent*)e;
494
495 if (kev->key() == Qt::Key_Escape) {
496 QWhatsThis::leaveWhatsThisMode();
497 return true;
498 } else if (customWhatsThis) {
499 return false;
500 } else if (kev->key() == Qt::Key_Menu ||
501 (kev->key() == Qt::Key_F10 &&
502 kev->modifiers() == Qt::ShiftModifier)) {
503 // we don't react to these keys, they are used for context menus
504 return false;
505 } else if (kev->key() != Qt::Key_Shift && kev->key() != Qt::Key_Alt // not a modifier key
506 && kev->key() != Qt::Key_Control && kev->key() != Qt::Key_Meta) {
507 QWhatsThis::leaveWhatsThisMode();
508 }
509 } break;
510 default:
511 return false;
512 }
513 return true;
514}
515
516class QWhatsThisAction: public QAction
517{
518 Q_OBJECT
519
520public:
521 explicit QWhatsThisAction(QObject* parent = 0);
522
523private slots:
524 void actionTriggered();
525};
526
527QWhatsThisAction::QWhatsThisAction(QObject *parent) : QAction(tr("What's This?"), parent)
528{
529#ifndef QT_NO_IMAGEFORMAT_XPM
530 QPixmap p((const char**)button_image);
531 setIcon(p);
532#endif
533 setCheckable(true);
534 connect(this, SIGNAL(triggered()), this, SLOT(actionTriggered()));
535#ifndef QT_NO_SHORTCUT
536 setShortcut(Qt::ShiftModifier + Qt::Key_F1);
537#endif
538}
539
540void QWhatsThisAction::actionTriggered()
541{
542 if (isChecked()) {
543 QWhatsThis::enterWhatsThisMode();
544 QWhatsThisPrivate::instance->action = this;
545 }
546}
547
548QWhatsThis::QWhatsThis()
549{
550}
551
552#ifdef QT3_SUPPORT
553/*!
554 \obsolete
555
556 Sets the What's This text \a s for the widget \a w.
557
558 Use QWidget::setWhatsThis() or QAction::setWhatsThis() instead.
559*/
560void QWhatsThis::add(QWidget *w, const QString &s)
561{
562 w->setWhatsThis(s);
563}
564
565/*!
566 \obsolete
567
568 Remove's the What's This text for the widget \a w.
569
570 Use QWidget::setWhatsThis() or QAction::setWhatsThis() instead.
571*/
572void QWhatsThis::remove(QWidget *w)
573{
574 w->setWhatsThis(QString());
575}
576
577class QWhatsThisButton : public QToolButton
578{
579 Q_OBJECT
580public:
581 QWhatsThisButton(QWidget *p) : QToolButton(p) {
582 setCheckable(true);
583 QPixmap pix( const_cast<const char**>(button_image) );
584 setIcon( pix );
585 QObject::connect(this, SIGNAL(toggled(bool)), this, SLOT(whatToggled(bool)));
586 setAutoRaise(true);
587 setFocusPolicy(Qt::NoFocus);
588 }
589
590public slots:
591 void whatToggled(bool b) {
592 if (b) {
593 QWhatsThis::enterWhatsThisMode();
594 QWhatsThisPrivate::instance->button = this;
595 }
596 }
597};
598
599/*!
600 Returns a new "What's This?" QToolButton with the given \a
601 parent. To do this now, create your own QToolButton and a
602 QWhatsThis object and call the QWhatsThis object's showText()
603 function when the QToolButton is invoked.
604
605 Use createAction() instead.
606*/
607QToolButton * QWhatsThis::whatsThisButton(QWidget * parent)
608{
609 return new QWhatsThisButton(parent);
610}
611#endif
612
613/*!
614 This function switches the user interface into "What's This?"
615 mode. The user interface can be switched back into normal mode by
616 the user (e.g. by them clicking or pressing Esc), or
617 programmatically by calling leaveWhatsThisMode().
618
619 When entering "What's This?" mode, a QEvent of type
620 Qt::EnterWhatsThisMode is sent to all toplevel widgets.
621
622 \sa inWhatsThisMode() leaveWhatsThisMode()
623*/
624void QWhatsThis::enterWhatsThisMode()
625{
626 if (QWhatsThisPrivate::instance)
627 return;
628 (void) new QWhatsThisPrivate;
629 QEvent e(QEvent::EnterWhatsThisMode);
630 QWhatsThisPrivate::notifyToplevels(&e);
631 }
632
633/*!
634 Returns true if the user interface is in "What's This?" mode;
635 otherwise returns false.
636
637 \sa enterWhatsThisMode()
638*/
639bool QWhatsThis::inWhatsThisMode()
640{
641 return (QWhatsThisPrivate::instance != 0);
642}
643
644/*!
645 If the user interface is in "What's This?" mode, this function
646 switches back to normal mode; otherwise it does nothing.
647
648 When leaving "What's This?" mode, a QEvent of type
649 Qt::LeaveWhatsThisMode is sent to all toplevel widgets.
650
651 \sa enterWhatsThisMode() inWhatsThisMode()
652*/
653void QWhatsThis::leaveWhatsThisMode()
654{
655 delete QWhatsThisPrivate::instance;
656 QEvent e(QEvent::LeaveWhatsThisMode);
657 QWhatsThisPrivate::notifyToplevels(&e);
658}
659
660void QWhatsThisPrivate::say(QWidget * widget, const QString &text, int x, int y)
661{
662 if (text.size() == 0)
663 return;
664 // make a fresh widget, and set it up
665 QWhatsThat *whatsThat = new QWhatsThat(
666 text,
667#if defined(Q_WS_X11) && !defined(QT_NO_CURSOR)
668 QApplication::desktop()->screen(widget ? widget->x11Info().screen() : QCursor::x11Screen()),
669#else
670 0,
671#endif
672 widget
673 );
674
675
676 // okay, now to find a suitable location
677
678 int scr = (widget ?
679 QApplication::desktop()->screenNumber(widget) :
680#if defined(Q_WS_X11) && !defined(QT_NO_CURSOR)
681 QCursor::x11Screen()
682#else
683 QApplication::desktop()->screenNumber(QPoint(x,y))
684#endif // Q_WS_X11
685 );
686 QRect screen = QApplication::desktop()->screenGeometry(scr);
687
688 int w = whatsThat->width();
689 int h = whatsThat->height();
690 int sx = screen.x();
691 int sy = screen.y();
692
693 // first try locating the widget immediately above/below,
694 // with nice alignment if possible.
695 QPoint pos;
696 if (widget)
697 pos = widget->mapToGlobal(QPoint(0,0));
698
699 if (widget && w > widget->width() + 16)
700 x = pos.x() + widget->width()/2 - w/2;
701 else
702 x = x - w/2;
703
704 // squeeze it in if that would result in part of what's this
705 // being only partially visible
706 if (x + w + shadowWidth > sx+screen.width())
707 x = (widget? (qMin(screen.width(),
708 pos.x() + widget->width())
709 ) : screen.width())
710 - w;
711
712 if (x < sx)
713 x = sx;
714
715 if (widget && h > widget->height() + 16) {
716 y = pos.y() + widget->height() + 2; // below, two pixels spacing
717 // what's this is above or below, wherever there's most space
718 if (y + h + 10 > sy+screen.height())
719 y = pos.y() + 2 - shadowWidth - h; // above, overlap
720 }
721 y = y + 2;
722
723 // squeeze it in if that would result in part of what's this
724 // being only partially visible
725 if (y + h + shadowWidth > sy+screen.height())
726 y = (widget ? (qMin(screen.height(),
727 pos.y() + widget->height())
728 ) : screen.height())
729 - h;
730 if (y < sy)
731 y = sy;
732
733 whatsThat->move(x, y);
734 whatsThat->show();
735 whatsThat->grabKeyboard();
736}
737
738/*!
739 Shows \a text as a "What's This?" window, at global position \a
740 pos. The optional widget argument, \a w, is used to determine the
741 appropriate screen on multi-head systems.
742
743 \sa hideText()
744*/
745void QWhatsThis::showText(const QPoint &pos, const QString &text, QWidget *w)
746{
747 leaveWhatsThisMode();
748 QWhatsThisPrivate::say(w, text, pos.x(), pos.y());
749}
750
751/*!
752 If a "What's This?" window is showing, this destroys it.
753
754 \sa showText()
755*/
756void QWhatsThis::hideText()
757{
758 qDeleteInEventHandler(QWhatsThat::instance);
759}
760
761/*!
762 Returns a ready-made QAction, used to invoke "What's This?" context
763 help, with the given \a parent.
764
765 The returned QAction provides a convenient way to let users enter
766 "What's This?" mode.
767*/
768QAction *QWhatsThis::createAction(QObject *parent)
769{
770 return new QWhatsThisAction(parent);
771}
772
773QT_END_NAMESPACE
774
775#include "qwhatsthis.moc"
776
777#endif // QT_NO_WHATSTHIS
Note: See TracBrowser for help on using the repository browser.