source: psi/trunk/libpsi/psiwidgets/iconwidget.cpp@ 151

Last change on this file since 151 was 2, checked in by dmik, 19 years ago

Imported original Psi 0.10 sources from Affinix

File size: 15.3 KB
Line 
1/*
2 * iconwidget.cpp - misc. Iconset- and Icon-aware widgets
3 * Copyright (C) 2003 Michail Pishchagin
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 */
20
21#include "iconwidget.h"
22
23#include <qapplication.h>
24#include <qpainter.h>
25
26#ifndef WIDGET_PLUGIN
27# include "iconset.h"
28# include <qstyle.h>
29# include <qbitmap.h>
30# include <qmap.h>
31#else
32# include <qimage.h>
33
34static const char *cancel_xpm[] = {
35"22 22 60 1",
36" c None",
37". c #E84300",
38"+ c #E63F00",
39"@ c #D11E00",
40"# c #D11B00",
41"$ c #F69D50",
42"% c #F59A4D",
43"& c #E23800",
44"* c #EE5F1F",
45"= c #ED5A1D",
46"- c #CD1700",
47"; c #FECBA2",
48"> c #FEC69A",
49", c #F39045",
50"' c #DE3200",
51") c #FE7B3C",
52"! c #FE7234",
53"~ c #EC4C15",
54"{ c #CC1100",
55"] c #FEC091",
56"^ c #FEBA89",
57"/ c #F2873D",
58"( c #DA2C00",
59"_ c #FE692C",
60": c #EB4712",
61"< c #CA0F00",
62"[ c #FEB480",
63"} c #FEAE78",
64"| c #F07D35",
65"1 c #D62600",
66"2 c #FEA870",
67"3 c #FEA166",
68"4 c #EF722D",
69"5 c #D32100",
70"6 c #FE9B5F",
71"7 c #FE9356",
72"8 c #F16C2A",
73"9 c #F16525",
74"0 c #FE8B4D",
75"a c #FE8445",
76"b c #EE4B15",
77"c c #FE6025",
78"d c #EE4310",
79"e c #C90E00",
80"f c #FE561D",
81"g c #FE4B16",
82"h c #EA2F08",
83"i c #C70900",
84"j c #FE4010",
85"k c #FE350B",
86"l c #EA1D03",
87"m c #C60700",
88"n c #FE2906",
89"o c #FE1A02",
90"p c #E90900",
91"q c #C50300",
92"r c #FE0A00",
93"s c #FE0000",
94"t c #E90000",
95"u c #C40000",
96" ",
97" ",
98" .+ @# ",
99" .$%& @*=- ",
100" .$;>,' @*)!~{ ",
101" +%>]^/( @*)!_:< ",
102" &,^[}|1 @*)!_:< ",
103" '/}2345@*)!_:< ",
104" (|36789)!_:< ",
105" 1470a)!_:< ",
106" 58a)!_b< ",
107" @9)!_cde ",
108" @*)!_cfghi ",
109" @*)!_bdgjklm ",
110" @*)!_:<ehknopq ",
111" @*)!_:< ilorstu ",
112" @*)!_:< mpssstu ",
113" #=!_:< qtsstu ",
114" -~:< uttu ",
115" {< uu ",
116" ",
117" "};
118
119// dammit MSVC6
120class Iconset {
121public:
122 Iconset() { }
123};
124#endif
125
126//----------------------------------------------------------------------------
127// IconsetSelect
128//----------------------------------------------------------------------------
129
130class IconsetSelectItem : public IconWidgetItem
131{
132 Q_OBJECT
133private:
134 static const int margin;
135 static const int displayNumIcons;
136#ifndef WIDGET_PLUGIN
137 Iconset iss;
138 QMap<Icon*, QRect> iconRects;
139#endif
140 int w, h;
141 mutable int fullW, fullH;
142
143public:
144 IconsetSelectItem(QListBox *parent, IconsetSelectItem *after, const Iconset &_iconset)
145 : IconWidgetItem(parent, after)
146 {
147#ifndef WIDGET_PLUGIN
148 iss = _iconset;
149 setText( iss.name() );
150
151 w = margin;
152 h = 2*margin;
153
154 int count;
155
156 QPtrListIterator<Icon> it = iss.iterator();
157 for (count = 0; it.current(); ++it) {
158 if ( count++ >= displayNumIcons )
159 break; // display only first displayNumIcons icons
160
161 QPixmap pix = it.current()->pixmap();
162
163 iconRects[it.current()] = QRect( w, margin, pix.width(), pix.height() );
164
165 w += pix.width() + margin;
166 h = QMAX( h, pix.height() + 2*margin );
167
168 connect (it.current(), SIGNAL(pixmapChanged(const QPixmap &)), SLOT(iconUpdated(const QPixmap &)));
169 it.current()->activated(false); // start animation
170 }
171
172 QMap<Icon*, QRect>::Iterator it2;
173 for (it2 = iconRects.begin(); it2 != iconRects.end(); it2++) {
174 QRect r = it2.data();
175 it2.data() = QRect( r.x(), (h - r.height())/2, r.width(), r.height() );
176 }
177#else
178 Q_UNUSED( _iconset );
179#endif
180 }
181
182 ~IconsetSelectItem()
183 {
184#ifndef WIDGET_PLUGIN
185 QMap<Icon*, QRect>::Iterator it;
186 for (it = iconRects.begin(); it != iconRects.end(); it++)
187 it.key()->stop();
188#endif
189 }
190
191 const Iconset *iconset() const
192 {
193#ifndef WIDGET_PLUGIN
194 return &iss;
195#else
196 return 0;
197#endif
198 }
199
200 int height( const QListBox *lb ) const
201 {
202 fullH = lb->fontMetrics().lineSpacing() + 2 + h;
203 return QMAX( fullH, QApplication::globalStrut().height() );
204 }
205
206 int width( const QListBox *lb ) const
207 {
208 fullW = QMAX(lb->fontMetrics().width( text() ) + 6, w + 10);
209 return QMAX( fullW, QApplication::globalStrut().width() );
210 }
211
212 void paint(QPainter *painter)
213 {
214#ifndef WIDGET_PLUGIN
215 QFontMetrics fm = painter->fontMetrics();
216 painter->drawText( 3, fm.ascent() + (fm.leading()+1)/2 + 1, text() );
217
218 QMap<Icon*, QRect>::Iterator it;
219 for (it = iconRects.begin(); it != iconRects.end(); it++) {
220 Icon *icon = it.key();
221 QRect r = it.data();
222 painter->drawPixmap(QPoint(10 + r.left(), fm.lineSpacing() + 2 + r.top()), icon->pixmap());
223 }
224#else
225 Q_UNUSED(painter);
226#endif
227 }
228
229private slots:
230 void iconUpdated(const QPixmap &)
231 {
232#ifndef WIDGET_PLUGIN
233 IconsetSelect *issel = (IconsetSelect *)listBox();
234 issel->updateItem (this);
235#endif
236 }
237};
238const int IconsetSelectItem::margin = 3;
239const int IconsetSelectItem::displayNumIcons = 10;
240
241class IconsetSelect::Private
242{
243public:
244 Private()
245 {
246 lastItem = 0;
247 }
248
249 IconsetSelectItem *lastItem;
250};
251
252IconsetSelect::IconsetSelect(QWidget *parent, const char *name)
253: QListBox(parent, name)
254{
255 d = new Private;
256}
257
258IconsetSelect::~IconsetSelect()
259{
260 delete d;
261}
262
263void IconsetSelect::insert(const Iconset &iconset)
264{
265#ifndef WIDGET_PLUGIN
266 IconsetSelectItem *item = new IconsetSelectItem(this, d->lastItem, iconset);
267 d->lastItem = item;
268#else
269 Q_UNUSED(iconset);
270#endif
271}
272
273void IconsetSelect::moveItemUp()
274{
275 if ( currentItem() < 1 )
276 return;
277
278 IconsetSelectItem *i = (IconsetSelectItem *)item(currentItem());
279 if ( !i )
280 return;
281 QListBoxItem *prev = i->prev()->prev();
282 takeItem (i);
283 insertItem (i, prev);
284 setSelected (i, true);
285 setCurrentItem (i);
286}
287
288void IconsetSelect::moveItemDown()
289{
290 if ( currentItem() == -1 || currentItem() > (int)count() - 2 )
291 return;
292
293 IconsetSelectItem *i = (IconsetSelectItem *)item(currentItem());
294 if ( !i )
295 return;
296 QListBoxItem *next = i->next();
297 takeItem (i);
298 insertItem (i, next);
299 setCurrentItem (i);
300}
301
302const Iconset *IconsetSelect::iconset() const
303{
304 IconsetSelectItem *i = (IconsetSelectItem *)selectedItem();
305 if ( !i )
306 i = (IconsetSelectItem *)item(currentItem());
307 if ( i )
308 return i->iconset();
309 return 0;
310}
311
312void IconsetSelect::paintCell(QPainter *p, int row, int col)
313{
314 // we'll do some caching to avoid flicker
315 QListBoxItem *item = QListBox::item(row);
316
317 if ( !item ) {
318 QListBox::paintCell(p, row, col);
319 return;
320 }
321
322 int w = contentsWidth();
323 int h = item->height(this);
324 QPixmap pix(w, h);
325 QPainter p2;
326 p2.begin (&pix);
327 QListBox::paintCell(&p2, row, col);
328 p2.end ();
329
330 p->drawPixmap(QPoint(0, 0), pix);
331}
332
333
334//----------------------------------------------------------------------------
335// IconsetDisplay
336//----------------------------------------------------------------------------
337
338class IconsetDisplayItem : public IconWidgetItem
339{
340 Q_OBJECT
341private:
342 static const int margin;
343 Icon *icon;
344 int w, h;
345
346public:
347 IconsetDisplayItem(QListBox *parent, IconsetDisplayItem *after, Icon *i, int iconW)
348 : IconWidgetItem(parent, after)
349 {
350#ifndef WIDGET_PLUGIN
351 icon = i;
352 w = iconW;
353
354 connect (icon, SIGNAL(pixmapChanged(const QPixmap &)), SLOT(iconUpdated(const QPixmap &)));
355 icon->activated(false);
356
357 h = icon->pixmap().height();
358
359 QString str;
360 QDictIterator<QString> it ( icon->text() );
361 for ( ; it.current(); ++it) {
362 if ( !str.isEmpty() )
363 str += ", ";
364 str += **it;
365 }
366 if ( !str.isEmpty() )
367 setText(str);
368 else
369 setText(tr("Name: '%1'").arg(icon->name()));
370#else
371 Q_UNUSED( i );
372 Q_UNUSED( iconW );
373#endif
374 }
375
376 ~IconsetDisplayItem()
377 {
378#ifndef WIDGET_PLUGIN
379 icon->stop();
380#endif
381 }
382
383 int height( const QListBox *lb ) const
384 {
385 int hh = QMAX(h + 2*margin, lb->fontMetrics().lineSpacing() + 2);
386 return QMAX( hh, QApplication::globalStrut().height() );
387 }
388
389 int width( const QListBox *lb ) const
390 {
391 int ww = lb->fontMetrics().width( text() ) + 6 + w + 2*margin;
392 return QMAX( ww, QApplication::globalStrut().width() );
393 }
394
395 void paint(QPainter *painter)
396 {
397#ifndef WIDGET_PLUGIN
398 painter->drawPixmap(QPoint((2*margin+w - icon->pixmap().width())/2, margin), icon->pixmap());
399 QFontMetrics fm = painter->fontMetrics();
400 //int hh = QMAX(h + 2*margin, fm.lineSpacing() + 2);
401 painter->drawText( w + 2*margin + 3, fm.ascent() + (fm.leading()+1)/2 + 1, text() );
402 //painter->drawText( w + 2*margin + 3, (hh - fm.lineSpacing())/2, text() );
403#else
404 Q_UNUSED(painter);
405#endif
406 }
407
408private slots:
409 void iconUpdated(const QPixmap &)
410 {
411 IconsetDisplay *issel = (IconsetDisplay *)listBox();
412 issel->updateItem (this);
413 }
414};
415const int IconsetDisplayItem::margin = 3;
416
417class IconsetDisplay::Private
418{
419public:
420 Private()
421 {
422 lastItem = 0;
423 }
424
425 IconsetDisplayItem *lastItem;
426};
427
428IconsetDisplay::IconsetDisplay(QWidget *parent, const char *name)
429: QListBox(parent, name, WStaticContents | WResizeNoErase | WRepaintNoErase)
430{
431 d = new Private;
432}
433
434IconsetDisplay::~IconsetDisplay()
435{
436 delete d;
437}
438
439void IconsetDisplay::setIconset(const Iconset &iconset)
440{
441#ifndef WIDGET_PLUGIN
442 int w = 0;
443 QPtrListIterator<Icon> it = iconset.iterator();
444 for ( ; it.current(); ++it) {
445 w = QMAX(w, it.current()->pixmap().width());
446 }
447
448 it = iconset.iterator();
449 for ( ; it.current(); ++it) {
450 IconsetDisplayItem *item = new IconsetDisplayItem(this, d->lastItem, it.current(), w);
451 d->lastItem = item;
452 }
453#else
454 Q_UNUSED(iconset);
455#endif
456}
457
458void IconsetDisplay::paintCell(QPainter *p, int row, int col)
459{
460 // we'll do some caching to avoid flicker
461 QListBoxItem *item = QListBox::item(row);
462
463 if ( !item ) {
464 QListBox::paintCell(p, row, col);
465 return;
466 }
467
468 int w = contentsWidth();
469 int h = item->height(this);
470 QPixmap pix(w, h);
471 QPainter p2;
472 p2.begin (&pix);
473 QListBox::paintCell(&p2, row, col);
474 p2.end ();
475
476 p->drawPixmap(QPoint(0, 0), pix);
477}
478
479
480//----------------------------------------------------------------------------
481// IconButton
482//----------------------------------------------------------------------------
483
484class IconButton::Private : public QObject
485{
486 Q_OBJECT
487public:
488 Icon *icon;
489 IconButton *button;
490 bool textVisible;
491 bool activate, forced;
492#ifdef WIDGET_PLUGIN
493 QString iconName;
494#endif
495
496public:
497 Private(IconButton *b)
498 {
499 icon = 0;
500 button = b;
501 textVisible = true;
502 forced = false;
503 }
504
505 ~Private()
506 {
507 iconStop();
508 }
509
510 void setIcon(Icon *i)
511 {
512#ifndef WIDGET_PLUGIN
513 iconStop();
514 if ( i )
515 icon = new Icon(*i);
516 iconStart();
517#else
518 Q_UNUSED(i);
519#endif
520 }
521
522 void iconStart()
523 {
524#ifndef WIDGET_PLUGIN
525 if ( icon ) {
526 connect(icon, SIGNAL(pixmapChanged(const QPixmap &)), SLOT(iconUpdated(const QPixmap &)));
527 if ( activate )
528 icon->activated(true); // FIXME: should icon play sound when it's activated on button?
529 }
530
531 updateIcon();
532#endif
533 }
534
535 void iconStop()
536 {
537#ifndef WIDGET_PLUGIN
538 if ( icon ) {
539 disconnect(icon, 0, this, 0 );
540 if ( activate )
541 icon->stop();
542
543 delete icon;
544 icon = 0;
545 }
546#endif
547 }
548
549 void update()
550 {
551#ifndef WIDGET_PLUGIN
552 if ( icon )
553 iconUpdated( icon->pixmap() );
554#endif
555 }
556
557 void updateIcon()
558 {
559#ifndef WIDGET_PLUGIN
560 if ( icon )
561 iconUpdated( icon->pixmap() );
562 else
563 iconUpdated( QPixmap() );
564#endif
565 }
566
567public slots:
568 void iconUpdated(const QPixmap &pix)
569 {
570 button->setUpdatesEnabled(FALSE);
571 if ( textVisible || button->text().isEmpty() )
572 button->setIconSet(pix);
573 else
574 button->setPixmap(pix);
575 button->setUpdatesEnabled(TRUE);
576 button->update();
577 }
578};
579
580IconButton::IconButton(QWidget *parent, const char *name)
581: QPushButton(parent, name)
582{
583 setWFlags(getWFlags() | WRepaintNoErase); // no nasty flicker anymore :)
584 d = new Private(this);
585}
586
587IconButton::~IconButton()
588{
589 delete d;
590}
591
592void IconButton::setIcon(const QPixmap &p)
593{
594 QPushButton::setIcon(p);
595}
596
597void IconButton::forceSetIcon(const Icon *i, bool activate)
598{
599 d->activate = activate;
600 d->setIcon ((Icon *)i);
601 d->forced = true;
602}
603
604void IconButton::setIcon(const Icon *i, bool activate)
605{
606#ifndef Q_WS_X11
607 if ( !text().isEmpty() )
608 return;
609#endif
610
611 forceSetIcon(i, activate);
612 d->forced = false;
613}
614
615void IconButton::setIcon(const QString &name)
616{
617#ifndef WIDGET_PLUGIN
618 setIcon( IconsetFactory::iconPtr(name) );
619#else
620 d->iconName = name;
621
622 if ( !name.isEmpty() ) {
623 QPixmap pix((const char **)cancel_xpm);
624 d->iconUpdated(QPixmap( pix ));
625 }
626 else
627 d->iconUpdated(QPixmap());
628#endif
629}
630
631const QString &IconButton::iconName() const
632{
633#ifndef WIDGET_PLUGIN
634 if ( d->icon )
635 return d->icon->name();
636 return QString::null;
637#else
638 return d->iconName;
639#endif
640}
641
642void IconButton::setText(const QString &text)
643{
644#ifndef Q_WS_X11
645 if ( !d->forced )
646 setIcon(0);
647#endif
648
649 QPushButton::setText( text );
650 d->updateIcon();
651}
652
653bool IconButton::textVisible() const
654{
655 return d->textVisible;
656}
657
658void IconButton::setTextVisible(bool v)
659{
660 d->textVisible = v;
661 d->updateIcon();
662}
663
664void IconButton::drawButtonLabel(QPainter *p)
665{
666 QPushButton::drawButtonLabel(p);
667}
668
669//----------------------------------------------------------------------------
670// IconToolButton
671//----------------------------------------------------------------------------
672
673class IconToolButton::Private : public QObject
674{
675 Q_OBJECT
676public:
677 Icon *icon;
678 IconToolButton *button;
679 bool activate;
680#ifdef WIDGET_PLUGIN
681 QString iconName;
682#endif
683
684public:
685 Private(IconToolButton *b)
686 {
687 icon = 0;
688 button = b;
689 }
690
691 ~Private()
692 {
693 iconStop();
694 }
695
696 void setIcon(Icon *i)
697 {
698#ifndef WIDGET_PLUGIN
699 iconStop();
700 if ( i )
701 icon = new Icon(*i);
702 iconStart();
703#else
704 Q_UNUSED(i);
705#endif
706 }
707
708 void iconStart()
709 {
710#ifndef WIDGET_PLUGIN
711 if ( icon ) {
712 connect(icon, SIGNAL(pixmapChanged(const QPixmap &)), SLOT(iconUpdated(const QPixmap &)));
713 if ( activate )
714 icon->activated(true); // FIXME: should icon play sound when it's activated on button?
715 iconUpdated( icon->pixmap() );
716 }
717 else
718 iconUpdated( QPixmap() );
719#endif
720 }
721
722 void iconStop()
723 {
724#ifndef WIDGET_PLUGIN
725 if ( icon ) {
726 disconnect(icon, 0, this, 0 );
727 if ( activate )
728 icon->stop();
729
730 delete icon;
731 icon = 0;
732 }
733#endif
734 }
735
736 void update()
737 {
738#ifndef WIDGET_PLUGIN
739 if ( icon )
740 iconUpdated( icon->pixmap() );
741#endif
742 }
743
744private slots:
745 void iconUpdated(const QPixmap &pix)
746 {
747 button->setUpdatesEnabled(FALSE);
748 //if ( textVisible )
749 button->setIconSet(pix);
750 //else
751 // button->setPixmap(pix);
752 button->setUpdatesEnabled(TRUE);
753 button->update();
754 }
755};
756
757IconToolButton::IconToolButton(QWidget *parent, const char *name)
758: QToolButton(parent, name)
759{
760 setWFlags(getWFlags() | WRepaintNoErase);
761 d = new Private(this);
762}
763
764IconToolButton::~IconToolButton()
765{
766 delete d;
767}
768
769void IconToolButton::setIcon(const QPixmap &p)
770{
771 QToolButton::setIcon(p);
772}
773
774void IconToolButton::setIcon(const Icon *i, bool activate)
775{
776 d->activate = activate;
777 d->setIcon ((Icon *)i);
778}
779
780void IconToolButton::setIcon(const QString &name)
781{
782#ifndef WIDGET_PLUGIN
783 setIcon( IconsetFactory::iconPtr(name) );
784#else
785 d->iconName = name;
786#endif
787}
788
789const QString &IconToolButton::iconName() const
790{
791#ifndef WIDGET_PLUGIN
792 if ( d->icon )
793 return d->icon->name();
794 return QString::null;
795#else
796 return d->iconName;
797#endif
798}
799
800void IconToolButton::drawButtonLabel(QPainter *p)
801{
802 QToolButton::drawButtonLabel(p);
803}
804
805#include "iconwidget.moc"
Note: See TracBrowser for help on using the repository browser.