source: psi/trunk/libpsi/psiwidgets/iconselect.cpp@ 139

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

Imported original Psi 0.10 sources from Affinix

File size: 8.5 KB
Line 
1/*
2 * iconselect.cpp - class that allows user to select an Icon from an Iconset
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 "iconselect.h"
22
23#include <qapplication.h>
24#include <qdesktopwidget.h>
25#include <qobjectlist.h>
26#include <qpainter.h>
27#include <qstyle.h>
28#include <qlayout.h>
29#include <qbutton.h>
30#include <qlabel.h>
31#include <qtooltip.h>
32#include <qtextcodec.h>
33
34#include <math.h>
35
36#include "iconset.h"
37
38//----------------------------------------------------------------------------
39// IconSelectButton
40//----------------------------------------------------------------------------
41
42class IconSelectButton : public QButton
43{
44 Q_OBJECT
45
46private:
47 Icon *ic;
48 QString text;
49 QSize s;
50 bool animated;
51
52public:
53 IconSelectButton(QWidget *parent, const char *name = 0)
54 : QButton(parent, name, WRepaintNoErase)
55 {
56 //setFocusPolicy(StrongFocus);
57 ic = 0;
58 animated = false;
59 connect (this, SIGNAL(clicked()), SLOT(iconSelected()));
60 }
61
62 ~IconSelectButton()
63 {
64 iconStop();
65
66 if ( ic ) {
67 delete ic;
68 ic = 0;
69 }
70 }
71
72 void setIcon(const Icon *i)
73 {
74 iconStop();
75
76 if ( ic ) {
77 delete ic;
78 ic = 0;
79 }
80
81 if ( i )
82 ic = new Icon(*((Icon *)i));
83 else
84 ic = 0;
85 }
86
87 const Icon *icon() const
88 {
89 return ic;
90 }
91
92 QSize sizeHint() const { return s; }
93 void setSizeHint(QSize sh) { s = sh; }
94
95signals:
96 void iconSelected(const Icon *);
97 void textSelected(QString);
98
99public slots:
100 void aboutToShow() { iconStart(); }
101 void aboutToHide() { iconStop(); }
102
103private:
104 void iconStart()
105 {
106 if ( ic ) {
107 connect(ic, SIGNAL(pixmapChanged(const QPixmap &)), SLOT(iconUpdated(const QPixmap &)));
108 if ( !animated ) {
109 ic->activated(false);
110 animated = true;
111 }
112
113 if ( !ic->text().isEmpty() ) {
114 // first, try to get the text by priorities
115 QStringList lang;
116 lang << QString(QTextCodec::locale()).left(2); // most prioritent, is the local language
117 lang << ""; // and then the language without name goes (international?)
118 lang << "en"; // then real English
119
120 QString *str = 0;
121 QStringList::Iterator it = lang.begin();
122 for ( ; it != lang.end(); ++it) {
123 str = ic->text().find( *it );
124 if (str)
125 break;
126 }
127
128 // if all fails, just get the first text
129 if ( !str )
130 {
131 QDictIterator<QString> it ( ic->text() );
132 for ( ; it.current(); ++it) {
133 if ( it.current() && !it.current()->isEmpty() ) {
134 str = it.current();
135 break;
136 }
137 }
138 }
139
140 if ( str )
141 text = *str;
142
143 // and list of possible variants in the ToolTip
144 QString toolTip;
145 QDictIterator<QString> it2 ( ic->text() );
146 for ( ; it2.current(); ++it2) {
147 if ( !toolTip.isEmpty() )
148 toolTip += ", ";
149 toolTip += **it2;
150 break; // comment this to get list of iconsets
151 }
152 if ( toolTip.length() > 30 )
153 toolTip = toolTip.left(30) + "...";
154 QToolTip::add(this, toolTip);
155 }
156 }
157 }
158
159 void iconStop()
160 {
161 if ( ic ) {
162 disconnect(ic, 0, this, 0 );
163 if ( animated ) {
164 ic->stop();
165 animated = false;
166 }
167 }
168 }
169
170 void enterEvent(QEvent *) { setFocus(); } // focus follows mouse mode
171 void leaveEvent(QEvent *) { clearFocus(); }
172
173private slots:
174 void iconUpdated(const QPixmap &)
175 {
176 update();
177 }
178
179 void iconSelected()
180 {
181 clearFocus();
182 if ( ic ) {
183 emit iconSelected(ic);
184 emit textSelected(text);
185 parentWidget()->parentWidget()->close();
186 }
187 }
188
189private:
190 void drawButton (QPainter *p)
191 {
192 int flags = QStyle::Style_Enabled;
193
194 if ( hasFocus() /* && hasMouse()*/ /*|| isDown() || isOn()*/ )
195 flags |= QStyle::Style_Active;
196
197 QMenuItem dummy;
198 style().drawControl(QStyle::CE_PopupMenuItem, p, this, rect(), colorGroup(),
199 flags, QStyleOption(&dummy, 0, 0));
200
201 if ( ic ) {
202 QPixmap pix = ic->pixmap();
203 p->drawPixmap((width() - pix.width())/2, (height() - pix.height())/2, pix);
204 }
205 }
206};
207
208//----------------------------------------------------------------------------
209// IconSelect -- the widget that does all dirty work
210//----------------------------------------------------------------------------
211
212class IconSelect : public QWidget
213{
214 Q_OBJECT
215
216private:
217 Iconset is;
218 QGridLayout *grid;
219
220public:
221 IconSelect(QWidget *parent, const char *name = 0);
222 ~IconSelect();
223
224 void setIconset(const Iconset &);
225 const Iconset &iconset() const;
226
227 //bool isFocusEnabled () const { return true; }
228 //void keyPressEvent(QKeyEvent *);
229
230 /*void paintEvent(QPaintEvent *e)
231 {
232 QWidget *pw = (QWidget *)parent();
233 if ( !pw || !pw->paletteBackgroundPixmap() )
234 return;
235
236 QPainter paint;
237 paint.begin(this);
238
239 QRect r = rect();
240 QPixmap pix(r.width(), r.height());
241 QPainter p;
242 p.begin(&pix);
243 p.drawTiledPixmap (r, *pw->paletteBackgroundPixmap(), mapToParent( r.topLeft() ));
244 //QLabel::drawContents ( &p );
245 p.end();
246
247 paint.drawPixmap (r.topLeft(), pix );
248
249 paint.end();
250 }*/
251
252 void noIcons();
253};
254
255IconSelect::IconSelect(QWidget *parent, const char *name)
256: QWidget(parent, name)
257{
258 grid = 0;
259 noIcons();
260 setFocus();
261}
262
263IconSelect::~IconSelect()
264{
265}
266
267void IconSelect::noIcons()
268{
269 grid = new QGridLayout(this);
270 grid->setAutoAdd(true);
271
272 QLabel *lbl = new QLabel(this);
273 lbl->setText( tr("No icons available") );
274}
275
276void IconSelect::setIconset(const Iconset &iconset)
277{
278 is = iconset;
279
280 // delete all children
281 if (grid) {
282 delete grid;
283
284 QObjectList *l = queryList();
285 l->setAutoDelete(true);
286 delete l;
287 }
288
289 if ( !is.count() ) {
290 noIcons();
291 return;
292 }
293
294 // first we need to find optimal size for elements and don't forget about
295 // taking too much screen space
296 float w = 0, h = 0;
297
298 double count; // the 'double' type is somewhat important for MSVC.NET here
299 QPtrListIterator<Icon> it = is.iterator();
300 for (count = 0; it.current(); ++it, count++) {
301 w += (*it)->pixmap().width();
302 h += (*it)->pixmap().height();
303 }
304 w /= count;
305 h /= count;
306
307 const int margin = 2;
308 int tileSize = (int)QMAX(w, h) + 2*margin;
309
310 QRect r = QApplication::desktop()->availableGeometry( this );
311 int maxSize = QMIN(r.width(), r.height())*3/4;
312
313 int size = (int)ceil( sqrt( count ) );
314
315 if ( size*tileSize > maxSize ) { // too many icons. find reasonable size.
316 int c = 0;
317 for (w = 0; w <= maxSize; w += tileSize)
318 c++;
319 size = c - 1;
320 }
321
322 // now, fill grid with elements
323 grid = new QGridLayout(this, size, size);
324 grid->setAutoAdd(true);
325
326 count = 0;
327
328 it = is.iterator();
329 for ( ; it.current(); ++it) {
330 if ( ++count > size*size )
331 break;
332
333 IconSelectButton *b = new IconSelectButton(this);
334 b->setIcon( *it );
335 b->setSizeHint( QSize(tileSize, tileSize) );
336 connect (b, SIGNAL(iconSelected(const Icon *)), parent(), SIGNAL(iconSelected(const Icon *)));
337 connect (b, SIGNAL(textSelected(QString)), parent(), SIGNAL(textSelected(QString)));
338
339 connect (parent(), SIGNAL(aboutToShow()), b, SLOT(aboutToShow()));
340 connect (parent(), SIGNAL(aboutToHide()), b, SLOT(aboutToHide()));
341 }
342}
343
344const Iconset &IconSelect::iconset() const
345{
346 return is;
347}
348
349/*void IconSelect::keyPressEvent(QKeyEvent *e)
350{
351 int it = 0;
352 switch ( e->key() ) {
353 case Key_Tab:
354 it = e->state() & ShiftButton ? -1 : 1;
355 break;
356
357 case Key_Up:
358 case Key_Left:
359 it = -1;
360 break;
361
362 case Key_Down:
363 case Key_Right:
364 it = 1;
365 break;
366
367 default:
368 e->ignore();
369 }
370
371 if ( it )
372 focusNextPrevChild ( it > 0 );
373}*/
374
375//----------------------------------------------------------------------------
376// IconSelectPopup
377//----------------------------------------------------------------------------
378
379class IconSelectPopup::Private : public QObject
380{
381public:
382 Private(QWidget *parent)
383 : QObject(parent)
384 {
385 icsel = new IconSelect(parent);
386 }
387
388 IconSelect *icsel;
389};
390
391IconSelectPopup::IconSelectPopup(QWidget *parent, const char *name)
392: QPopupMenu(parent, name)
393{
394 d = new Private(this);
395
396 insertItem (d->icsel);
397}
398
399IconSelectPopup::~IconSelectPopup()
400{
401}
402
403void IconSelectPopup::setIconset(const Iconset &i)
404{
405 d->icsel->setIconset(i);
406}
407
408const Iconset &IconSelectPopup::iconset() const
409{
410 return d->icsel->iconset();
411}
412
413#include "iconselect.moc"
Note: See TracBrowser for help on using the repository browser.