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

Last change on this file since 284 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 22.6 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** 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 are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
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 \mainclass
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
146extern 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
198 QRect r;
199 doc = 0;
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_NT_based) > QSysInfo::WV_2000) {
230 BOOL shadow;
231 SystemParametersInfo(SPI_GETDROPSHADOW, 0, &shadow, 0);
232 shadowWidth = shadow ? 0 : 6;
233 }
234#endif
235 resize(r.width() + 2*hMargin + shadowWidth, r.height() + 2*vMargin + shadowWidth);
236}
237
238QWhatsThat::~QWhatsThat()
239{
240 instance = 0;
241 if (doc)
242 delete doc;
243}
244
245void QWhatsThat::showEvent(QShowEvent *)
246{
247 background = QPixmap::grabWindow(QApplication::desktop()->internalWinId(),
248 x(), y(), width(), height());
249}
250
251void QWhatsThat::mousePressEvent(QMouseEvent* e)
252{
253 pressed = true;
254 if (e->button() == Qt::LeftButton && rect().contains(e->pos())) {
255 if (doc)
256 anchor = doc->documentLayout()->anchorAt(e->pos() - QPoint(hMargin, vMargin));
257 return;
258 }
259 close();
260}
261
262void QWhatsThat::mouseReleaseEvent(QMouseEvent* e)
263{
264 if (!pressed)
265 return;
266 if (widget && e->button() == Qt::LeftButton && doc && rect().contains(e->pos())) {
267 QString a = doc->documentLayout()->anchorAt(e->pos() - QPoint(hMargin, vMargin));
268 QString href;
269 if (anchor == a)
270 href = a;
271 anchor.clear();
272 if (!href.isEmpty()) {
273 QWhatsThisClickedEvent e(href);
274 if (QApplication::sendEvent(widget, &e))
275 return;
276 }
277 }
278 close();
279}
280
281void QWhatsThat::mouseMoveEvent(QMouseEvent* e)
282{
283#ifdef QT_NO_CURSOR
284 Q_UNUSED(e);
285#else
286 if (!doc)
287 return;
288 QString a = doc->documentLayout()->anchorAt(e->pos() - QPoint(hMargin, vMargin));
289 if (!a.isEmpty())
290 setCursor(Qt::PointingHandCursor);
291 else
292 setCursor(Qt::ArrowCursor);
293#endif
294}
295
296void QWhatsThat::keyPressEvent(QKeyEvent*)
297{
298 close();
299}
300
301void QWhatsThat::paintEvent(QPaintEvent*)
302{
303 bool drawShadow = true;
304#if defined(Q_WS_WIN)
305 if ((QSysInfo::WindowsVersion&QSysInfo::WV_NT_based) > QSysInfo::WV_2000) {
306 BOOL shadow;
307 SystemParametersInfo(SPI_GETDROPSHADOW, 0, &shadow, 0);
308 drawShadow = !shadow;
309 }
310#elif defined(Q_WS_MAC) || defined(Q_WS_QWS)
311 drawShadow = false; // never draw it on OS X or QWS, as we get it for free
312#endif
313
314 QRect r = rect();
315 r.adjust(0, 0, -1, -1);
316 if (drawShadow)
317 r.adjust(0, 0, -shadowWidth, -shadowWidth);
318 QPainter p(this);
319 p.drawPixmap(0, 0, background);
320 p.setPen(QPen(palette().toolTipText(), 0));
321 p.setBrush(palette().toolTipBase());
322 p.drawRect(r);
323 int w = r.width();
324 int h = r.height();
325 p.setPen(palette().brush(QPalette::Dark).color());
326 p.drawRect(1, 1, w-2, h-2);
327 if (drawShadow) {
328 p.setPen(palette().shadow().color());
329 p.drawPoint(w + 5, 6);
330 p.drawLine(w + 3, 6, w + 5, 8);
331 p.drawLine(w + 1, 6, w + 5, 10);
332 int i;
333 for(i=7; i < h; i += 2)
334 p.drawLine(w, i, w + 5, i + 5);
335 for(i = w - i + h; i > 6; i -= 2)
336 p.drawLine(i, h, i + 5, h + 5);
337 for(; i > 0 ; i -= 2)
338 p.drawLine(6, h + 6 - i, i + 5, h + 5);
339 }
340 r.adjust(0, 0, 1, 1);
341 p.setPen(palette().toolTipText().color());
342 r.adjust(hMargin, vMargin, -hMargin, -vMargin);
343
344 if (doc) {
345 p.translate(r.x(), r.y());
346 QRect rect = r;
347 rect.translate(-r.x(), -r.y());
348 p.setClipRect(rect);
349 QAbstractTextDocumentLayout::PaintContext context;
350 doc->documentLayout()->draw(&p, context);
351 }
352 else
353 {
354 p.drawText(r, Qt::AlignLeft + Qt::AlignTop + Qt::TextWordWrap + Qt::TextExpandTabs, text);
355 }
356}
357
358static const char * const button_image[] = {
359"16 16 3 1",
360" c None",
361"o c #000000",
362"a c #000080",
363"o aaaaa ",
364"oo aaa aaa ",
365"ooo aaa aaa",
366"oooo aa aa",
367"ooooo aa aa",
368"oooooo a aaa",
369"ooooooo aaa ",
370"oooooooo aaa ",
371"ooooooooo aaa ",
372"ooooo aaa ",
373"oo ooo ",
374"o ooo aaa ",
375" ooo aaa ",
376" ooo ",
377" ooo ",
378" ooo "};
379
380class QWhatsThisPrivate : public QObject
381{
382 public:
383 QWhatsThisPrivate();
384 ~QWhatsThisPrivate();
385 static QWhatsThisPrivate *instance;
386 bool eventFilter(QObject *, QEvent *);
387 QPointer<QAction> action;
388#ifdef QT3_SUPPORT
389 QPointer<QToolButton> button;
390#endif
391 static void say(QWidget *, const QString &, int x = 0, int y = 0);
392 static void notifyToplevels(QEvent *e);
393 bool leaveOnMouseRelease;
394};
395
396void QWhatsThisPrivate::notifyToplevels(QEvent *e)
397{
398 QWidgetList toplevels = QApplication::topLevelWidgets();
399 for (int i = 0; i < toplevels.count(); ++i) {
400 register QWidget *w = toplevels.at(i);
401 QApplication::sendEvent(w, e);
402 }
403}
404
405QWhatsThisPrivate *QWhatsThisPrivate::instance = 0;
406
407QWhatsThisPrivate::QWhatsThisPrivate()
408 : leaveOnMouseRelease(false)
409{
410 instance = this;
411 qApp->installEventFilter(this);
412
413 QPoint pos = QCursor::pos();
414 if (QWidget *w = QApplication::widgetAt(pos)) {
415 QHelpEvent e(QEvent::QueryWhatsThis, w->mapFromGlobal(pos), pos);
416 bool sentEvent = QApplication::sendEvent(w, &e);
417#ifdef QT_NO_CURSOR
418 Q_UNUSED(sentEvent);
419#else
420 QApplication::setOverrideCursor((!sentEvent || !e.isAccepted())?
421 Qt::ForbiddenCursor:Qt::WhatsThisCursor);
422 } else {
423 QApplication::setOverrideCursor(Qt::WhatsThisCursor);
424#endif
425 }
426#ifndef QT_NO_ACCESSIBILITY
427 QAccessible::updateAccessibility(this, 0, QAccessible::ContextHelpStart);
428#endif
429}
430
431QWhatsThisPrivate::~QWhatsThisPrivate()
432{
433 if (action)
434 action->setChecked(false);
435#ifdef QT3_SUPPORT
436 if (button)
437 button->setChecked(false);
438#endif
439#ifndef QT_NO_CURSOR
440 QApplication::restoreOverrideCursor();
441#endif
442#ifndef QT_NO_ACCESSIBILITY
443 QAccessible::updateAccessibility(this, 0, QAccessible::ContextHelpEnd);
444#endif
445 instance = 0;
446}
447
448bool QWhatsThisPrivate::eventFilter(QObject *o, QEvent *e)
449{
450 if (!o->isWidgetType())
451 return false;
452 QWidget * w = static_cast<QWidget *>(o);
453 bool customWhatsThis = w->testAttribute(Qt::WA_CustomWhatsThis);
454 switch (e->type()) {
455 case QEvent::MouseButtonPress:
456 {
457 QMouseEvent *me = static_cast<QMouseEvent*>(e);
458 if (me->button() == Qt::RightButton || customWhatsThis)
459 return false;
460 QHelpEvent e(QEvent::WhatsThis, me->pos(), me->globalPos());
461 if (!QApplication::sendEvent(w, &e) || !e.isAccepted())
462 leaveOnMouseRelease = true;
463
464 } break;
465
466 case QEvent::MouseMove:
467 {
468 QMouseEvent *me = static_cast<QMouseEvent*>(e);
469 QHelpEvent e(QEvent::QueryWhatsThis, me->pos(), me->globalPos());
470 bool sentEvent = QApplication::sendEvent(w, &e);
471#ifdef QT_NO_CURSOR
472 Q_UNUSED(sentEvent);
473#else
474 QApplication::changeOverrideCursor((!sentEvent || !e.isAccepted())?
475 Qt::ForbiddenCursor:Qt::WhatsThisCursor);
476#endif
477 }
478 // fall through
479 case QEvent::MouseButtonRelease:
480 case QEvent::MouseButtonDblClick:
481 if (leaveOnMouseRelease && e->type() == QEvent::MouseButtonRelease)
482 QWhatsThis::leaveWhatsThisMode();
483 if (static_cast<QMouseEvent*>(e)->button() == Qt::RightButton || customWhatsThis)
484 return false; // ignore RMB release
485 break;
486 case QEvent::KeyPress:
487 {
488 QKeyEvent* kev = (QKeyEvent*)e;
489
490 if (kev->key() == Qt::Key_Escape) {
491 QWhatsThis::leaveWhatsThisMode();
492 return true;
493 } else if (customWhatsThis) {
494 return false;
495 } else if (kev->key() == Qt::Key_Menu ||
496 (kev->key() == Qt::Key_F10 &&
497 kev->modifiers() == Qt::ShiftModifier)) {
498 // we don't react to these keys, they are used for context menus
499 return false;
500 } else if (kev->key() != Qt::Key_Shift && kev->key() != Qt::Key_Alt // not a modifier key
501 && kev->key() != Qt::Key_Control && kev->key() != Qt::Key_Meta) {
502 QWhatsThis::leaveWhatsThisMode();
503 }
504 } break;
505 default:
506 return false;
507 }
508 return true;
509}
510
511class QWhatsThisAction: public QAction
512{
513 Q_OBJECT
514
515public:
516 explicit QWhatsThisAction(QObject* parent = 0);
517
518private slots:
519 void actionTriggered();
520};
521
522QWhatsThisAction::QWhatsThisAction(QObject *parent) : QAction(tr("What's This?"), parent)
523{
524#ifndef QT_NO_IMAGEFORMAT_XPM
525 QPixmap p((const char**)button_image);
526 setIcon(p);
527#endif
528 setCheckable(true);
529 connect(this, SIGNAL(triggered()), this, SLOT(actionTriggered()));
530#ifndef QT_NO_SHORTCUT
531 setShortcut(Qt::ShiftModifier + Qt::Key_F1);
532#endif
533}
534
535void QWhatsThisAction::actionTriggered()
536{
537 if (isChecked()) {
538 QWhatsThis::enterWhatsThisMode();
539 QWhatsThisPrivate::instance->action = this;
540 }
541}
542
543QWhatsThis::QWhatsThis()
544{
545}
546
547#ifdef QT3_SUPPORT
548/*!
549 \obsolete
550
551 Sets the What's This text \a s for the widget \a w.
552
553 Use QWidget::setWhatsThis() or QAction::setWhatsThis() instead.
554*/
555void QWhatsThis::add(QWidget *w, const QString &s)
556{
557 w->setWhatsThis(s);
558}
559
560/*!
561 \obsolete
562
563 Remove's the What's This text for the widget \a w.
564
565 Use QWidget::setWhatsThis() or QAction::setWhatsThis() instead.
566*/
567void QWhatsThis::remove(QWidget *w)
568{
569 w->setWhatsThis(QString());
570}
571
572class QWhatsThisButton : public QToolButton
573{
574 Q_OBJECT
575public:
576 QWhatsThisButton(QWidget *p) : QToolButton(p) {
577 setCheckable(true);
578 QPixmap pix( const_cast<const char**>(button_image) );
579 setIcon( pix );
580 QObject::connect(this, SIGNAL(toggled(bool)), this, SLOT(whatToggled(bool)));
581 setAutoRaise(true);
582 setFocusPolicy(Qt::NoFocus);
583 }
584
585public slots:
586 void whatToggled(bool b) {
587 if (b) {
588 QWhatsThis::enterWhatsThisMode();
589 QWhatsThisPrivate::instance->button = this;
590 }
591 }
592};
593
594/*!
595 Returns a new "What's This?" QToolButton with the given \a
596 parent. To do this now, create your own QToolButton and a
597 QWhatsThis object and call the QWhatsThis object's showText()
598 function when the QToolButton is invoked.
599
600 Use createAction() instead.
601*/
602QToolButton * QWhatsThis::whatsThisButton(QWidget * parent)
603{
604 return new QWhatsThisButton(parent);
605}
606#endif
607
608/*!
609 This function switches the user interface into "What's This?"
610 mode. The user interface can be switched back into normal mode by
611 the user (e.g. by them clicking or pressing Esc), or
612 programmatically by calling leaveWhatsThisMode().
613
614 When entering "What's This?" mode, a QEvent of type
615 Qt::EnterWhatsThisMode is sent to all toplevel widgets.
616
617 \sa inWhatsThisMode() leaveWhatsThisMode()
618*/
619void QWhatsThis::enterWhatsThisMode()
620{
621 if (QWhatsThisPrivate::instance)
622 return;
623 (void) new QWhatsThisPrivate;
624 QEvent e(QEvent::EnterWhatsThisMode);
625 QWhatsThisPrivate::notifyToplevels(&e);
626 }
627
628/*!
629 Returns true if the user interface is in "What's This?" mode;
630 otherwise returns false.
631
632 \sa enterWhatsThisMode()
633*/
634bool QWhatsThis::inWhatsThisMode()
635{
636 return (QWhatsThisPrivate::instance != 0);
637}
638
639/*!
640 If the user interface is in "What's This?" mode, this function
641 switches back to normal mode; otherwise it does nothing.
642
643 When leaving "What's This?" mode, a QEvent of type
644 Qt::LeaveWhatsThisMode is sent to all toplevel widgets.
645
646 \sa enterWhatsThisMode() inWhatsThisMode()
647*/
648void QWhatsThis::leaveWhatsThisMode()
649{
650 delete QWhatsThisPrivate::instance;
651 QEvent e(QEvent::LeaveWhatsThisMode);
652 QWhatsThisPrivate::notifyToplevels(&e);
653}
654
655void QWhatsThisPrivate::say(QWidget * widget, const QString &text, int x, int y)
656{
657 if (text.size() == 0)
658 return;
659 // make a fresh widget, and set it up
660 QWhatsThat *whatsThat = new QWhatsThat(
661 text,
662#if defined(Q_WS_X11) && !defined(QT_NO_CURSOR)
663 QApplication::desktop()->screen(widget ? widget->x11Info().screen() : QCursor::x11Screen()),
664#else
665 0,
666#endif
667 widget
668 );
669
670
671 // okay, now to find a suitable location
672
673 int scr = (widget ?
674 QApplication::desktop()->screenNumber(widget) :
675#if defined(Q_WS_X11) && !defined(QT_NO_CURSOR)
676 QCursor::x11Screen()
677#else
678 QApplication::desktop()->screenNumber(QPoint(x,y))
679#endif // Q_WS_X11
680 );
681 QRect screen = QApplication::desktop()->screenGeometry(scr);
682
683 int w = whatsThat->width();
684 int h = whatsThat->height();
685 int sx = screen.x();
686 int sy = screen.y();
687
688 // first try locating the widget immediately above/below,
689 // with nice alignment if possible.
690 QPoint pos;
691 if (widget)
692 pos = widget->mapToGlobal(QPoint(0,0));
693
694 if (widget && w > widget->width() + 16)
695 x = pos.x() + widget->width()/2 - w/2;
696 else
697 x = x - w/2;
698
699 // squeeze it in if that would result in part of what's this
700 // being only partially visible
701 if (x + w + shadowWidth > sx+screen.width())
702 x = (widget? (qMin(screen.width(),
703 pos.x() + widget->width())
704 ) : screen.width())
705 - w;
706
707 if (x < sx)
708 x = sx;
709
710 if (widget && h > widget->height() + 16) {
711 y = pos.y() + widget->height() + 2; // below, two pixels spacing
712 // what's this is above or below, wherever there's most space
713 if (y + h + 10 > sy+screen.height())
714 y = pos.y() + 2 - shadowWidth - h; // above, overlap
715 }
716 y = y + 2;
717
718 // squeeze it in if that would result in part of what's this
719 // being only partially visible
720 if (y + h + shadowWidth > sy+screen.height())
721 y = (widget ? (qMin(screen.height(),
722 pos.y() + widget->height())
723 ) : screen.height())
724 - h;
725 if (y < sy)
726 y = sy;
727
728 whatsThat->move(x, y);
729 whatsThat->show();
730 whatsThat->grabKeyboard();
731}
732
733/*!
734 Shows \a text as a "What's This?" window, at global position \a
735 pos. The optional widget argument, \a w, is used to determine the
736 appropriate screen on multi-head systems.
737
738 \sa hideText()
739*/
740void QWhatsThis::showText(const QPoint &pos, const QString &text, QWidget *w)
741{
742 leaveWhatsThisMode();
743 QWhatsThisPrivate::say(w, text, pos.x(), pos.y());
744}
745
746/*!
747 If a "What's This?" window is showing, this destroys it.
748
749 \sa showText()
750*/
751void QWhatsThis::hideText()
752{
753 qDeleteInEventHandler(QWhatsThat::instance);
754}
755
756/*!
757 Returns a ready-made QAction, used to invoke "What's This?" context
758 help, with the given \a parent.
759
760 The returned QAction provides a convenient way to let users enter
761 "What's This?" mode.
762*/
763QAction *QWhatsThis::createAction(QObject *parent)
764{
765 return new QWhatsThisAction(parent);
766}
767
768QT_END_NAMESPACE
769
770#include "qwhatsthis.moc"
771
772#endif // QT_NO_WHATSTHIS
Note: See TracBrowser for help on using the repository browser.