| 1 | /****************************************************************************
|
|---|
| 2 | ** $Id: qwhatsthis.cpp 2 2005-11-16 15:49:26Z dmik $
|
|---|
| 3 | **
|
|---|
| 4 | ** Implementation of QWhatsThis class
|
|---|
| 5 | **
|
|---|
| 6 | ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
|
|---|
| 7 | **
|
|---|
| 8 | ** This file is part of the widgets module of the Qt GUI Toolkit.
|
|---|
| 9 | **
|
|---|
| 10 | ** This file may be distributed under the terms of the Q Public License
|
|---|
| 11 | ** as defined by Trolltech AS of Norway and appearing in the file
|
|---|
| 12 | ** LICENSE.QPL included in the packaging of this file.
|
|---|
| 13 | **
|
|---|
| 14 | ** This file may be distributed and/or modified under the terms of the
|
|---|
| 15 | ** GNU General Public License version 2 as published by the Free Software
|
|---|
| 16 | ** Foundation and appearing in the file LICENSE.GPL included in the
|
|---|
| 17 | ** packaging of this file.
|
|---|
| 18 | **
|
|---|
| 19 | ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
|
|---|
| 20 | ** licenses may use this file in accordance with the Qt Commercial License
|
|---|
| 21 | ** Agreement provided with the Software.
|
|---|
| 22 | **
|
|---|
| 23 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
|---|
| 24 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|---|
| 25 | **
|
|---|
| 26 | ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
|
|---|
| 27 | ** information about Qt Commercial License Agreements.
|
|---|
| 28 | ** See http://www.trolltech.com/qpl/ for QPL licensing information.
|
|---|
| 29 | ** See http://www.trolltech.com/gpl/ for GPL licensing information.
|
|---|
| 30 | **
|
|---|
| 31 | ** Contact info@trolltech.com if any conditions of this licensing are
|
|---|
| 32 | ** not clear to you.
|
|---|
| 33 | **
|
|---|
| 34 | **********************************************************************/
|
|---|
| 35 |
|
|---|
| 36 | #include "qwhatsthis.h"
|
|---|
| 37 | #ifndef QT_NO_WHATSTHIS
|
|---|
| 38 | #include "qapplication.h"
|
|---|
| 39 | #include "qpaintdevicemetrics.h"
|
|---|
| 40 | #include "qpixmap.h"
|
|---|
| 41 | #include "qpainter.h"
|
|---|
| 42 | #include "qtimer.h"
|
|---|
| 43 | #include "qptrdict.h"
|
|---|
| 44 | #include "qtoolbutton.h"
|
|---|
| 45 | #include "qshared.h"
|
|---|
| 46 | #include "qcursor.h"
|
|---|
| 47 | #include "qbitmap.h"
|
|---|
| 48 | #include "qtooltip.h"
|
|---|
| 49 | #include "qsimplerichtext.h"
|
|---|
| 50 | #include "qstylesheet.h"
|
|---|
| 51 | #if defined(QT_ACCESSIBILITY_SUPPORT)
|
|---|
| 52 | #include "qaccessible.h"
|
|---|
| 53 | #endif
|
|---|
| 54 | #if defined(Q_WS_WIN)
|
|---|
| 55 | #include "qt_windows.h"
|
|---|
| 56 | #ifndef SPI_GETDROPSHADOW
|
|---|
| 57 | #define SPI_GETDROPSHADOW 0x1024
|
|---|
| 58 | #endif
|
|---|
| 59 | #endif
|
|---|
| 60 |
|
|---|
| 61 | /*!
|
|---|
| 62 | \class QWhatsThis qwhatsthis.h
|
|---|
| 63 | \brief The QWhatsThis class provides a simple description of any
|
|---|
| 64 | widget, i.e. answering the question "What's this?".
|
|---|
| 65 |
|
|---|
| 66 | \ingroup helpsystem
|
|---|
| 67 | \mainclass
|
|---|
| 68 |
|
|---|
| 69 | "What's this?" help is part of an application's online help system
|
|---|
| 70 | that provides users with information about functionality, usage,
|
|---|
| 71 | background etc., in various levels of detail from short tool tips
|
|---|
| 72 | to full text browsing help windows.
|
|---|
| 73 |
|
|---|
| 74 | QWhatsThis provides a single window with an explanatory text that
|
|---|
| 75 | pops up when the user asks "What's this?". The default way to do
|
|---|
| 76 | this is to focus the relevant widget and press Shift+F1. The help
|
|---|
| 77 | text appears immediately; it goes away as soon as the user does
|
|---|
| 78 | something else.
|
|---|
| 79 |
|
|---|
| 80 | (Note that if there is an accelerator for Shift+F1, this mechanism
|
|---|
| 81 | will not work.)
|
|---|
| 82 |
|
|---|
| 83 | To add "What's this?" text to a widget you simply call
|
|---|
| 84 | QWhatsThis::add() for the widget. For example, to assign text to a
|
|---|
| 85 | menu item, call QMenuData::setWhatsThis(); for a global
|
|---|
| 86 | accelerator key, call QAccel::setWhatsThis() and If you're using
|
|---|
| 87 | actions, use QAction::setWhatsThis().
|
|---|
| 88 |
|
|---|
| 89 | The text can be either rich text or plain text. If you specify a
|
|---|
| 90 | rich text formatted string, it will be rendered using the default
|
|---|
| 91 | stylesheet. This makes it possible to embed images. See
|
|---|
| 92 | QStyleSheet::defaultSheet() for details.
|
|---|
| 93 |
|
|---|
| 94 | \quotefile action/application.cpp
|
|---|
| 95 | \skipto fileOpenText
|
|---|
| 96 | \printuntil setWhatsThis
|
|---|
| 97 |
|
|---|
| 98 | An alternative way to enter "What's this?" mode is to use the
|
|---|
| 99 | ready-made tool bar tool button from
|
|---|
| 100 | QWhatsThis::whatsThisButton(). By invoking this context help
|
|---|
| 101 | button (in the picture below the first one from the right) the
|
|---|
| 102 | user switches into "What's this?" mode. If they now click on a
|
|---|
| 103 | widget the appropriate help text is shown. The mode is left when
|
|---|
| 104 | help is given or when the user presses Esc.
|
|---|
| 105 |
|
|---|
| 106 | \img whatsthis.png
|
|---|
| 107 |
|
|---|
| 108 | If you are using QMainWindow you can also use the
|
|---|
| 109 | QMainWindow::whatsThis() slot to invoke the mode from a menu item.
|
|---|
| 110 |
|
|---|
| 111 | For more control you can create a dedicated QWhatsThis object for
|
|---|
| 112 | a special widget. By subclassing and reimplementing
|
|---|
| 113 | QWhatsThis::text() it is possible to have different help texts,
|
|---|
| 114 | depending on the position of the mouse click. By reimplementing
|
|---|
| 115 | QWhatsThis::clicked() it is possible to have hyperlinks inside the
|
|---|
| 116 | help texts.
|
|---|
| 117 |
|
|---|
| 118 | If you wish to control the "What's this?" behavior of a widget
|
|---|
| 119 | manually see QWidget::customWhatsThis().
|
|---|
| 120 |
|
|---|
| 121 | The What's This object can be removed using QWhatsThis::remove(),
|
|---|
| 122 | although this is rarely necessary because it is automatically
|
|---|
| 123 | removed when the widget is destroyed.
|
|---|
| 124 |
|
|---|
| 125 | \sa QToolTip
|
|---|
| 126 | */
|
|---|
| 127 |
|
|---|
| 128 | // a special button
|
|---|
| 129 | class QWhatsThisButton: public QToolButton
|
|---|
| 130 | {
|
|---|
| 131 | Q_OBJECT
|
|---|
| 132 |
|
|---|
| 133 | public:
|
|---|
| 134 | QWhatsThisButton( QWidget * parent, const char * name );
|
|---|
| 135 | ~QWhatsThisButton();
|
|---|
| 136 |
|
|---|
| 137 | public slots:
|
|---|
| 138 | void mouseReleased();
|
|---|
| 139 |
|
|---|
| 140 | };
|
|---|
| 141 |
|
|---|
| 142 |
|
|---|
| 143 | class QWhatsThat : public QWidget
|
|---|
| 144 | {
|
|---|
| 145 | Q_OBJECT
|
|---|
| 146 | public:
|
|---|
| 147 | QWhatsThat( QWidget* w, const QString& txt, QWidget* parent, const char* name );
|
|---|
| 148 | ~QWhatsThat() ;
|
|---|
| 149 |
|
|---|
| 150 | public slots:
|
|---|
| 151 | void hide();
|
|---|
| 152 | inline void widgetDestroyed() { widget = 0; }
|
|---|
| 153 |
|
|---|
| 154 | protected:
|
|---|
| 155 | void mousePressEvent( QMouseEvent* );
|
|---|
| 156 | void mouseReleaseEvent( QMouseEvent* );
|
|---|
| 157 | void mouseMoveEvent( QMouseEvent* );
|
|---|
| 158 | void keyPressEvent( QKeyEvent* );
|
|---|
| 159 | void paintEvent( QPaintEvent* );
|
|---|
| 160 |
|
|---|
| 161 | private:
|
|---|
| 162 | QString text;
|
|---|
| 163 | #ifndef QT_NO_RICHTEXT
|
|---|
| 164 | QSimpleRichText* doc;
|
|---|
| 165 | #endif
|
|---|
| 166 | QString anchor;
|
|---|
| 167 | bool pressed;
|
|---|
| 168 | QWidget* widget;
|
|---|
| 169 | };
|
|---|
| 170 |
|
|---|
| 171 |
|
|---|
| 172 | class QWhatsThisPrivate: public QObject
|
|---|
| 173 | {
|
|---|
| 174 | Q_OBJECT
|
|---|
| 175 | public:
|
|---|
| 176 |
|
|---|
| 177 | // an item for storing texts
|
|---|
| 178 | struct WhatsThisItem: public QShared
|
|---|
| 179 | {
|
|---|
| 180 | WhatsThisItem(): QShared() { whatsthis = 0; }
|
|---|
| 181 | ~WhatsThisItem();
|
|---|
| 182 | QString s;
|
|---|
| 183 | QWhatsThis* whatsthis;
|
|---|
| 184 | };
|
|---|
| 185 |
|
|---|
| 186 | // the (these days pretty small) state machine
|
|---|
| 187 | enum State { Inactive, Waiting };
|
|---|
| 188 |
|
|---|
| 189 | QWhatsThisPrivate();
|
|---|
| 190 | ~QWhatsThisPrivate();
|
|---|
| 191 |
|
|---|
| 192 | bool eventFilter( QObject *, QEvent * );
|
|---|
| 193 |
|
|---|
| 194 | WhatsThisItem* newItem( QWidget * widget );
|
|---|
| 195 | void add( QWidget * widget, QWhatsThis* special );
|
|---|
| 196 | void add( QWidget * widget, const QString& text );
|
|---|
| 197 |
|
|---|
| 198 | // say it.
|
|---|
| 199 | void say( QWidget *, const QString&, const QPoint& );
|
|---|
| 200 |
|
|---|
| 201 | // setup and teardown
|
|---|
| 202 | static void setUpWhatsThis();
|
|---|
| 203 |
|
|---|
| 204 | void enterWhatsThisMode();
|
|---|
| 205 | void leaveWhatsThisMode();
|
|---|
| 206 |
|
|---|
| 207 | // variables
|
|---|
| 208 | QWhatsThat * whatsThat;
|
|---|
| 209 | QPtrDict<WhatsThisItem> * dict;
|
|---|
| 210 | QPtrDict<QWidget> * tlw;
|
|---|
| 211 | QPtrDict<QWhatsThisButton> * buttons;
|
|---|
| 212 | State state;
|
|---|
| 213 |
|
|---|
| 214 | private slots:
|
|---|
| 215 | void cleanupWidget()
|
|---|
| 216 | {
|
|---|
| 217 | const QObject* o = sender();
|
|---|
| 218 | if ( o->isWidgetType() ) // sanity
|
|---|
| 219 | QWhatsThis::remove((QWidget*)o);
|
|---|
| 220 | }
|
|---|
| 221 |
|
|---|
| 222 | };
|
|---|
| 223 |
|
|---|
| 224 | // static, but static the less-typing way
|
|---|
| 225 | static QWhatsThisPrivate * wt = 0;
|
|---|
| 226 |
|
|---|
| 227 | // shadowWidth not const, for XP drop-shadow-fu turns it to 0
|
|---|
| 228 | int shadowWidth = 6; // also used as '5' and '6' and even '8' below
|
|---|
| 229 | const int vMargin = 8;
|
|---|
| 230 | const int hMargin = 12;
|
|---|
| 231 |
|
|---|
| 232 | // Lets QPopupMenu destroy the QWhatsThat.
|
|---|
| 233 | void qWhatsThisBDH()
|
|---|
| 234 | {
|
|---|
| 235 | if ( wt && wt->whatsThat )
|
|---|
| 236 | wt->whatsThat->hide();
|
|---|
| 237 | }
|
|---|
| 238 |
|
|---|
| 239 |
|
|---|
| 240 | QWhatsThat::QWhatsThat( QWidget* w, const QString& txt, QWidget* parent, const char* name )
|
|---|
| 241 | : QWidget( parent, name, WType_Popup ), text( txt ), pressed( FALSE ), widget( w )
|
|---|
| 242 | {
|
|---|
| 243 |
|
|---|
| 244 | setBackgroundMode( NoBackground );
|
|---|
| 245 | setPalette( QToolTip::palette() );
|
|---|
| 246 | setMouseTracking( TRUE );
|
|---|
| 247 | #ifndef QT_NO_CURSOR
|
|---|
| 248 | setCursor( arrowCursor );
|
|---|
| 249 | #endif
|
|---|
| 250 |
|
|---|
| 251 | if ( widget )
|
|---|
| 252 | connect( widget, SIGNAL( destroyed() ), this, SLOT( widgetDestroyed() ) );
|
|---|
| 253 |
|
|---|
| 254 |
|
|---|
| 255 | QRect r;
|
|---|
| 256 | #ifndef QT_NO_RICHTEXT
|
|---|
| 257 | doc = 0;
|
|---|
| 258 | if ( QStyleSheet::mightBeRichText( text ) ) {
|
|---|
| 259 | QFont f = QApplication::font( this );
|
|---|
| 260 | doc = new QSimpleRichText( text, f );
|
|---|
| 261 | doc->adjustSize();
|
|---|
| 262 | r.setRect( 0, 0, doc->width(), doc->height() );
|
|---|
| 263 | }
|
|---|
| 264 | else
|
|---|
| 265 | #endif
|
|---|
| 266 | {
|
|---|
| 267 | int sw = QApplication::desktop()->width() / 3;
|
|---|
| 268 | if ( sw < 200 )
|
|---|
| 269 | sw = 200;
|
|---|
| 270 | else if ( sw > 300 )
|
|---|
| 271 | sw = 300;
|
|---|
| 272 |
|
|---|
| 273 | r = fontMetrics().boundingRect( 0, 0, sw, 1000,
|
|---|
| 274 | AlignAuto + AlignTop + WordBreak + ExpandTabs,
|
|---|
| 275 | text );
|
|---|
| 276 | }
|
|---|
| 277 | #if defined(Q_WS_WIN)
|
|---|
| 278 | if ( (qWinVersion()&WV_NT_based) > WV_2000 ) {
|
|---|
| 279 | BOOL shadow;
|
|---|
| 280 | SystemParametersInfo( SPI_GETDROPSHADOW, 0, &shadow, 0 );
|
|---|
| 281 | shadowWidth = shadow ? 0 : 6;
|
|---|
| 282 | }
|
|---|
| 283 | #endif
|
|---|
| 284 | resize( r.width() + 2*hMargin + shadowWidth, r.height() + 2*vMargin + shadowWidth );
|
|---|
| 285 | }
|
|---|
| 286 |
|
|---|
| 287 | QWhatsThat::~QWhatsThat()
|
|---|
| 288 | {
|
|---|
| 289 | if ( wt && wt->whatsThat == this )
|
|---|
| 290 | wt->whatsThat = 0;
|
|---|
| 291 | #ifndef QT_NO_RICHTEXT
|
|---|
| 292 | if ( doc )
|
|---|
| 293 | delete doc;
|
|---|
| 294 | #endif
|
|---|
| 295 | }
|
|---|
| 296 |
|
|---|
| 297 | void QWhatsThat::hide()
|
|---|
| 298 | {
|
|---|
| 299 | QWidget::hide();
|
|---|
| 300 | #if defined(QT_ACCESSIBILITY_SUPPORT)
|
|---|
| 301 | QAccessible::updateAccessibility( this, 0, QAccessible::ContextHelpEnd );
|
|---|
| 302 | #endif
|
|---|
| 303 | }
|
|---|
| 304 |
|
|---|
| 305 | void QWhatsThat::mousePressEvent( QMouseEvent* e )
|
|---|
| 306 | {
|
|---|
| 307 | pressed = TRUE;
|
|---|
| 308 | if ( e->button() == LeftButton && rect().contains( e->pos() ) ) {
|
|---|
| 309 | #ifndef QT_NO_RICHTEXT
|
|---|
| 310 | if ( doc )
|
|---|
| 311 | anchor = doc->anchorAt( e->pos() - QPoint( hMargin, vMargin) );
|
|---|
| 312 | #endif
|
|---|
| 313 | return;
|
|---|
| 314 | }
|
|---|
| 315 | hide();
|
|---|
| 316 | }
|
|---|
| 317 |
|
|---|
| 318 | void QWhatsThat::mouseReleaseEvent( QMouseEvent* e )
|
|---|
| 319 | {
|
|---|
| 320 | if ( !pressed )
|
|---|
| 321 | return;
|
|---|
| 322 | #ifndef QT_NO_RICHTEXT
|
|---|
| 323 | if ( e->button() == LeftButton && doc && rect().contains( e->pos() ) ) {
|
|---|
| 324 | QString a = doc->anchorAt( e->pos() - QPoint( hMargin, vMargin ) );
|
|---|
| 325 | QString href;
|
|---|
| 326 | if ( anchor == a )
|
|---|
| 327 | href = a;
|
|---|
| 328 | anchor = QString::null;
|
|---|
| 329 | if ( widget && wt && wt->dict ) {
|
|---|
| 330 | QWhatsThisPrivate::WhatsThisItem * i = wt->dict->find( widget );
|
|---|
| 331 | if ( i && i->whatsthis && !i->whatsthis->clicked( href ) )
|
|---|
| 332 | return;
|
|---|
| 333 | }
|
|---|
| 334 | }
|
|---|
| 335 | #endif
|
|---|
| 336 | hide();
|
|---|
| 337 | }
|
|---|
| 338 |
|
|---|
| 339 | void QWhatsThat::mouseMoveEvent( QMouseEvent* e)
|
|---|
| 340 | {
|
|---|
| 341 | #ifndef QT_NO_RICHTEXT
|
|---|
| 342 | #ifndef QT_NO_CURSOR
|
|---|
| 343 | if ( !doc )
|
|---|
| 344 | return;
|
|---|
| 345 | QString a = doc->anchorAt( e->pos() - QPoint( hMargin, vMargin ) );
|
|---|
| 346 | if ( !a.isEmpty() )
|
|---|
| 347 | setCursor( pointingHandCursor );
|
|---|
| 348 | else
|
|---|
| 349 | setCursor( arrowCursor );
|
|---|
| 350 | #endif
|
|---|
| 351 | #endif
|
|---|
| 352 | }
|
|---|
| 353 |
|
|---|
| 354 |
|
|---|
| 355 | void QWhatsThat::keyPressEvent( QKeyEvent* )
|
|---|
| 356 | {
|
|---|
| 357 | hide();
|
|---|
| 358 | }
|
|---|
| 359 |
|
|---|
| 360 |
|
|---|
| 361 |
|
|---|
| 362 | void QWhatsThat::paintEvent( QPaintEvent* )
|
|---|
| 363 | {
|
|---|
| 364 | bool drawShadow = TRUE;
|
|---|
| 365 | #if defined(Q_WS_WIN)
|
|---|
| 366 | if ( (qWinVersion()&WV_NT_based) > WV_2000 ) {
|
|---|
| 367 | BOOL shadow;
|
|---|
| 368 | SystemParametersInfo( SPI_GETDROPSHADOW, 0, &shadow, 0 );
|
|---|
| 369 | drawShadow = !shadow;
|
|---|
| 370 | }
|
|---|
| 371 | #elif defined(Q_WS_MACX)
|
|---|
| 372 | drawShadow = FALSE; //never draw it on OS X we get it for free
|
|---|
| 373 | #endif
|
|---|
| 374 |
|
|---|
| 375 | QRect r = rect();
|
|---|
| 376 | if ( drawShadow )
|
|---|
| 377 | r.addCoords( 0, 0, -shadowWidth, -shadowWidth );
|
|---|
| 378 | QPainter p( this);
|
|---|
| 379 | p.setPen( colorGroup().foreground() );
|
|---|
| 380 | p.drawRect( r );
|
|---|
| 381 | p.setPen( colorGroup().mid() );
|
|---|
| 382 | p.setBrush( colorGroup().brush( QColorGroup::Background ) );
|
|---|
| 383 | int w = r.width();
|
|---|
| 384 | int h = r.height();
|
|---|
| 385 | p.drawRect( 1, 1, w-2, h-2 );
|
|---|
| 386 | if ( drawShadow ) {
|
|---|
| 387 | p.setPen( colorGroup().shadow() );
|
|---|
| 388 | p.drawPoint( w + 5, 6 );
|
|---|
| 389 | p.drawLine( w + 3, 6, w + 5, 8 );
|
|---|
| 390 | p.drawLine( w + 1, 6, w + 5, 10 );
|
|---|
| 391 | int i;
|
|---|
| 392 | for( i=7; i < h; i += 2 )
|
|---|
| 393 | p.drawLine( w, i, w + 5, i + 5 );
|
|---|
| 394 | for( i = w - i + h; i > 6; i -= 2 )
|
|---|
| 395 | p.drawLine( i, h, i + 5, h + 5 );
|
|---|
| 396 | for( ; i > 0 ; i -= 2 )
|
|---|
| 397 | p.drawLine( 6, h + 6 - i, i + 5, h + 5 );
|
|---|
| 398 | }
|
|---|
| 399 | p.setPen( colorGroup().foreground() );
|
|---|
| 400 | r.addCoords( hMargin, vMargin, -hMargin, -vMargin );
|
|---|
| 401 |
|
|---|
| 402 | #ifndef QT_NO_RICHTEXT
|
|---|
| 403 | if ( doc ) {
|
|---|
| 404 | doc->draw( &p, r.x(), r.y(), r, colorGroup(), 0 );
|
|---|
| 405 | }
|
|---|
| 406 | else
|
|---|
| 407 | #endif
|
|---|
| 408 | {
|
|---|
| 409 | p.drawText( r, AlignAuto + AlignTop + WordBreak + ExpandTabs, text );
|
|---|
| 410 | }
|
|---|
| 411 | }
|
|---|
| 412 |
|
|---|
| 413 | // the item
|
|---|
| 414 | QWhatsThisPrivate::WhatsThisItem::~WhatsThisItem()
|
|---|
| 415 | {
|
|---|
| 416 | if ( count )
|
|---|
| 417 | qFatal( "QWhatsThis: Internal error (%d)", count );
|
|---|
| 418 | delete whatsthis;
|
|---|
| 419 | }
|
|---|
| 420 |
|
|---|
| 421 |
|
|---|
| 422 | static const char * const button_image[] = {
|
|---|
| 423 | "16 16 3 1",
|
|---|
| 424 | " c None",
|
|---|
| 425 | "o c #000000",
|
|---|
| 426 | "a c #000080",
|
|---|
| 427 | "o aaaaa ",
|
|---|
| 428 | "oo aaa aaa ",
|
|---|
| 429 | "ooo aaa aaa",
|
|---|
| 430 | "oooo aa aa",
|
|---|
| 431 | "ooooo aa aa",
|
|---|
| 432 | "oooooo a aaa",
|
|---|
| 433 | "ooooooo aaa ",
|
|---|
| 434 | "oooooooo aaa ",
|
|---|
| 435 | "ooooooooo aaa ",
|
|---|
| 436 | "ooooo aaa ",
|
|---|
| 437 | "oo ooo ",
|
|---|
| 438 | "o ooo aaa ",
|
|---|
| 439 | " ooo aaa ",
|
|---|
| 440 | " ooo ",
|
|---|
| 441 | " ooo ",
|
|---|
| 442 | " ooo "};
|
|---|
| 443 |
|
|---|
| 444 | // the button class
|
|---|
| 445 | QWhatsThisButton::QWhatsThisButton( QWidget * parent, const char * name )
|
|---|
| 446 | : QToolButton( parent, name )
|
|---|
| 447 | {
|
|---|
| 448 | QPixmap p( (const char**)button_image );
|
|---|
| 449 | setPixmap( p );
|
|---|
| 450 | setToggleButton( TRUE );
|
|---|
| 451 | setAutoRaise( TRUE );
|
|---|
| 452 | setFocusPolicy( NoFocus );
|
|---|
| 453 | setTextLabel( tr( "What's this?" ) );
|
|---|
| 454 | wt->buttons->insert( (void *)this, this );
|
|---|
| 455 | connect( this, SIGNAL( released() ),
|
|---|
| 456 | this, SLOT( mouseReleased() ) );
|
|---|
| 457 | }
|
|---|
| 458 |
|
|---|
| 459 |
|
|---|
| 460 | QWhatsThisButton::~QWhatsThisButton()
|
|---|
| 461 | {
|
|---|
| 462 | if ( wt && wt->buttons )
|
|---|
| 463 | wt->buttons->take( (void *)this );
|
|---|
| 464 | }
|
|---|
| 465 |
|
|---|
| 466 |
|
|---|
| 467 | void QWhatsThisButton::mouseReleased()
|
|---|
| 468 | {
|
|---|
| 469 | if ( wt->state == QWhatsThisPrivate::Inactive && isOn() ) {
|
|---|
| 470 | QWhatsThisPrivate::setUpWhatsThis();
|
|---|
| 471 | #ifndef QT_NO_CURSOR
|
|---|
| 472 | QApplication::setOverrideCursor( whatsThisCursor, FALSE );
|
|---|
| 473 | #endif
|
|---|
| 474 | wt->state = QWhatsThisPrivate::Waiting;
|
|---|
| 475 | qApp->installEventFilter( wt );
|
|---|
| 476 | }
|
|---|
| 477 | }
|
|---|
| 478 |
|
|---|
| 479 | static void qWhatsThisPrivateCleanup()
|
|---|
| 480 | {
|
|---|
| 481 | if( wt ) {
|
|---|
| 482 | delete wt;
|
|---|
| 483 | wt = 0;
|
|---|
| 484 | }
|
|---|
| 485 | }
|
|---|
| 486 |
|
|---|
| 487 | // the what's this manager class
|
|---|
| 488 | QWhatsThisPrivate::QWhatsThisPrivate()
|
|---|
| 489 | : QObject( 0, "global what's this object" )
|
|---|
| 490 | {
|
|---|
| 491 | whatsThat = 0;
|
|---|
| 492 | dict = new QPtrDict<QWhatsThisPrivate::WhatsThisItem>;
|
|---|
| 493 | tlw = new QPtrDict<QWidget>;
|
|---|
| 494 | wt = this;
|
|---|
| 495 | buttons = new QPtrDict<QWhatsThisButton>;
|
|---|
| 496 | state = Inactive;
|
|---|
| 497 | }
|
|---|
| 498 |
|
|---|
| 499 | QWhatsThisPrivate::~QWhatsThisPrivate()
|
|---|
| 500 | {
|
|---|
| 501 | #ifndef QT_NO_CURSOR
|
|---|
| 502 | if ( state == Waiting && qApp )
|
|---|
| 503 | QApplication::restoreOverrideCursor();
|
|---|
| 504 | #endif
|
|---|
| 505 | // the two straight-and-simple dicts
|
|---|
| 506 | delete tlw;
|
|---|
| 507 | delete buttons;
|
|---|
| 508 |
|
|---|
| 509 | // then delete the complex one.
|
|---|
| 510 | QPtrDictIterator<WhatsThisItem> it( *dict );
|
|---|
| 511 | WhatsThisItem * i;
|
|---|
| 512 | QWidget * w;
|
|---|
| 513 | while( (i=it.current()) != 0 ) {
|
|---|
| 514 | w = (QWidget *)it.currentKey();
|
|---|
| 515 | ++it;
|
|---|
| 516 | dict->take( w );
|
|---|
| 517 | if ( i->deref() )
|
|---|
| 518 | delete i;
|
|---|
| 519 | }
|
|---|
| 520 | delete dict;
|
|---|
| 521 | if ( whatsThat && !whatsThat->parentWidget() ) {
|
|---|
| 522 | delete whatsThat;
|
|---|
| 523 | }
|
|---|
| 524 | // and finally lose wt
|
|---|
| 525 | wt = 0;
|
|---|
| 526 | }
|
|---|
| 527 |
|
|---|
| 528 | bool QWhatsThisPrivate::eventFilter( QObject * o, QEvent * e )
|
|---|
| 529 | {
|
|---|
| 530 | switch( state ) {
|
|---|
| 531 | case Waiting:
|
|---|
| 532 | if ( e->type() == QEvent::MouseButtonPress && o->isWidgetType() ) {
|
|---|
| 533 | QWidget * w = (QWidget *) o;
|
|---|
| 534 | if ( ( (QMouseEvent*)e)->button() == RightButton )
|
|---|
| 535 | return FALSE; // ignore RMB
|
|---|
| 536 | if ( w->customWhatsThis() )
|
|---|
| 537 | return FALSE;
|
|---|
| 538 | QWhatsThisPrivate::WhatsThisItem * i = 0;
|
|---|
| 539 | QMouseEvent* me = (QMouseEvent*) e;
|
|---|
| 540 | QPoint p = me->pos();
|
|---|
| 541 | while( w && !i ) {
|
|---|
| 542 | i = dict->find( w );
|
|---|
| 543 | if ( !i ) {
|
|---|
| 544 | p += w->pos();
|
|---|
| 545 | w = w->parentWidget( TRUE );
|
|---|
| 546 | }
|
|---|
| 547 | }
|
|---|
| 548 | leaveWhatsThisMode();
|
|---|
| 549 | if (!i ) {
|
|---|
| 550 | #if defined(QT_ACCESSIBILITY_SUPPORT)
|
|---|
| 551 | QAccessible::updateAccessibility( this, 0, QAccessible::ContextHelpEnd );
|
|---|
| 552 | #endif
|
|---|
| 553 | return TRUE;
|
|---|
| 554 | }
|
|---|
| 555 | if ( i->whatsthis )
|
|---|
| 556 | say( w, i->whatsthis->text( p ), me->globalPos() );
|
|---|
| 557 | else
|
|---|
| 558 | say( w, i->s, me->globalPos() );
|
|---|
| 559 | return TRUE;
|
|---|
| 560 | } else if ( e->type() == QEvent::MouseButtonRelease ) {
|
|---|
| 561 | if ( ( (QMouseEvent*)e)->button() == RightButton )
|
|---|
| 562 | return FALSE; // ignore RMB
|
|---|
| 563 | return !o->isWidgetType() || !((QWidget*)o)->customWhatsThis();
|
|---|
| 564 | } else if ( e->type() == QEvent::MouseMove ) {
|
|---|
| 565 | return !o->isWidgetType() || !((QWidget*)o)->customWhatsThis();
|
|---|
| 566 | } else if ( e->type() == QEvent::KeyPress ) {
|
|---|
| 567 | QKeyEvent* kev = (QKeyEvent*)e;
|
|---|
| 568 |
|
|---|
| 569 | if ( kev->key() == Qt::Key_Escape ) {
|
|---|
| 570 | leaveWhatsThisMode();
|
|---|
| 571 | return TRUE;
|
|---|
| 572 | } else if ( o->isWidgetType() && ((QWidget*)o)->customWhatsThis() ) {
|
|---|
| 573 | return FALSE;
|
|---|
| 574 | } else if ( kev->key() == Key_Menu ||
|
|---|
| 575 | ( kev->key() == Key_F10 &&
|
|---|
| 576 | kev->state() == ShiftButton ) ) {
|
|---|
| 577 | // we don't react to these keys, they are used for context menus
|
|---|
| 578 | return FALSE;
|
|---|
| 579 | } else if ( kev->state() == kev->stateAfter() &&
|
|---|
| 580 | kev->key() != Key_Meta ) { // not a modifier key
|
|---|
| 581 | leaveWhatsThisMode();
|
|---|
| 582 | }
|
|---|
| 583 | } else if ( e->type() == QEvent::MouseButtonDblClick ) {
|
|---|
| 584 | return TRUE;
|
|---|
| 585 | }
|
|---|
| 586 | break;
|
|---|
| 587 | case Inactive:
|
|---|
| 588 | if ( e->type() == QEvent::Accel &&
|
|---|
| 589 | ((QKeyEvent *)e)->key() == Key_F1 &&
|
|---|
| 590 | o->isWidgetType() &&
|
|---|
| 591 | ((QKeyEvent *)e)->state() == ShiftButton ) {
|
|---|
| 592 | QWidget * w = ((QWidget *)o)->focusWidget();
|
|---|
| 593 | if ( !w )
|
|---|
| 594 | break;
|
|---|
| 595 | QString s = QWhatsThis::textFor( w, QPoint(0,0), TRUE );
|
|---|
| 596 | if ( !s.isNull() ) {
|
|---|
| 597 | say ( w, s, w->mapToGlobal( w->rect().center() ) );
|
|---|
| 598 | ((QKeyEvent *)e)->accept();
|
|---|
| 599 | return TRUE;
|
|---|
| 600 | }
|
|---|
| 601 | }
|
|---|
| 602 | break;
|
|---|
| 603 | }
|
|---|
| 604 | return FALSE;
|
|---|
| 605 | }
|
|---|
| 606 |
|
|---|
| 607 |
|
|---|
| 608 |
|
|---|
| 609 | void QWhatsThisPrivate::setUpWhatsThis()
|
|---|
| 610 | {
|
|---|
| 611 | if ( !wt ) {
|
|---|
| 612 | wt = new QWhatsThisPrivate();
|
|---|
| 613 |
|
|---|
| 614 | // It is necessary to use a post routine, because
|
|---|
| 615 | // the destructor deletes pixmaps and other stuff that
|
|---|
| 616 | // needs a working X connection under X11.
|
|---|
| 617 | qAddPostRoutine( qWhatsThisPrivateCleanup );
|
|---|
| 618 | }
|
|---|
| 619 | }
|
|---|
| 620 |
|
|---|
| 621 |
|
|---|
| 622 | void QWhatsThisPrivate::enterWhatsThisMode()
|
|---|
| 623 | {
|
|---|
| 624 | #if defined(QT_ACCESSIBILITY_SUPPORT)
|
|---|
| 625 | QAccessible::updateAccessibility( this, 0, QAccessible::ContextHelpStart );
|
|---|
| 626 | #endif
|
|---|
| 627 | }
|
|---|
| 628 |
|
|---|
| 629 |
|
|---|
| 630 | void QWhatsThisPrivate::leaveWhatsThisMode()
|
|---|
| 631 | {
|
|---|
| 632 | if ( state == Waiting ) {
|
|---|
| 633 | QPtrDictIterator<QWhatsThisButton> it( *(wt->buttons) );
|
|---|
| 634 | QWhatsThisButton * b;
|
|---|
| 635 | while( (b=it.current()) != 0 ) {
|
|---|
| 636 | ++it;
|
|---|
| 637 | b->setOn( FALSE );
|
|---|
| 638 | }
|
|---|
| 639 | #ifndef QT_NO_CURSOR
|
|---|
| 640 | QApplication::restoreOverrideCursor();
|
|---|
| 641 | #endif
|
|---|
| 642 | state = Inactive;
|
|---|
| 643 | qApp->removeEventFilter( this );
|
|---|
| 644 | }
|
|---|
| 645 | }
|
|---|
| 646 |
|
|---|
| 647 |
|
|---|
| 648 |
|
|---|
| 649 | void QWhatsThisPrivate::say( QWidget * widget, const QString &text, const QPoint& ppos)
|
|---|
| 650 | {
|
|---|
| 651 | if ( text.isEmpty() )
|
|---|
| 652 | return;
|
|---|
| 653 | // make a fresh widget, and set it up
|
|---|
| 654 | delete whatsThat;
|
|---|
| 655 | whatsThat = new QWhatsThat(
|
|---|
| 656 | widget, text,
|
|---|
| 657 | #if defined(Q_WS_X11)
|
|---|
| 658 | QApplication::desktop()->screen( widget ?
|
|---|
| 659 | widget->x11Screen() :
|
|---|
| 660 | QCursor::x11Screen() ),
|
|---|
| 661 | #else
|
|---|
| 662 | 0,
|
|---|
| 663 | #endif
|
|---|
| 664 | "automatic what's this? widget" );
|
|---|
| 665 |
|
|---|
| 666 |
|
|---|
| 667 | // okay, now to find a suitable location
|
|---|
| 668 |
|
|---|
| 669 | int scr = ( widget ?
|
|---|
| 670 | QApplication::desktop()->screenNumber( widget ) :
|
|---|
| 671 | #if defined(Q_WS_X11)
|
|---|
| 672 | QCursor::x11Screen()
|
|---|
| 673 | #else
|
|---|
| 674 | QApplication::desktop()->screenNumber( ppos )
|
|---|
| 675 | #endif // Q_WS_X11
|
|---|
| 676 | );
|
|---|
| 677 | QRect screen = QApplication::desktop()->screenGeometry( scr );
|
|---|
| 678 |
|
|---|
| 679 | int x;
|
|---|
| 680 | int w = whatsThat->width();
|
|---|
| 681 | int h = whatsThat->height();
|
|---|
| 682 | int sx = screen.x();
|
|---|
| 683 | int sy = screen.y();
|
|---|
| 684 |
|
|---|
| 685 | // first try locating the widget immediately above/below,
|
|---|
| 686 | // with nice alignment if possible.
|
|---|
| 687 | QPoint pos;
|
|---|
| 688 | if ( widget )
|
|---|
| 689 | pos = widget->mapToGlobal( QPoint( 0,0 ) );
|
|---|
| 690 |
|
|---|
| 691 | if ( widget && w > widget->width() + 16 )
|
|---|
| 692 | x = pos.x() + widget->width()/2 - w/2;
|
|---|
| 693 | else
|
|---|
| 694 | x = ppos.x() - w/2;
|
|---|
| 695 |
|
|---|
| 696 | // squeeze it in if that would result in part of what's this
|
|---|
| 697 | // being only partially visible
|
|---|
| 698 | if ( x + w + shadowWidth > sx+screen.width() )
|
|---|
| 699 | x = (widget? (QMIN(screen.width(),
|
|---|
| 700 | pos.x() + widget->width())
|
|---|
| 701 | ) : screen.width() )
|
|---|
| 702 | - w;
|
|---|
| 703 |
|
|---|
| 704 | if ( x < sx )
|
|---|
| 705 | x = sx;
|
|---|
| 706 |
|
|---|
| 707 | int y;
|
|---|
| 708 | if ( widget && h > widget->height() + 16 ) {
|
|---|
| 709 | y = pos.y() + widget->height() + 2; // below, two pixels spacing
|
|---|
| 710 | // what's this is above or below, wherever there's most space
|
|---|
| 711 | if ( y + h + 10 > sy+screen.height() )
|
|---|
| 712 | y = pos.y() + 2 - shadowWidth - h; // above, overlap
|
|---|
| 713 | }
|
|---|
| 714 | y = ppos.y() + 2;
|
|---|
| 715 |
|
|---|
| 716 | // squeeze it in if that would result in part of what's this
|
|---|
| 717 | // being only partially visible
|
|---|
| 718 | if ( y + h + shadowWidth > sy+screen.height() )
|
|---|
| 719 | y = ( widget ? (QMIN(screen.height(),
|
|---|
| 720 | pos.y() + widget->height())
|
|---|
| 721 | ) : screen.height() )
|
|---|
| 722 | - h;
|
|---|
| 723 | if ( y < sy )
|
|---|
| 724 | y = sy;
|
|---|
| 725 |
|
|---|
| 726 | whatsThat->move( x, y );
|
|---|
| 727 | whatsThat->show();
|
|---|
| 728 | }
|
|---|
| 729 |
|
|---|
| 730 | QWhatsThisPrivate::WhatsThisItem* QWhatsThisPrivate::newItem( QWidget * widget )
|
|---|
| 731 | {
|
|---|
| 732 | WhatsThisItem * i = dict->find( (void *)widget );
|
|---|
| 733 | if ( i )
|
|---|
| 734 | QWhatsThis::remove( widget );
|
|---|
| 735 | i = new WhatsThisItem;
|
|---|
| 736 | dict->insert( (void *)widget, i );
|
|---|
| 737 | QWidget * t = widget->topLevelWidget();
|
|---|
| 738 | if ( !tlw->find( (void *)t ) ) {
|
|---|
| 739 | tlw->insert( (void *)t, t );
|
|---|
| 740 | t->installEventFilter( this );
|
|---|
| 741 | }
|
|---|
| 742 | connect( widget, SIGNAL(destroyed()), this, SLOT(cleanupWidget()) );
|
|---|
| 743 | return i;
|
|---|
| 744 | }
|
|---|
| 745 |
|
|---|
| 746 | void QWhatsThisPrivate::add( QWidget * widget, QWhatsThis* special )
|
|---|
| 747 | {
|
|---|
| 748 | newItem( widget )->whatsthis = special;
|
|---|
| 749 | }
|
|---|
| 750 |
|
|---|
| 751 | void QWhatsThisPrivate::add( QWidget * widget, const QString &text )
|
|---|
| 752 | {
|
|---|
| 753 | newItem( widget )->s = text;
|
|---|
| 754 | }
|
|---|
| 755 |
|
|---|
| 756 |
|
|---|
| 757 | // and finally the What's This class itself
|
|---|
| 758 |
|
|---|
| 759 | /*!
|
|---|
| 760 | Adds \a text as "What's this" help for \a widget. If the text is
|
|---|
| 761 | rich text formatted (i.e. it contains markup) it will be rendered
|
|---|
| 762 | with the default stylesheet QStyleSheet::defaultSheet().
|
|---|
| 763 |
|
|---|
| 764 | The text is destroyed if the widget is later destroyed, so it need
|
|---|
| 765 | not be explicitly removed.
|
|---|
| 766 |
|
|---|
| 767 | \sa remove()
|
|---|
| 768 | */
|
|---|
| 769 | void QWhatsThis::add( QWidget * widget, const QString &text )
|
|---|
| 770 | {
|
|---|
| 771 | if ( text.isEmpty() )
|
|---|
| 772 | return; // pointless
|
|---|
| 773 | QWhatsThisPrivate::setUpWhatsThis();
|
|---|
| 774 | wt->add(widget,text);
|
|---|
| 775 | }
|
|---|
| 776 |
|
|---|
| 777 |
|
|---|
| 778 | /*!
|
|---|
| 779 | Removes the "What's this?" help associated with the \a widget.
|
|---|
| 780 | This happens automatically if the widget is destroyed.
|
|---|
| 781 |
|
|---|
| 782 | \sa add()
|
|---|
| 783 | */
|
|---|
| 784 | void QWhatsThis::remove( QWidget * widget )
|
|---|
| 785 | {
|
|---|
| 786 | QWhatsThisPrivate::setUpWhatsThis();
|
|---|
| 787 | QWhatsThisPrivate::WhatsThisItem * i = wt->dict->find( (void *)widget );
|
|---|
| 788 | if ( !i )
|
|---|
| 789 | return;
|
|---|
| 790 |
|
|---|
| 791 | wt->dict->take( (void *)widget );
|
|---|
| 792 |
|
|---|
| 793 | i->deref();
|
|---|
| 794 | if ( !i->count )
|
|---|
| 795 | delete i;
|
|---|
| 796 | }
|
|---|
| 797 |
|
|---|
| 798 |
|
|---|
| 799 | /*!
|
|---|
| 800 | Returns the what's this text for widget \a w or QString::null if
|
|---|
| 801 | there is no "What's this?" help for the widget. \a pos contains
|
|---|
| 802 | the mouse position; this is useful, for example, if you've
|
|---|
| 803 | subclassed to make the text that is displayed position dependent.
|
|---|
| 804 |
|
|---|
| 805 | If \a includeParents is TRUE, parent widgets are taken into
|
|---|
| 806 | consideration as well when looking for what's this help text.
|
|---|
| 807 |
|
|---|
| 808 | \sa add()
|
|---|
| 809 | */
|
|---|
| 810 | QString QWhatsThis::textFor( QWidget * w, const QPoint& pos, bool includeParents )
|
|---|
| 811 | {
|
|---|
| 812 | QWhatsThisPrivate::setUpWhatsThis();
|
|---|
| 813 | QWhatsThisPrivate::WhatsThisItem * i = 0;
|
|---|
| 814 | QPoint p = pos;
|
|---|
| 815 | while( w && !i ) {
|
|---|
| 816 | i = wt->dict->find( w );
|
|---|
| 817 | if ( !includeParents )
|
|---|
| 818 | break;
|
|---|
| 819 | if ( !i ) {
|
|---|
| 820 | p += w->pos();
|
|---|
| 821 | w = w->parentWidget( TRUE );
|
|---|
| 822 | }
|
|---|
| 823 | }
|
|---|
| 824 | if (!i)
|
|---|
| 825 | return QString::null;
|
|---|
| 826 | if ( i->whatsthis )
|
|---|
| 827 | return i->whatsthis->text( p );
|
|---|
| 828 | return i->s;
|
|---|
| 829 | }
|
|---|
| 830 |
|
|---|
| 831 |
|
|---|
| 832 | /*!
|
|---|
| 833 | Creates a QToolButton preconfigured to enter "What's this?" mode
|
|---|
| 834 | when clicked. You will often use this with a tool bar as \a
|
|---|
| 835 | parent:
|
|---|
| 836 | \code
|
|---|
| 837 | (void) QWhatsThis::whatsThisButton( my_help_tool_bar );
|
|---|
| 838 | \endcode
|
|---|
| 839 | */
|
|---|
| 840 | QToolButton * QWhatsThis::whatsThisButton( QWidget * parent )
|
|---|
| 841 | {
|
|---|
| 842 | QWhatsThisPrivate::setUpWhatsThis();
|
|---|
| 843 | return new QWhatsThisButton( parent,
|
|---|
| 844 | "automatic what's this? button" );
|
|---|
| 845 | }
|
|---|
| 846 |
|
|---|
| 847 | /*!
|
|---|
| 848 | Constructs a dynamic "What's this?" object for \a widget. The
|
|---|
| 849 | object is deleted when the \a widget is destroyed.
|
|---|
| 850 |
|
|---|
| 851 | When the widget is queried by the user the text() function of this
|
|---|
| 852 | QWhatsThis will be called to provide the appropriate text, rather
|
|---|
| 853 | than using the text assigned by add().
|
|---|
| 854 | */
|
|---|
| 855 | QWhatsThis::QWhatsThis( QWidget * widget)
|
|---|
| 856 | {
|
|---|
| 857 | QWhatsThisPrivate::setUpWhatsThis();
|
|---|
| 858 | wt->add(widget,this);
|
|---|
| 859 | }
|
|---|
| 860 |
|
|---|
| 861 |
|
|---|
| 862 | /*!
|
|---|
| 863 | Destroys the object and frees any allocated resources.
|
|---|
| 864 | */
|
|---|
| 865 | QWhatsThis::~QWhatsThis()
|
|---|
| 866 | {
|
|---|
| 867 | }
|
|---|
| 868 |
|
|---|
| 869 |
|
|---|
| 870 | /*!
|
|---|
| 871 | This virtual function returns the text for position \e p in the
|
|---|
| 872 | widget that this "What's this?" object documents. If there is no
|
|---|
| 873 | "What's this?" text for the position, QString::null is returned.
|
|---|
| 874 |
|
|---|
| 875 | The default implementation returns QString::null.
|
|---|
| 876 | */
|
|---|
| 877 | QString QWhatsThis::text( const QPoint & )
|
|---|
| 878 | {
|
|---|
| 879 | return QString::null;
|
|---|
| 880 | }
|
|---|
| 881 |
|
|---|
| 882 | /*!
|
|---|
| 883 | \fn bool QWhatsThis::clicked( const QString& href )
|
|---|
| 884 |
|
|---|
| 885 | This virtual function is called when the user clicks inside the
|
|---|
| 886 | "What's this?" window. \a href is the link the user clicked on, or
|
|---|
| 887 | QString::null if there was no link.
|
|---|
| 888 |
|
|---|
| 889 | If the function returns TRUE (the default), the "What's this?"
|
|---|
| 890 | window is closed, otherwise it remains visible.
|
|---|
| 891 |
|
|---|
| 892 | The default implementation ignores \a href and returns TRUE.
|
|---|
| 893 | */
|
|---|
| 894 | bool QWhatsThis::clicked( const QString& )
|
|---|
| 895 | {
|
|---|
| 896 | return TRUE;
|
|---|
| 897 | }
|
|---|
| 898 |
|
|---|
| 899 |
|
|---|
| 900 | /*!
|
|---|
| 901 | Enters "What's this?" mode and returns immediately.
|
|---|
| 902 |
|
|---|
| 903 | Qt will install a special cursor and take over mouse input until
|
|---|
| 904 | the user clicks somewhere. It then shows any help available and
|
|---|
| 905 | ends "What's this?" mode. Finally, Qt removes the special cursor
|
|---|
| 906 | and help window and then restores ordinary event processing, at
|
|---|
| 907 | which point the left mouse button is no longer pressed.
|
|---|
| 908 |
|
|---|
| 909 | The user can also use the Esc key to leave "What's this?" mode.
|
|---|
| 910 |
|
|---|
| 911 | \sa inWhatsThisMode(), leaveWhatsThisMode()
|
|---|
| 912 | */
|
|---|
| 913 |
|
|---|
| 914 | void QWhatsThis::enterWhatsThisMode()
|
|---|
| 915 | {
|
|---|
| 916 | QWhatsThisPrivate::setUpWhatsThis();
|
|---|
| 917 | if ( wt->state == QWhatsThisPrivate::Inactive ) {
|
|---|
| 918 | wt->enterWhatsThisMode();
|
|---|
| 919 | #ifndef QT_NO_CURSOR
|
|---|
| 920 | QApplication::setOverrideCursor( whatsThisCursor, FALSE );
|
|---|
| 921 | #endif
|
|---|
| 922 | wt->state = QWhatsThisPrivate::Waiting;
|
|---|
| 923 | qApp->installEventFilter( wt );
|
|---|
| 924 | }
|
|---|
| 925 | }
|
|---|
| 926 |
|
|---|
| 927 |
|
|---|
| 928 | /*!
|
|---|
| 929 | Returns TRUE if the application is in "What's this?" mode;
|
|---|
| 930 | otherwise returns FALSE.
|
|---|
| 931 |
|
|---|
| 932 | \sa enterWhatsThisMode(), leaveWhatsThisMode()
|
|---|
| 933 | */
|
|---|
| 934 | bool QWhatsThis::inWhatsThisMode()
|
|---|
| 935 | {
|
|---|
| 936 | if (!wt)
|
|---|
| 937 | return FALSE;
|
|---|
| 938 | return wt->state == QWhatsThisPrivate::Waiting;
|
|---|
| 939 | }
|
|---|
| 940 |
|
|---|
| 941 |
|
|---|
| 942 | /*!
|
|---|
| 943 | Leaves "What's this?" question mode.
|
|---|
| 944 |
|
|---|
| 945 | This function is used internally by widgets that support
|
|---|
| 946 | QWidget::customWhatsThis(); applications do not usually call it.
|
|---|
| 947 | An example of such a widget is QPopupMenu: menus still work
|
|---|
| 948 | normally in "What's this?" mode but also provide help texts for
|
|---|
| 949 | individual menu items.
|
|---|
| 950 |
|
|---|
| 951 | If \a text is not QString::null, a "What's this?" help window is
|
|---|
| 952 | displayed at the global screen position \a pos. If widget \a w is
|
|---|
| 953 | not 0 and has its own dedicated QWhatsThis object, this object
|
|---|
| 954 | will receive clicked() messages when the user clicks on hyperlinks
|
|---|
| 955 | inside the help text.
|
|---|
| 956 |
|
|---|
| 957 | \sa inWhatsThisMode(), enterWhatsThisMode(), QWhatsThis::clicked()
|
|---|
| 958 | */
|
|---|
| 959 | void QWhatsThis::leaveWhatsThisMode( const QString& text, const QPoint& pos, QWidget* w )
|
|---|
| 960 | {
|
|---|
| 961 | if ( !inWhatsThisMode() )
|
|---|
| 962 | return;
|
|---|
| 963 |
|
|---|
| 964 | wt->leaveWhatsThisMode();
|
|---|
| 965 | if ( !text.isNull() )
|
|---|
| 966 | wt->say( w, text, pos );
|
|---|
| 967 | }
|
|---|
| 968 |
|
|---|
| 969 | /*!
|
|---|
| 970 | Display \a text in a help window at the global screen position \a
|
|---|
| 971 | pos.
|
|---|
| 972 |
|
|---|
| 973 | If widget \a w is not 0 and has its own dedicated QWhatsThis
|
|---|
| 974 | object, this object will receive clicked() messages when the user
|
|---|
| 975 | clicks on hyperlinks inside the help text.
|
|---|
| 976 |
|
|---|
| 977 | \sa QWhatsThis::clicked()
|
|---|
| 978 | */
|
|---|
| 979 | void QWhatsThis::display( const QString& text, const QPoint& pos, QWidget* w )
|
|---|
| 980 | {
|
|---|
| 981 | if ( inWhatsThisMode() ) {
|
|---|
| 982 | leaveWhatsThisMode( text, pos, w );
|
|---|
| 983 | return;
|
|---|
| 984 | }
|
|---|
| 985 | QWhatsThisPrivate::setUpWhatsThis();
|
|---|
| 986 | wt->say( w, text, pos );
|
|---|
| 987 | }
|
|---|
| 988 |
|
|---|
| 989 | /*!
|
|---|
| 990 | Sets the font for all "What's this?" helps to \a font.
|
|---|
| 991 | */
|
|---|
| 992 | void QWhatsThis::setFont( const QFont &font )
|
|---|
| 993 | {
|
|---|
| 994 | QApplication::setFont( font, TRUE, "QWhatsThat" );
|
|---|
| 995 | }
|
|---|
| 996 |
|
|---|
| 997 | #include "qwhatsthis.moc"
|
|---|
| 998 | #endif
|
|---|