source: psi/trunk/libpsi/psiwidgets/iconaction.cpp@ 59

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

Imported original Psi 0.10 sources from Affinix

File size: 11.9 KB
Line 
1/*
2 * iconaction.cpp - the QAction subclass that uses Icons and supports animation
3 * Copyright (C) 2003-2004 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 "iconaction.h"
22
23#include "iconwidget.h"
24#include "iconset.h"
25
26#include <qlayout.h>
27#include <qpopupmenu.h>
28#include <qtooltip.h>
29#include <qobjectlist.h>
30#include <qtimer.h>
31
32//----------------------------------------------------------------------------
33// IconAction
34//----------------------------------------------------------------------------
35
36class IconAction::Private : public QObject
37{
38 Q_OBJECT
39public:
40 QPtrList<IconToolButton> buttons;
41 QMap<QPopupMenu *, int> popups;
42 Icon *icon;
43 IconAction *action;
44 QPopupMenu *popup;
45
46 Private(IconAction *act) {
47 icon = 0;
48 action = act;
49 popup = 0;
50 }
51
52 QString menuText() {
53 QString txt = action->menuText();
54
55 if ( !action->accel().isEmpty() )
56 txt += '\t' + (QString)action->accel();
57
58 return txt;
59 }
60
61public slots:
62 void menuClicked() {
63 action->setOn( !action->isOn() );
64 emit action->setOn( action->isOn() );
65 emit action->activated(); // required for our lovely status change actions
66 }
67
68 void popupDestroyed( QObject *obj ) {
69 bool dirty = true;
70 while ( dirty ) {
71 dirty = false;
72
73 QMap<QPopupMenu *, int>::Iterator it = popups.begin();
74 for ( ; it != popups.end(); ++it ) {
75 if ( it.key() == obj ) {
76 dirty = true;
77 popups.remove( it );
78 break;
79 }
80 }
81 }
82 }
83};
84
85IconAction::IconAction(QObject *parent, const char *name)
86: QAction(parent, name)
87{
88 d = new Private(this);
89}
90
91IconAction::IconAction(const QString &text, const QString &icon, const QString &menuText, QKeySequence accel, QObject *parent, const char *name, bool toggle)
92: QAction(text, menuText, accel, parent, name, toggle)
93{
94 d = new Private(this);
95
96 setIcon(icon);
97}
98
99IconAction::IconAction(const QString &text, const QString &menuText, QKeySequence accel, QObject *parent, const char *name, bool toggle)
100: QAction(text, menuText, accel, parent, name, toggle)
101{
102 d = new Private(this);
103}
104
105IconAction::~IconAction()
106{
107 // delete the buttons list before our own destruction
108 d->buttons.setAutoDelete(true);
109 d->buttons.clear();
110
111 delete d;
112}
113
114const Icon *IconAction::icon() const
115{
116 return d->icon;
117}
118
119void IconAction::setIcon(const Icon *i)
120{
121 if ( d->icon ) {
122 disconnect(d->icon, 0, this, 0 );
123 d->icon->stop();
124 delete d->icon;
125 d->icon = 0;
126 }
127
128 QIconSet is;
129 if ( i ) {
130 d->icon = new Icon(*i);
131 connect(d->icon, SIGNAL(iconModified(const QPixmap &)), SLOT(iconUpdated(const QPixmap &)));
132 d->icon->activated(true);
133
134 is = d->icon->iconSet();
135 }
136
137 QAction::setIconSet( is );
138
139 for ( QPtrListIterator<IconToolButton> it(d->buttons); it.current(); ++it ) {
140 IconToolButton *btn = it.current();
141 btn->setIcon ( d->icon );
142 }
143
144#ifndef Q_WS_MAC
145 is = QIconSet();
146#endif
147
148 QMap<QPopupMenu *, int>::Iterator it2 = d->popups.begin();
149 for ( ; it2 != d->popups.end(); ++it2 ) {
150 it2.key()->changeItem( it2.data(), iconSet(), d->menuText() );
151 }
152}
153
154void IconAction::setIcon(const QString &name)
155{
156 setIcon( IconsetFactory::iconPtr(name) );
157}
158
159const QString &IconAction::iconName() const
160{
161 if ( d->icon )
162 return d->icon->name();
163 return QString::null;
164}
165
166bool IconAction::addTo(QWidget *w)
167{
168 if ( w->inherits("QToolBar") || w->isA("QWidget") ) {
169 QCString bname = name() + QCString("_action_button");
170 IconToolButton *btn = new IconToolButton ( w, bname );
171 d->buttons.append ( btn );
172
173 btn->setToggleButton ( isToggleAction() );
174 btn->setOn( isOn() );
175 btn->setTextLabel ( text() );
176 btn->setIcon ( d->icon, false );
177 btn->setEnabled ( isEnabled() );
178
179 if ( d->popup )
180 btn->setPopup( d->popup );
181 btn->setPopupDelay (1); // the popup will be displayed immediately
182
183 QToolTip::add (btn, toolTipFromMenuText());
184
185 if ( w->isA("QWidget") )
186 if ( w->layout() )
187 w->layout()->add( btn );
188
189 connect(btn, SIGNAL(clicked()), this, SIGNAL(activated()));
190 connect(btn, SIGNAL(toggled(bool)), this, SLOT(setOn(bool)));
191
192 connect(btn, SIGNAL(destroyed()), SLOT(objectDestroyed()));
193
194 addingToolButton(btn);
195 }
196 else if ( w->inherits("QPopupMenu") ) {
197 //if ( !isVisible() )
198 // return true;
199
200 QPopupMenu *popup = (QPopupMenu *)w;
201 int id;
202 QIconSet iconset;
203#ifndef Q_WS_MAC
204 iconset = iconSet();
205#endif
206 if ( d->popup )
207 id = popup->insertItem (iconset, d->menuText(), d->popup);
208 else
209 id = popup->insertItem (iconset, d->menuText());
210
211 d->popups.insert( popup, id );
212 connect( popup, SIGNAL( destroyed( QObject * ) ), d, SLOT( popupDestroyed( QObject * ) ) );
213
214 popup->setItemEnabled(id, isEnabled());
215 popup->setWhatsThis(id, whatsThis());
216
217 popup->setItemVisible(id, isVisible());
218
219 // will not work for actions with d->popup :-/
220 if ( isToggleAction() ) {
221 popup->setCheckable( true );
222 popup->setItemChecked(id, isOn());
223 popup->connectItem(id, d, SLOT(menuClicked()));
224 }
225 else
226 popup->connectItem(id, this, SIGNAL(activated()));
227
228 addingMenuItem( popup, id );
229 }
230 else
231 return QAction::addTo(w);
232
233 return true;
234}
235
236void IconAction::objectDestroyed()
237{
238 const QObject *obj = sender();
239 d->buttons.removeRef((IconToolButton *)obj);
240}
241
242void IconAction::setOn(bool b)
243{
244 QAction::setOn(b);
245 for ( QPtrListIterator<IconToolButton> it(d->buttons); it.current(); ++it ) {
246 IconToolButton *btn = it.current();
247 btn->setOn(b);
248 }
249
250 QMap<QPopupMenu *, int>::Iterator it2 = d->popups.begin();
251 for ( ; it2 != d->popups.end(); ++it2 ) {
252 it2.key()->setItemChecked( it2.data(), b );
253 }
254}
255
256void IconAction::toolButtonToggled(bool b)
257{
258 setOn(b);
259}
260
261void IconAction::setEnabled(bool e)
262{
263 QAction::setEnabled(e);
264 for ( QPtrListIterator<IconToolButton> it(d->buttons); it.current(); ++it ) {
265 IconToolButton *btn = it.current();
266 btn->setEnabled (e);
267 }
268
269 QMap<QPopupMenu *, int>::Iterator it2 = d->popups.begin();
270 for ( ; it2 != d->popups.end(); ++it2 ) {
271 it2.key()->setItemEnabled( it2.data(), e );
272 }
273}
274
275void IconAction::setText(const QString &t)
276{
277 QAction::setText(t);
278 for ( QPtrListIterator<IconToolButton> it(d->buttons); it.current(); ++it ) {
279 IconToolButton *btn = it.current();
280 btn->setTextLabel(t);
281 }
282
283#ifndef Q_WS_MAC
284 QIconSet is = iconSet();
285#else
286 QIconSet is;
287#endif
288
289 QMap<QPopupMenu *, int>::Iterator it2 = d->popups.begin();
290 for ( ; it2 != d->popups.end(); ++it2 ) {
291 it2.key()->changeItem( it2.data(), is, d->menuText() );
292 }
293}
294
295QPtrList<IconToolButton> IconAction::buttonList()
296{
297 return d->buttons;
298}
299
300void IconAction::iconUpdated(const QPixmap &pix)
301{
302 QAction::setIconSet( d->icon->iconSet() );
303
304#ifndef Q_WS_MAC
305 QPixmap p = pix;
306#else
307 Q_UNUSED( pix );
308 QPixmap p;
309#endif
310
311 QMap<QPopupMenu *, int>::Iterator it2 = d->popups.begin();
312 for ( ; it2 != d->popups.end(); ++it2 ) {
313 it2.key()->changeItem( it2.data(), p, d->menuText() );
314 }
315}
316
317QString IconAction::toolTipFromMenuText() const
318{
319 QString tt, str = menuText();
320 for (int i = 0; i < (int)str.length(); i++)
321 if ( str[i] == '&' && str[i+1] != '&' )
322 continue;
323 else
324 tt += str[i];
325
326 return tt;
327}
328
329QPopupMenu *IconAction::popup() const
330{
331 return d->popup;
332}
333
334void IconAction::setPopup( QPopupMenu *p )
335{
336 d->popup = p;
337
338 QPtrList<IconToolButton> btns = buttonList();
339 for ( QPtrListIterator<IconToolButton> it(btns); it.current(); ++it ) {
340 QToolButton *btn = it.current();
341
342 btn->setPopup (0);
343
344 if ( p )
345 btn->setPopup ( p );
346 }
347}
348
349void IconAction::setIconSet( const QIconSet &ic )
350{
351 QAction::setIconSet( ic );
352
353 QPtrList<IconToolButton> btns = buttonList();
354 for ( QPtrListIterator<IconToolButton> it(btns); it.current(); ++it ) {
355 QToolButton *btn = it.current();
356
357 btn->setIconSet( ic );
358 }
359
360#ifndef Q_WS_MAC
361 QIconSet is = ic;
362#else
363 QIconSet is;
364#endif
365
366 QMap<QPopupMenu *, int>::Iterator it2 = d->popups.begin();
367 for ( ; it2 != d->popups.end(); ++it2 ) {
368 it2.key()->changeItem( it2.data(), is, d->menuText() );
369 }
370}
371
372void IconAction::setVisible( bool b )
373{
374 QAction::setVisible( b );
375
376 QPtrList<IconToolButton> btns = buttonList();
377 for ( QPtrListIterator<IconToolButton> it(btns); it.current(); ++it ) {
378 QToolButton *btn = it.current();
379
380 if ( b )
381 btn->show();
382 else
383 btn->hide();
384 }
385
386 QMap<QPopupMenu *, int>::Iterator it2 = d->popups.begin();
387 for ( ; it2 != d->popups.end(); ++it2 ) {
388 it2.key()->setItemVisible( it2.data(), b );
389 }
390}
391
392IconAction *IconAction::copy() const
393{
394 IconAction *act = new IconAction(text(), iconName(), menuText(), accel(), 0, name(), isToggleAction());
395
396 *act = *this;
397
398 return act;
399}
400
401IconAction &IconAction::operator=( const IconAction &from )
402{
403 setText( from.text() );
404 setIcon( from.iconName() );
405 setMenuText( from.menuText() );
406 setAccel( from.accel() );
407 setName( from.name() );
408 setToggleAction( from.isToggleAction() );
409 setWhatsThis( whatsThis() );
410
411 // TODO: add more
412
413 return *this;
414}
415
416//----------------------------------------------------------------------------
417// IconActionGroup
418//----------------------------------------------------------------------------
419
420class IconActionGroup::Private : public QObject
421{
422 Q_OBJECT
423public:
424 Private(IconActionGroup *_group) {
425 group = _group;
426 dirty = false;
427 }
428
429 IconActionGroup *group;
430
431 QPopupMenu *popup;
432
433 bool exclusive;
434 bool usesDropDown;
435
436 bool dirty;
437
438public slots:
439 void updatePopup();
440};
441
442void IconActionGroup::Private::updatePopup()
443{
444 if ( !dirty )
445 return;
446
447 if ( !usesDropDown )
448 qWarning("IconActionGroup does not support !usesDropDown yet");
449
450 popup->clear();
451
452 QObjectList *l = group->queryList("QAction");
453 QObjectListIt it( *l );
454 QObject *obj;
455 for ( ; (obj = it.current()); ++it) {
456 QAction *action = (QAction *)obj;
457
458 if ( !group->icon() && action->inherits( "IconAction" ) )
459 group->setIcon( ((IconAction * )action)->icon() );
460
461 action->addTo( popup );
462 }
463 delete l;
464
465 group->setPopup( popup );
466 dirty = false;
467}
468
469IconActionGroup::IconActionGroup(QObject *parent, const char *name, bool exclusive)
470 : IconAction( parent, name )
471{
472 d = new Private(this);
473 d->popup = new QPopupMenu();
474
475 d->exclusive = exclusive;
476}
477
478IconActionGroup::~IconActionGroup()
479{
480 delete d->popup;
481 delete d;
482}
483
484void IconActionGroup::insertChild( QObject *obj )
485{
486 IconAction::insertChild( obj );
487
488 d->dirty = true;
489 QTimer::singleShot( 0, d, SLOT( updatePopup() ) );
490}
491
492void IconActionGroup::removeChild( QObject *obj )
493{
494 IconAction::removeChild( obj );
495
496 d->dirty = true;
497 QTimer::singleShot( 0, d, SLOT( updatePopup() ) );
498}
499
500void IconActionGroup::add( QAction * )
501{
502 qWarning("IconActionGroup::add(): not implemented");
503}
504
505void IconActionGroup::addSeparator()
506{
507 QAction *separatorAction = new QAction(this, "qt_separator_action");
508 Q_UNUSED( separatorAction );
509}
510
511bool IconActionGroup::addTo( QWidget *w )
512{
513 if ( w->inherits("QPopupMenu") ) {
514 QPopupMenu *popup = (QPopupMenu *)w;
515
516 QObjectList *l = queryList("QAction");
517 QObjectListIt it( *l );
518 QObject *obj;
519 for ( ; (obj = it.current()); ++it) {
520 QAction *action = (QAction *)obj;
521
522 action->addTo( popup );
523 }
524 delete l;
525
526 return true;
527 }
528
529 return IconAction::addTo( w );
530}
531
532IconAction *IconActionGroup::copy() const
533{
534 qWarning("IconActionGroup::copy() doesn't work!");
535 return (IconAction *)this;
536}
537
538void IconActionGroup::setExclusive( bool e )
539{
540 d->exclusive = e;
541}
542
543bool IconActionGroup::isExclusive() const
544{
545 return d->exclusive;
546}
547
548void IconActionGroup::setUsesDropDown( bool u )
549{
550 d->usesDropDown = u;
551}
552
553bool IconActionGroup::usesDropDown() const
554{
555 return d->usesDropDown;
556}
557
558void IconActionGroup::addingToolButton(IconToolButton *btn)
559{
560 btn->setPopupDelay( 0 );
561}
562
563#include "iconaction.moc"
Note: See TracBrowser for help on using the repository browser.