1 | /****************************************************************************
|
---|
2 | ** $Id: qiconset.cpp 2 2005-11-16 15:49:26Z 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 |
|
---|
829 | QPainter painter;
|
---|
830 | painter.begin( pixmap );
|
---|
831 | painter.setPen( dis.base() );
|
---|
832 | painter.drawPixmap( 1, 1, normalMask );
|
---|
833 | painter.setPen( dis.foreground() );
|
---|
834 | painter.drawPixmap( 0, 0, normalMask );
|
---|
835 | painter.end();
|
---|
836 |
|
---|
837 | if ( !normalMask.mask() )
|
---|
838 | normalMask.setMask( normalMask );
|
---|
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
|
---|