[2] | 1 | /****************************************************************************
|
---|
| 2 | ** $Id: qiconset.cpp 8 2005-11-16 19:36:46Z dmik $
|
---|
| 3 | **
|
---|
| 4 | ** Implementation of QIconSet class
|
---|
| 5 | **
|
---|
| 6 | ** Created : 980318
|
---|
| 7 | **
|
---|
| 8 | ** Copyright (C) 1992-2002 Trolltech AS. All rights reserved.
|
---|
| 9 | **
|
---|
| 10 | ** This file is part of the kernel module of the Qt GUI Toolkit.
|
---|
| 11 | **
|
---|
| 12 | ** This file may be distributed under the terms of the Q Public License
|
---|
| 13 | ** as defined by Trolltech AS of Norway and appearing in the file
|
---|
| 14 | ** LICENSE.QPL included in the packaging of this file.
|
---|
| 15 | **
|
---|
| 16 | ** This file may be distributed and/or modified under the terms of the
|
---|
| 17 | ** GNU General Public License version 2 as published by the Free Software
|
---|
| 18 | ** Foundation and appearing in the file LICENSE.GPL included in the
|
---|
| 19 | ** packaging of this file.
|
---|
| 20 | **
|
---|
| 21 | ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
|
---|
| 22 | ** licenses may use this file in accordance with the Qt Commercial License
|
---|
| 23 | ** Agreement provided with the Software.
|
---|
| 24 | **
|
---|
| 25 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
---|
| 26 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
---|
| 27 | **
|
---|
| 28 | ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
|
---|
| 29 | ** information about Qt Commercial License Agreements.
|
---|
| 30 | ** See http://www.trolltech.com/qpl/ for QPL licensing information.
|
---|
| 31 | ** See http://www.trolltech.com/gpl/ for GPL licensing information.
|
---|
| 32 | **
|
---|
| 33 | ** Contact info@trolltech.com if any conditions of this licensing are
|
---|
| 34 | ** not clear to you.
|
---|
| 35 | **
|
---|
| 36 | **********************************************************************/
|
---|
| 37 |
|
---|
| 38 | #include "qiconset.h"
|
---|
| 39 |
|
---|
| 40 | #ifndef QT_NO_ICONSET
|
---|
| 41 |
|
---|
| 42 | #include "qapplication.h"
|
---|
| 43 | #include "qbitmap.h"
|
---|
| 44 | #include "qcleanuphandler.h"
|
---|
| 45 | #include "qimage.h"
|
---|
| 46 | #include "qpainter.h"
|
---|
| 47 |
|
---|
| 48 | enum { NumSizes = 2, NumModes = 3, NumStates = 2 };
|
---|
| 49 |
|
---|
| 50 | static QIconFactory *defaultFac = 0;
|
---|
| 51 | static QSingleCleanupHandler<QIconFactory> q_cleanup_icon_factory;
|
---|
| 52 |
|
---|
| 53 | static short widths[2] = { 22, 32 };
|
---|
| 54 | static short heights[2] = { 22, 32 };
|
---|
| 55 |
|
---|
| 56 | enum QIconSetIconOrigin {
|
---|
| 57 | SuppliedFileName, // 'fileName' contains the name of the file
|
---|
| 58 | SuppliedPixmap, // 'pixmap' is a pointer to the user-supplied pixmap
|
---|
| 59 | Manufactured, // 'pixmap' is a factory-generated pixmap (or 0)
|
---|
| 60 | Generated // 'pixmap' is a QIconSet-generated pixmap (or 0)
|
---|
| 61 | };
|
---|
| 62 |
|
---|
| 63 | struct QIconSetIcon
|
---|
| 64 | {
|
---|
| 65 | QIconSetIconOrigin origin;
|
---|
| 66 | union {
|
---|
| 67 | QString *fileName;
|
---|
| 68 | QPixmap *pixmap;
|
---|
| 69 | };
|
---|
| 70 |
|
---|
| 71 | QIconSetIcon() : origin( Generated ) { pixmap = 0; }
|
---|
| 72 | QIconSetIcon( const QIconSetIcon& other )
|
---|
| 73 | : origin( Generated ) {
|
---|
| 74 | pixmap = 0;
|
---|
| 75 | operator=( other );
|
---|
| 76 | }
|
---|
| 77 | ~QIconSetIcon() {
|
---|
| 78 | if ( origin == SuppliedFileName ) {
|
---|
| 79 | delete fileName;
|
---|
| 80 | } else {
|
---|
| 81 | delete pixmap;
|
---|
| 82 | }
|
---|
| 83 | }
|
---|
| 84 |
|
---|
| 85 | QIconSetIcon& operator=( const QIconSetIcon& other );
|
---|
| 86 |
|
---|
| 87 | void clearCached() {
|
---|
| 88 | if ( pixmap && (origin == Manufactured || origin == Generated) ) {
|
---|
| 89 | origin = Generated;
|
---|
| 90 | delete pixmap;
|
---|
| 91 | pixmap = 0;
|
---|
| 92 | }
|
---|
| 93 | }
|
---|
| 94 | };
|
---|
| 95 |
|
---|
| 96 | QIconSetIcon& QIconSetIcon::operator=( const QIconSetIcon& other )
|
---|
| 97 | {
|
---|
| 98 | QPixmap *oldPixmap = 0;
|
---|
| 99 | QString *oldFileName = 0;
|
---|
| 100 | if ( origin == SuppliedFileName ) {
|
---|
| 101 | oldFileName = fileName;
|
---|
| 102 | } else {
|
---|
| 103 | oldPixmap = pixmap;
|
---|
| 104 | }
|
---|
| 105 |
|
---|
| 106 | origin = other.origin;
|
---|
| 107 | if ( other.origin == SuppliedFileName ) {
|
---|
| 108 | fileName = new QString( *other.fileName );
|
---|
| 109 | } else {
|
---|
| 110 | if ( other.pixmap ) {
|
---|
| 111 | pixmap = new QPixmap( *other.pixmap );
|
---|
| 112 | } else {
|
---|
| 113 | pixmap = 0;
|
---|
| 114 | }
|
---|
| 115 | }
|
---|
| 116 | delete oldPixmap;
|
---|
| 117 | delete oldFileName;
|
---|
| 118 | return *this;
|
---|
| 119 | }
|
---|
| 120 |
|
---|
| 121 | class QIconSetPrivate : public QShared
|
---|
| 122 | {
|
---|
| 123 | public:
|
---|
| 124 | QIconSetIcon icons[NumSizes][NumModes][NumStates];
|
---|
| 125 | QPixmap defaultPix;
|
---|
| 126 | QIconFactory *factory;
|
---|
| 127 |
|
---|
| 128 | QIconSetPrivate() : factory( 0 ) { }
|
---|
| 129 | QIconSetPrivate( const QIconSetPrivate& other ) : QShared() {
|
---|
| 130 | count = 1;
|
---|
| 131 | for ( int i = 0; i < NumSizes; i++ ) {
|
---|
| 132 | for ( int j = 0; j < NumModes; j++ ) {
|
---|
| 133 | for ( int k = 0; k < NumStates; k++ ) {
|
---|
| 134 | icons[i][j][k] = other.icons[i][j][k];
|
---|
| 135 | }
|
---|
| 136 | }
|
---|
| 137 | }
|
---|
| 138 | defaultPix = other.defaultPix;
|
---|
| 139 | factory = other.factory;
|
---|
| 140 | if ( factory )
|
---|
| 141 | factory->ref();
|
---|
| 142 | }
|
---|
| 143 | ~QIconSetPrivate() {
|
---|
| 144 | setFactory( 0 );
|
---|
| 145 | }
|
---|
| 146 |
|
---|
| 147 | QIconSetIcon *icon( const QIconSet *iconSet, QIconSet::Size size,
|
---|
| 148 | QIconSet::Mode mode, QIconSet::State state );
|
---|
| 149 | void setFactory( QIconFactory *newFactory ) {
|
---|
| 150 | if ( newFactory )
|
---|
| 151 | newFactory->ref();
|
---|
| 152 | if ( factory && factory->deref() && factory->autoDelete() )
|
---|
| 153 | delete factory;
|
---|
| 154 | factory = newFactory;
|
---|
| 155 | }
|
---|
| 156 |
|
---|
| 157 | Q_DUMMY_COMPARISON_OPERATOR( QIconSetPrivate )
|
---|
| 158 | };
|
---|
| 159 |
|
---|
| 160 | QIconSetIcon *QIconSetPrivate::icon( const QIconSet *iconSet,
|
---|
| 161 | QIconSet::Size size, QIconSet::Mode mode,
|
---|
| 162 | QIconSet::State state )
|
---|
| 163 | {
|
---|
| 164 | QIconSetIcon *ik = &icons[(int) size - 1][(int) mode][(int) state];
|
---|
| 165 |
|
---|
| 166 | if ( iconSet ) {
|
---|
| 167 | if ( ik->origin == SuppliedFileName ) {
|
---|
| 168 | QPixmap *newPixmap = new QPixmap( *ik->fileName );
|
---|
| 169 | delete ik->fileName;
|
---|
| 170 |
|
---|
| 171 | if ( newPixmap->isNull() ) {
|
---|
| 172 | delete newPixmap;
|
---|
| 173 | ik->origin = Generated;
|
---|
| 174 | ik->pixmap = 0;
|
---|
| 175 | } else {
|
---|
| 176 | ik->origin = SuppliedPixmap;
|
---|
| 177 | ik->pixmap = newPixmap;
|
---|
| 178 | }
|
---|
| 179 | }
|
---|
| 180 |
|
---|
| 181 | if ( !ik->pixmap && ik->origin == Generated ) {
|
---|
| 182 | QIconFactory *f = factory;
|
---|
| 183 | if ( !f )
|
---|
| 184 | f = defaultFac;
|
---|
| 185 |
|
---|
| 186 | if ( f ) {
|
---|
| 187 | /*
|
---|
| 188 | We set 'origin' to Manufactured half a second too
|
---|
| 189 | early to prevent recursive calls to this function.
|
---|
| 190 | (This can happen if createPixmap() calls
|
---|
| 191 | QIconSet::pixmap(), which in turn calls this
|
---|
| 192 | function.)
|
---|
| 193 | */
|
---|
| 194 | ik->origin = Manufactured;
|
---|
| 195 | ik->pixmap = f->createPixmap( *iconSet, size, mode, state );
|
---|
| 196 | if ( !ik->pixmap )
|
---|
| 197 | ik->origin = Generated;
|
---|
| 198 | }
|
---|
| 199 | }
|
---|
| 200 | }
|
---|
| 201 | return ik;
|
---|
| 202 | }
|
---|
| 203 |
|
---|
| 204 | /*! \class QIconSet
|
---|
| 205 |
|
---|
| 206 | \brief The QIconSet class provides a set of icons with different
|
---|
| 207 | styles and sizes.
|
---|
| 208 |
|
---|
| 209 | \ingroup graphics
|
---|
| 210 | \ingroup images
|
---|
| 211 | \ingroup shared
|
---|
| 212 | \mainclass
|
---|
| 213 |
|
---|
| 214 | A QIconSet can generate smaller, larger, active, and disabled pixmaps
|
---|
| 215 | from the set of icons it is given. Such pixmaps are used by
|
---|
| 216 | QToolButton, QHeader, QPopupMenu, etc. to show an icon representing a
|
---|
| 217 | particular action.
|
---|
| 218 |
|
---|
| 219 | The simplest use of QIconSet is to create one from a QPixmap and then
|
---|
| 220 | use it, allowing Qt to work out all the required icon styles and
|
---|
| 221 | sizes. For example:
|
---|
| 222 |
|
---|
| 223 | \code
|
---|
| 224 | QToolButton *but = new QToolButton( QIconSet( QPixmap("open.xpm") ), ... );
|
---|
| 225 | \endcode
|
---|
| 226 |
|
---|
| 227 | Using whichever pixmaps you specify as a base, QIconSet provides a
|
---|
| 228 | set of six icons, each with a \l Size and a \l Mode: Small Normal,
|
---|
| 229 | Small Disabled, Small Active, Large Normal, Large Disabled, and
|
---|
| 230 | Large Active.
|
---|
| 231 |
|
---|
| 232 | An additional set of six icons can be provided for widgets that have
|
---|
| 233 | an "On" or "Off" state, like checkable menu items or toggleable
|
---|
| 234 | toolbuttons. If you provide pixmaps for the "On" state, but not for
|
---|
| 235 | the "Off" state, the QIconSet will provide the "Off" pixmaps. You may
|
---|
| 236 | specify icons for both states in you wish.
|
---|
| 237 |
|
---|
| 238 | You can set any of the icons using setPixmap().
|
---|
| 239 |
|
---|
| 240 | When you retrieve a pixmap using pixmap(Size, Mode, State),
|
---|
| 241 | QIconSet will return the icon that has been set or previously
|
---|
| 242 | generated for that size, mode and state combination. If none is
|
---|
| 243 | available, QIconSet will ask the icon factory. If the icon factory
|
---|
| 244 | cannot provide any (the default), QIconSet generates a pixmap based
|
---|
| 245 | on the pixmaps it has been given and returns it.
|
---|
| 246 |
|
---|
| 247 | The \c Disabled appearance is computed using an algorithm that
|
---|
| 248 | produces results very similar to those used in Microsoft Windows
|
---|
| 249 | 95. The \c Active appearance is identical to the \c Normal
|
---|
| 250 | appearance unless you use setPixmap() to set it to something
|
---|
| 251 | special.
|
---|
| 252 |
|
---|
| 253 | When scaling icons, QIconSet uses \link QImage::smoothScale()
|
---|
| 254 | smooth scaling\endlink, which can partially blend the color component
|
---|
| 255 | of pixmaps. If the results look poor, the best solution
|
---|
| 256 | is to supply pixmaps in both large and small sizes.
|
---|
| 257 |
|
---|
| 258 | You can use the static function setIconSize() to set the preferred
|
---|
| 259 | size of the generated large/small icons. The default small size is
|
---|
| 260 | 22 x 22, while the default large size is 32 x 32. These sizes only
|
---|
| 261 | affect generated icons.
|
---|
| 262 |
|
---|
| 263 | The isGenerated() function returns TRUE if an icon was generated by
|
---|
| 264 | QIconSet or by a factory; clearGenerated() clears all cached
|
---|
| 265 | pixmaps.
|
---|
| 266 |
|
---|
| 267 | \section1 Making Classes that Use QIconSet
|
---|
| 268 |
|
---|
| 269 | If you write your own widgets that have an option to set a small
|
---|
| 270 | pixmap, consider allowing a QIconSet to be set for that pixmap. The
|
---|
| 271 | Qt class QToolButton is an example of such a widget.
|
---|
| 272 |
|
---|
| 273 | Provide a method to set a QIconSet, and when you draw the icon, choose
|
---|
| 274 | whichever icon is appropriate for the current state of your widget.
|
---|
| 275 | For example:
|
---|
| 276 | \code
|
---|
| 277 | void MyWidget::drawIcon( QPainter* p, QPoint pos )
|
---|
| 278 | {
|
---|
| 279 | p->drawPixmap( pos, icons->pixmap(
|
---|
| 280 | QIconSet::Small,
|
---|
| 281 | isEnabled() ? QIconSet::Normal :
|
---|
| 282 | QIconSet::Disabled,
|
---|
| 283 | isEnabled() ? QIconSet::On :
|
---|
| 284 | QIconSet::Off));
|
---|
| 285 | }
|
---|
| 286 | \endcode
|
---|
| 287 |
|
---|
| 288 | You might also make use of the \c Active mode, perhaps making your
|
---|
| 289 | widget \c Active when the mouse is over the widget (see \l
|
---|
| 290 | QWidget::enterEvent()), while the mouse is pressed pending the
|
---|
| 291 | release that will activate the function, or when it is the currently
|
---|
| 292 | selected item. If the widget can be toggled, the "On" mode might be
|
---|
| 293 | used to draw a different icon.
|
---|
| 294 |
|
---|
| 295 | \img iconset.png QIconSet
|
---|
| 296 |
|
---|
| 297 | \sa QIconFactory QPixmap QMainWindow::setUsesBigPixmaps()
|
---|
| 298 | \link guibooks.html#fowler GUI Design Handbook: Iconic Label \endlink
|
---|
| 299 | */
|
---|
| 300 |
|
---|
| 301 |
|
---|
| 302 | /*!
|
---|
| 303 | \enum QIconSet::Size
|
---|
| 304 |
|
---|
| 305 | This enum type describes the size at which a pixmap is intended to be
|
---|
| 306 | used.
|
---|
| 307 | The currently defined sizes are:
|
---|
| 308 |
|
---|
| 309 | \value Automatic The size of the pixmap is determined from its
|
---|
| 310 | pixel size. This is a useful default.
|
---|
| 311 | \value Small The pixmap is the smaller of two.
|
---|
| 312 | \value Large The pixmap is the larger of two.
|
---|
| 313 |
|
---|
| 314 | If a Small pixmap is not set by QIconSet::setPixmap(), the Large
|
---|
| 315 | pixmap will be automatically scaled down to the size of a small pixmap
|
---|
| 316 | to generate the Small pixmap when required. Similarly, a Small pixmap
|
---|
| 317 | will be automatically scaled up to generate a Large pixmap. The
|
---|
| 318 | preferred sizes for large/small generated icons can be set using
|
---|
| 319 | setIconSize().
|
---|
| 320 |
|
---|
| 321 | \sa setIconSize() iconSize() setPixmap() pixmap() QMainWindow::setUsesBigPixmaps()
|
---|
| 322 | */
|
---|
| 323 |
|
---|
| 324 | /*!
|
---|
| 325 | \enum QIconSet::Mode
|
---|
| 326 |
|
---|
| 327 | This enum type describes the mode for which a pixmap is intended to be
|
---|
| 328 | used.
|
---|
| 329 | The currently defined modes are:
|
---|
| 330 |
|
---|
| 331 | \value Normal
|
---|
| 332 | Display the pixmap when the user is
|
---|
| 333 | not interacting with the icon, but the
|
---|
| 334 | functionality represented by the icon is available.
|
---|
| 335 | \value Disabled
|
---|
| 336 | Display the pixmap when the
|
---|
| 337 | functionality represented by the icon is not available.
|
---|
| 338 | \value Active
|
---|
| 339 | Display the pixmap when the
|
---|
| 340 | functionality represented by the icon is available and
|
---|
| 341 | the user is interacting with the icon, for example, moving the
|
---|
| 342 | mouse over it or clicking it.
|
---|
| 343 | */
|
---|
| 344 |
|
---|
| 345 | /*!
|
---|
| 346 | \enum QIconSet::State
|
---|
| 347 |
|
---|
| 348 | This enum describes the state for which a pixmap is intended to be
|
---|
| 349 | used. The \e state can be:
|
---|
| 350 |
|
---|
| 351 | \value Off Display the pixmap when the widget is in an "off" state
|
---|
| 352 | \value On Display the pixmap when the widget is in an "on" state
|
---|
| 353 |
|
---|
| 354 | \sa setPixmap() pixmap()
|
---|
| 355 | */
|
---|
| 356 |
|
---|
| 357 | /*!
|
---|
| 358 | Constructs a null icon set.
|
---|
| 359 |
|
---|
| 360 | \sa setPixmap(), reset()
|
---|
| 361 | */
|
---|
| 362 | QIconSet::QIconSet()
|
---|
| 363 | : d( 0 )
|
---|
| 364 | {
|
---|
| 365 | }
|
---|
| 366 |
|
---|
| 367 | /*!
|
---|
| 368 | Constructs an icon set for which the Normal pixmap is \a pixmap,
|
---|
| 369 | which is assumed to be of size \a size.
|
---|
| 370 |
|
---|
| 371 | The default for \a size is \c Automatic, which means that QIconSet
|
---|
| 372 | will determine whether the pixmap is Small or Large from its pixel
|
---|
| 373 | size. Pixmaps less than the width of a small generated icon are
|
---|
| 374 | considered to be Small. You can use setIconSize() to set the
|
---|
| 375 | preferred size of a generated icon.
|
---|
| 376 |
|
---|
| 377 | \sa setIconSize() reset()
|
---|
| 378 | */
|
---|
| 379 | QIconSet::QIconSet( const QPixmap& pixmap, Size size )
|
---|
| 380 | : d( 0 )
|
---|
| 381 | {
|
---|
| 382 | reset( pixmap, size );
|
---|
| 383 | }
|
---|
| 384 |
|
---|
| 385 | /*! Creates an iconset which uses the pixmap \a smallPix for for
|
---|
| 386 | displaying a small icon, and the pixmap \a largePix for displaying a
|
---|
| 387 | large icon.
|
---|
| 388 | */
|
---|
| 389 | QIconSet::QIconSet( const QPixmap& smallPix, const QPixmap& largePix )
|
---|
| 390 | : d( 0 )
|
---|
| 391 | {
|
---|
| 392 | reset( smallPix, Small );
|
---|
| 393 | reset( largePix, Large );
|
---|
| 394 | }
|
---|
| 395 |
|
---|
| 396 | /*!
|
---|
| 397 | Constructs a copy of \a other. This is very fast.
|
---|
| 398 | */
|
---|
| 399 | QIconSet::QIconSet( const QIconSet& other )
|
---|
| 400 | : d( other.d )
|
---|
| 401 | {
|
---|
| 402 | if ( d )
|
---|
| 403 | d->ref();
|
---|
| 404 | }
|
---|
| 405 |
|
---|
| 406 | /*!
|
---|
| 407 | Destroys the icon set and frees any allocated resources.
|
---|
| 408 | */
|
---|
| 409 | QIconSet::~QIconSet()
|
---|
| 410 | {
|
---|
| 411 | if ( d && d->deref() )
|
---|
| 412 | delete d;
|
---|
| 413 | }
|
---|
| 414 |
|
---|
| 415 | /*!
|
---|
| 416 | Sets this icon set to use pixmap \a pixmap for the Normal pixmap,
|
---|
| 417 | assuming it to be of size \a size.
|
---|
| 418 |
|
---|
| 419 | This is equivalent to assigning QIconSet(\a pixmap, \a size) to this
|
---|
| 420 | icon set.
|
---|
| 421 |
|
---|
| 422 | This function does nothing if \a pixmap is a null pixmap.
|
---|
| 423 | */
|
---|
| 424 | void QIconSet::reset( const QPixmap& pixmap, Size size )
|
---|
| 425 | {
|
---|
| 426 | if ( pixmap.isNull() )
|
---|
| 427 | return;
|
---|
| 428 |
|
---|
| 429 | detach();
|
---|
| 430 | normalize( size, pixmap.size() );
|
---|
| 431 | setPixmap( pixmap, size, Normal );
|
---|
| 432 | d->defaultPix = pixmap;
|
---|
| 433 | d->setFactory( 0 );
|
---|
| 434 | }
|
---|
| 435 |
|
---|
| 436 | /*!
|
---|
| 437 | Sets this icon set to provide pixmap \a pixmap for size \a size, mode \a
|
---|
| 438 | mode and state \a state. The icon set may also use \a pixmap for
|
---|
| 439 | generating other pixmaps if they are not explicitly set.
|
---|
| 440 |
|
---|
| 441 | The \a size can be one of Automatic, Large or Small. If Automatic is
|
---|
| 442 | used, QIconSet will determine if the pixmap is Small or Large from its
|
---|
| 443 | pixel size.
|
---|
| 444 |
|
---|
| 445 | Pixmaps less than the width of a small generated icon are
|
---|
| 446 | considered to be Small. You can use setIconSize() to set the preferred
|
---|
| 447 | size of a generated icon.
|
---|
| 448 |
|
---|
| 449 | This function does nothing if \a pixmap is a null pixmap.
|
---|
| 450 |
|
---|
| 451 | \sa reset()
|
---|
| 452 | */
|
---|
| 453 | void QIconSet::setPixmap( const QPixmap& pixmap, Size size, Mode mode,
|
---|
| 454 | State state )
|
---|
| 455 | {
|
---|
| 456 | if ( pixmap.isNull() )
|
---|
| 457 | return;
|
---|
| 458 |
|
---|
| 459 | normalize( size, pixmap.size() );
|
---|
| 460 |
|
---|
| 461 | detach();
|
---|
| 462 | clearGenerated();
|
---|
| 463 |
|
---|
| 464 | QIconSetIcon *icon = d->icon( 0, size, mode, state );
|
---|
| 465 | if ( icon->origin == SuppliedFileName ) {
|
---|
| 466 | delete icon->fileName;
|
---|
| 467 | icon->pixmap = 0;
|
---|
| 468 | }
|
---|
| 469 | icon->origin = SuppliedPixmap;
|
---|
| 470 | if ( icon->pixmap == 0 ) {
|
---|
| 471 | icon->pixmap = new QPixmap( pixmap );
|
---|
| 472 | } else {
|
---|
| 473 | *icon->pixmap = pixmap;
|
---|
| 474 | }
|
---|
| 475 | }
|
---|
| 476 |
|
---|
| 477 | /*!
|
---|
| 478 | \overload
|
---|
| 479 |
|
---|
| 480 | The pixmap is loaded from \a fileName when it becomes necessary.
|
---|
| 481 | */
|
---|
| 482 | void QIconSet::setPixmap( const QString& fileName, Size size, Mode mode,
|
---|
| 483 | State state )
|
---|
| 484 | {
|
---|
| 485 | if ( size == Automatic ) {
|
---|
| 486 | setPixmap( QPixmap(fileName), size, mode, state );
|
---|
| 487 | } else {
|
---|
| 488 | detach();
|
---|
| 489 | clearGenerated();
|
---|
| 490 |
|
---|
| 491 | QIconSetIcon *icon = d->icon( 0, size, mode, state );
|
---|
| 492 | if ( icon->origin == SuppliedFileName ) {
|
---|
| 493 | *icon->fileName = fileName;
|
---|
| 494 | } else {
|
---|
| 495 | delete icon->pixmap;
|
---|
| 496 | icon->fileName = new QString( fileName );
|
---|
| 497 | icon->origin = SuppliedFileName;
|
---|
| 498 | }
|
---|
| 499 | }
|
---|
| 500 | }
|
---|
| 501 |
|
---|
| 502 | /*!
|
---|
| 503 | Returns a pixmap with size \a size, mode \a mode and state \a
|
---|
| 504 | state, generating one if necessary. Generated pixmaps are cached.
|
---|
| 505 | */
|
---|
| 506 | QPixmap QIconSet::pixmap( Size size, Mode mode, State state ) const
|
---|
| 507 | {
|
---|
| 508 | if ( !d ) {
|
---|
| 509 | if ( defaultFac ) {
|
---|
| 510 | QIconSet *that = (QIconSet *) this;
|
---|
| 511 | that->detach();
|
---|
| 512 | } else {
|
---|
| 513 | return QPixmap();
|
---|
| 514 | }
|
---|
| 515 | }
|
---|
| 516 |
|
---|
| 517 | if ( size == Automatic )
|
---|
| 518 | size = Small;
|
---|
| 519 |
|
---|
| 520 | QIconSetIcon *icon = d->icon( this, size, mode, state );
|
---|
| 521 | if ( icon->pixmap )
|
---|
| 522 | return *icon->pixmap;
|
---|
| 523 | if ( icon->origin == Manufactured ) {
|
---|
| 524 | /*
|
---|
| 525 | This can only occur during the half a second's time when
|
---|
| 526 | the icon is being manufactured. If QIconFactory somehow
|
---|
| 527 | tries to access the pixmap it's supposed to be creating, it
|
---|
| 528 | will get a null pixmap.
|
---|
| 529 | */
|
---|
| 530 | return QPixmap();
|
---|
| 531 | }
|
---|
| 532 |
|
---|
| 533 | if ( mode == Active )
|
---|
| 534 | return pixmap( size, Normal, state );
|
---|
| 535 |
|
---|
| 536 | Size otherSize = ( size == Large ) ? Small : Large;
|
---|
| 537 | QIconSetIcon *otherSizeIcon = d->icon( this, otherSize, mode, state );
|
---|
| 538 |
|
---|
| 539 | if ( state == Off ) {
|
---|
| 540 | if ( mode == Disabled &&
|
---|
| 541 | d->icon(this, size, Normal, Off)->origin != Generated ) {
|
---|
| 542 | icon->pixmap = createDisabled( size, Off );
|
---|
| 543 | } else if ( otherSizeIcon->origin != Generated ) {
|
---|
| 544 | icon->pixmap = createScaled( size, otherSizeIcon->pixmap );
|
---|
| 545 | } else if ( mode == Disabled ) {
|
---|
| 546 | icon->pixmap = createDisabled( size, Off );
|
---|
| 547 | } else if ( !d->defaultPix.isNull() ) {
|
---|
| 548 | icon->pixmap = new QPixmap( d->defaultPix );
|
---|
| 549 | } else {
|
---|
| 550 | /*
|
---|
| 551 | No icons are available for { TRUE, Normal, Off } and
|
---|
| 552 | { FALSE, Normal, Off }. Try the other 10 combinaisons,
|
---|
| 553 | best ones first.
|
---|
| 554 | */
|
---|
| 555 | const int N = 10;
|
---|
| 556 | static const struct {
|
---|
| 557 | bool sameSize;
|
---|
| 558 | Mode mode;
|
---|
| 559 | State state;
|
---|
| 560 | } tryList[N] = {
|
---|
| 561 | { TRUE, Active, Off },
|
---|
| 562 | { TRUE, Normal, On },
|
---|
| 563 | { TRUE, Active, On },
|
---|
| 564 | { FALSE, Active, Off },
|
---|
| 565 | { FALSE, Normal, On },
|
---|
| 566 | { FALSE, Active, On },
|
---|
| 567 | { TRUE, Disabled, Off },
|
---|
| 568 | { TRUE, Disabled, On },
|
---|
| 569 | { FALSE, Disabled, Off },
|
---|
| 570 | { FALSE, Disabled, On }
|
---|
| 571 | };
|
---|
| 572 |
|
---|
| 573 | for ( int i = 0; i < N; i++ ) {
|
---|
| 574 | bool sameSize = tryList[i].sameSize;
|
---|
| 575 | QIconSetIcon *tryIcon =
|
---|
| 576 | d->icon( this, sameSize ? size : otherSize,
|
---|
| 577 | tryList[i].mode, tryList[i].state );
|
---|
| 578 | if ( tryIcon->origin != Generated ) {
|
---|
| 579 | if ( sameSize ) {
|
---|
| 580 | if ( tryIcon->pixmap )
|
---|
| 581 | icon->pixmap = new QPixmap( *tryIcon->pixmap );
|
---|
| 582 | } else {
|
---|
| 583 | icon->pixmap = createScaled( size, tryIcon->pixmap );
|
---|
| 584 | }
|
---|
| 585 | break;
|
---|
| 586 | }
|
---|
| 587 | }
|
---|
| 588 | }
|
---|
| 589 | } else { /* ( state == On ) */
|
---|
| 590 | if ( mode == Normal ) {
|
---|
| 591 | if ( otherSizeIcon->origin != Generated ) {
|
---|
| 592 | icon->pixmap = createScaled( size, otherSizeIcon->pixmap );
|
---|
| 593 | } else {
|
---|
| 594 | icon->pixmap = new QPixmap( pixmap(size, mode, Off) );
|
---|
| 595 | }
|
---|
| 596 | } else { /* ( mode == Disabled ) */
|
---|
| 597 | QIconSetIcon *offIcon = d->icon( this, size, mode, Off );
|
---|
| 598 | QIconSetIcon *otherSizeOffIcon = d->icon( this, otherSize, mode,
|
---|
| 599 | Off );
|
---|
| 600 |
|
---|
| 601 | if ( offIcon->origin != Generated ) {
|
---|
| 602 | if ( offIcon->pixmap )
|
---|
| 603 | icon->pixmap = new QPixmap( *offIcon->pixmap );
|
---|
| 604 | } else if ( d->icon(this, size, Normal, On)->origin != Generated ) {
|
---|
| 605 | icon->pixmap = createDisabled( size, On );
|
---|
| 606 | } else if ( otherSizeIcon->origin != Generated ) {
|
---|
| 607 | icon->pixmap = createScaled( size, otherSizeIcon->pixmap );
|
---|
| 608 | } else if ( otherSizeOffIcon->origin != Generated ) {
|
---|
| 609 | icon->pixmap = createScaled( size, otherSizeOffIcon->pixmap );
|
---|
| 610 | } else {
|
---|
| 611 | icon->pixmap = createDisabled( size, On );
|
---|
| 612 | }
|
---|
| 613 | }
|
---|
| 614 | }
|
---|
| 615 | if ( icon->pixmap ) {
|
---|
| 616 | return *icon->pixmap;
|
---|
| 617 | } else {
|
---|
| 618 | return QPixmap();
|
---|
| 619 | }
|
---|
| 620 | }
|
---|
| 621 |
|
---|
| 622 | /*! \overload
|
---|
| 623 | \obsolete
|
---|
| 624 |
|
---|
| 625 | This is the same as pixmap(\a size, \a enabled, \a state).
|
---|
| 626 | */
|
---|
| 627 | QPixmap QIconSet::pixmap( Size size, bool enabled, State state ) const
|
---|
| 628 | {
|
---|
| 629 | return pixmap( size, enabled ? Normal : Disabled, state );
|
---|
| 630 | }
|
---|
| 631 |
|
---|
| 632 | /*!
|
---|
| 633 | \overload
|
---|
| 634 |
|
---|
| 635 | Returns the pixmap originally provided to the constructor or to
|
---|
| 636 | reset(). This is the Normal pixmap of unspecified Size.
|
---|
| 637 |
|
---|
| 638 | \sa reset()
|
---|
| 639 | */
|
---|
| 640 | QPixmap QIconSet::pixmap() const
|
---|
| 641 | {
|
---|
| 642 | if ( !d )
|
---|
| 643 | return QPixmap();
|
---|
| 644 | return d->defaultPix;
|
---|
| 645 | }
|
---|
| 646 |
|
---|
| 647 | /*!
|
---|
| 648 | Returns TRUE if the pixmap with size \a size, mode \a mode and
|
---|
| 649 | state \a state is generated from other pixmaps; otherwise returns
|
---|
| 650 | FALSE.
|
---|
| 651 |
|
---|
| 652 | A pixmap obtained from a QIconFactory is considered non-generated.
|
---|
| 653 | */
|
---|
| 654 | bool QIconSet::isGenerated( Size size, Mode mode, State state ) const
|
---|
| 655 | {
|
---|
| 656 | if ( !d )
|
---|
| 657 | return TRUE;
|
---|
| 658 | return d->icon( this, size, mode, state )->origin == Generated;
|
---|
| 659 | };
|
---|
| 660 |
|
---|
| 661 | /*!
|
---|
| 662 | Clears all cached pixmaps, including those obtained from an
|
---|
| 663 | eventual QIconFactory.
|
---|
| 664 | */
|
---|
| 665 | void QIconSet::clearGenerated()
|
---|
| 666 | {
|
---|
| 667 | if ( !d )
|
---|
| 668 | return;
|
---|
| 669 |
|
---|
| 670 | for ( int i = 0; i < NumSizes; i++ ) {
|
---|
| 671 | for ( int j = 0; j < NumModes; j++ ) {
|
---|
| 672 | for ( int k = 0; k < NumStates; k++ ) {
|
---|
| 673 | d->icons[i][j][k].clearCached();
|
---|
| 674 | }
|
---|
| 675 | }
|
---|
| 676 | }
|
---|
| 677 | }
|
---|
| 678 |
|
---|
| 679 | /*!
|
---|
| 680 | Installs \a factory as the icon factory for this iconset. The
|
---|
| 681 | icon factory is used to generates pixmaps not set by the user.
|
---|
| 682 |
|
---|
| 683 | If no icon factory is installed, QIconFactory::defaultFactory()
|
---|
| 684 | is used.
|
---|
| 685 | */
|
---|
| 686 | void QIconSet::installIconFactory( QIconFactory *factory )
|
---|
| 687 | {
|
---|
| 688 | detach();
|
---|
| 689 | d->setFactory( factory );
|
---|
| 690 | }
|
---|
| 691 |
|
---|
| 692 | /*!
|
---|
| 693 | Returns TRUE if the icon set is empty; otherwise returns FALSE.
|
---|
| 694 | */
|
---|
| 695 | bool QIconSet::isNull() const
|
---|
| 696 | {
|
---|
| 697 | return !d;
|
---|
| 698 | }
|
---|
| 699 |
|
---|
| 700 | /*!
|
---|
| 701 | Detaches this icon set from others with which it may share data.
|
---|
| 702 |
|
---|
| 703 | You will never need to call this function; other QIconSet functions
|
---|
| 704 | call it as necessary.
|
---|
| 705 | */
|
---|
| 706 | void QIconSet::detach()
|
---|
| 707 | {
|
---|
| 708 | if ( !d ) {
|
---|
| 709 | d = new QIconSetPrivate;
|
---|
| 710 | return;
|
---|
| 711 | }
|
---|
| 712 | if ( d->count != 1 ) {
|
---|
| 713 | d->deref();
|
---|
| 714 | d = new QIconSetPrivate( *d );
|
---|
| 715 | }
|
---|
| 716 | }
|
---|
| 717 |
|
---|
| 718 | /*!
|
---|
| 719 | Assigns \a other to this icon set and returns a reference to this
|
---|
| 720 | icon set.
|
---|
| 721 |
|
---|
| 722 | \sa detach()
|
---|
| 723 | */
|
---|
| 724 | QIconSet& QIconSet::operator=( const QIconSet& other )
|
---|
| 725 | {
|
---|
| 726 | if ( other.d )
|
---|
| 727 | other.d->ref();
|
---|
| 728 |
|
---|
| 729 | if ( d && d->deref() )
|
---|
| 730 | delete d;
|
---|
| 731 | d = other.d;
|
---|
| 732 | return *this;
|
---|
| 733 | }
|
---|
| 734 |
|
---|
| 735 | /*!
|
---|
| 736 | Set the preferred size for all small or large icons that are
|
---|
| 737 | generated after this call. If \a which is Small, sets the preferred
|
---|
| 738 | size of small generated icons to \a size. Similarly, if \a which is
|
---|
| 739 | Large, sets the preferred size of large generated icons to \a size.
|
---|
| 740 |
|
---|
| 741 | Note that cached icons will not be regenerated, so it is recommended
|
---|
| 742 | that you set the preferred icon sizes before generating any icon sets.
|
---|
| 743 | Also note that the preferred icon sizes will be ignored for icon sets
|
---|
| 744 | that have been created using both small and large pixmaps.
|
---|
| 745 |
|
---|
| 746 | \sa iconSize()
|
---|
| 747 | */
|
---|
| 748 | void QIconSet::setIconSize( Size which, const QSize& size )
|
---|
| 749 | {
|
---|
| 750 | widths[(int) which - 1] = size.width();
|
---|
| 751 | heights[(int) which - 1] = size.height();
|
---|
| 752 | }
|
---|
| 753 |
|
---|
| 754 | /*!
|
---|
| 755 | If \a which is Small, returns the preferred size of a small
|
---|
| 756 | generated icon; if \a which is Large, returns the preferred size
|
---|
| 757 | of a large generated icon.
|
---|
| 758 |
|
---|
| 759 | \sa setIconSize()
|
---|
| 760 | */
|
---|
| 761 | const QSize& QIconSet::iconSize( Size which )
|
---|
| 762 | {
|
---|
| 763 | // ### replace 'const QSize&' with QSize in Qt 4 and simply this code
|
---|
| 764 | static QSize size;
|
---|
| 765 | size = QSize( widths[(int) which - 1], heights[(int) which - 1] );
|
---|
| 766 | return size;
|
---|
| 767 | }
|
---|
| 768 |
|
---|
| 769 | void QIconSet::normalize( Size& which, const QSize& pixSize )
|
---|
| 770 | {
|
---|
| 771 | if ( which == Automatic )
|
---|
| 772 | which = pixSize.width() > iconSize( Small ).width() ? Large : Small;
|
---|
| 773 | }
|
---|
| 774 |
|
---|
| 775 | /*!
|
---|
| 776 | Returns a new pixmap that is a copy of \a suppliedPix, scaled to
|
---|
| 777 | the icon size \a size.
|
---|
| 778 | */
|
---|
| 779 | QPixmap *QIconSet::createScaled( Size size, const QPixmap *suppliedPix ) const
|
---|
| 780 | {
|
---|
| 781 | if ( !suppliedPix || suppliedPix->isNull() )
|
---|
| 782 | return 0;
|
---|
| 783 |
|
---|
| 784 | QImage img = suppliedPix->convertToImage();
|
---|
| 785 | QSize imgSize = iconSize( size );
|
---|
| 786 | if ( size == Small ) {
|
---|
| 787 | imgSize = imgSize.boundedTo( img.size() );
|
---|
| 788 | } else {
|
---|
| 789 | imgSize = imgSize.expandedTo( img.size() );
|
---|
| 790 | }
|
---|
| 791 | img = img.smoothScale( imgSize );
|
---|
| 792 |
|
---|
| 793 | QPixmap *pixmap = new QPixmap( img );
|
---|
| 794 | if ( !pixmap->mask() ) {
|
---|
| 795 | QBitmap mask;
|
---|
| 796 | mask.convertFromImage( img.createHeuristicMask(),
|
---|
| 797 | Qt::MonoOnly | Qt::ThresholdDither );
|
---|
| 798 | pixmap->setMask( mask );
|
---|
| 799 | }
|
---|
| 800 | return pixmap;
|
---|
| 801 | }
|
---|
| 802 |
|
---|
| 803 | /*!
|
---|
| 804 | Returns a new pixmap that has a 'disabled' look, taking as its
|
---|
| 805 | base the iconset's icon with size \a size and state \a state.
|
---|
| 806 | */
|
---|
| 807 | QPixmap *QIconSet::createDisabled( Size size, State state ) const
|
---|
| 808 | {
|
---|
| 809 | QPixmap normalPix = pixmap( size, Normal, state );
|
---|
| 810 | if ( normalPix.isNull() )
|
---|
| 811 | return 0;
|
---|
| 812 |
|
---|
| 813 | QImage img;
|
---|
| 814 | QPixmap *pixmap = 0;
|
---|
| 815 | QBitmap normalMask;
|
---|
| 816 | if ( normalPix.mask() ) {
|
---|
| 817 | normalMask = *normalPix.mask();
|
---|
| 818 | } else {
|
---|
| 819 | img = normalPix.convertToImage();
|
---|
| 820 | normalMask.convertFromImage( img.createHeuristicMask(),
|
---|
| 821 | Qt::MonoOnly | Qt::ThresholdDither );
|
---|
| 822 | }
|
---|
| 823 |
|
---|
| 824 | pixmap = new QPixmap( normalPix.width() + 1,
|
---|
| 825 | normalPix.height() + 1 );
|
---|
| 826 | const QColorGroup &dis = QApplication::palette().disabled();
|
---|
| 827 | pixmap->fill( dis.background() );
|
---|
| 828 |
|
---|
[8] | 829 | if ( !normalMask.mask() )
|
---|
| 830 | normalMask.setMask( normalMask );
|
---|
| 831 |
|
---|
[2] | 832 | QPainter painter;
|
---|
| 833 | painter.begin( pixmap );
|
---|
[8] | 834 | painter.setPen( dis.light() );
|
---|
[2] | 835 | painter.drawPixmap( 1, 1, normalMask );
|
---|
[8] | 836 | painter.setPen( dis.dark() );
|
---|
[2] | 837 | painter.drawPixmap( 0, 0, normalMask );
|
---|
| 838 | painter.end();
|
---|
| 839 |
|
---|
| 840 | QBitmap mask( pixmap->size() );
|
---|
| 841 | mask.fill( Qt::color0 );
|
---|
| 842 | painter.begin( &mask );
|
---|
| 843 | painter.drawPixmap( 0, 0, normalMask );
|
---|
| 844 | painter.drawPixmap( 1, 1, normalMask );
|
---|
| 845 | painter.end();
|
---|
| 846 | pixmap->setMask( mask );
|
---|
| 847 | return pixmap;
|
---|
| 848 | }
|
---|
| 849 |
|
---|
| 850 | /*! \class QIconFactory
|
---|
| 851 | \ingroup advanced
|
---|
| 852 | \brief The QIconFactory class is used to create pixmaps for a QIconSet.
|
---|
| 853 |
|
---|
| 854 | By reimplementing createPixmap(), you can override QIconSet's
|
---|
| 855 | default algorithm for computing pixmaps not supplied by the user.
|
---|
| 856 |
|
---|
| 857 | Call setAutoDelete(TRUE) if you want the factory to automatically
|
---|
| 858 | delete itself when it is no longer needed by QIconSet.
|
---|
| 859 |
|
---|
| 860 | \sa QIconSet
|
---|
| 861 | */
|
---|
| 862 |
|
---|
| 863 | /*!
|
---|
| 864 | Constructs an icon factory.
|
---|
| 865 | */
|
---|
| 866 | QIconFactory::QIconFactory()
|
---|
| 867 | : autoDel( 0 )
|
---|
| 868 | {
|
---|
| 869 | count = 0;
|
---|
| 870 | }
|
---|
| 871 |
|
---|
| 872 | /*!
|
---|
| 873 | Destroys the object and frees any allocated resources.
|
---|
| 874 | */
|
---|
| 875 | QIconFactory::~QIconFactory()
|
---|
| 876 | {
|
---|
| 877 | }
|
---|
| 878 |
|
---|
| 879 | /*!
|
---|
| 880 | Ceates a pixmap for \a iconSet with a certain \a size, \a mode, and
|
---|
| 881 | \a state. Returns 0 if the default QIconSet algorithm should be
|
---|
| 882 | used to create a pixmap that wasn't supplied by the user.
|
---|
| 883 |
|
---|
| 884 | It is the caller's responsibility to delete the returned pixmap.
|
---|
| 885 |
|
---|
| 886 | The default implementation always returns 0.
|
---|
| 887 | */
|
---|
| 888 | QPixmap *QIconFactory::createPixmap( const QIconSet& /* iconSet */,
|
---|
| 889 | QIconSet::Size /* size */,
|
---|
| 890 | QIconSet::Mode /* mode */,
|
---|
| 891 | QIconSet::State /* state */ )
|
---|
| 892 | {
|
---|
| 893 | return 0;
|
---|
| 894 | }
|
---|
| 895 |
|
---|
| 896 | /*!
|
---|
| 897 | \fn void QIconFactory::setAutoDelete( bool autoDelete )
|
---|
| 898 |
|
---|
| 899 | If \a autoDelete is TRUE, sets the icon factory to automatically
|
---|
| 900 | delete itself when it is no longer referenced by any QIconSet and
|
---|
| 901 | isn't the default factory. If \a autoDelete is FALSE (the default)
|
---|
| 902 | auto-deletion is disabled.
|
---|
| 903 |
|
---|
| 904 | \sa autoDelete(), defaultFactory()
|
---|
| 905 | */
|
---|
| 906 |
|
---|
| 907 | /*!
|
---|
| 908 | \fn bool QIconFactory::autoDelete() const
|
---|
| 909 |
|
---|
| 910 | Returns TRUE if auto-deletion is enabled; otherwise returns FALSE.
|
---|
| 911 |
|
---|
| 912 | \sa setAutoDelete()
|
---|
| 913 | */
|
---|
| 914 |
|
---|
| 915 | /*!
|
---|
| 916 | Returns the default icon factory.
|
---|
| 917 |
|
---|
| 918 | \sa installDefaultFactory()
|
---|
| 919 | */
|
---|
| 920 | QIconFactory *QIconFactory::defaultFactory()
|
---|
| 921 | {
|
---|
| 922 | if ( !defaultFac ) {
|
---|
| 923 | defaultFac = new QIconFactory;
|
---|
| 924 | defaultFac->setAutoDelete( TRUE );
|
---|
| 925 | defaultFac->ref();
|
---|
| 926 | q_cleanup_icon_factory.set( &defaultFac );
|
---|
| 927 | }
|
---|
| 928 | return defaultFac;
|
---|
| 929 | }
|
---|
| 930 |
|
---|
| 931 | /*!
|
---|
| 932 | Replaces the default icon factory with \a factory.
|
---|
| 933 | */
|
---|
| 934 | void QIconFactory::installDefaultFactory( QIconFactory *factory )
|
---|
| 935 | {
|
---|
| 936 | if ( !factory )
|
---|
| 937 | return;
|
---|
| 938 |
|
---|
| 939 | factory->ref();
|
---|
| 940 | if ( defaultFac && defaultFac->deref() && defaultFac->autoDelete() )
|
---|
| 941 | delete defaultFac;
|
---|
| 942 | defaultFac = factory;
|
---|
| 943 | q_cleanup_icon_factory.set( &defaultFac );
|
---|
| 944 | }
|
---|
| 945 |
|
---|
| 946 | #endif // QT_NO_ICONSET
|
---|