2
* iconselect.cpp - class that allows user to select an PsiIcon from an Iconset
3
* Copyright (C) 2003-2005 Michail Pishchagin
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.
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.
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
21
#include "iconselect.h"
23
#include <QApplication>
24
#include <QDesktopWidget>
27
#include <QStyleOption>
29
#include <QAbstractButton>
34
#include <QMouseEvent>
39
#include "psitooltip.h"
41
//----------------------------------------------------------------------------
43
//----------------------------------------------------------------------------
47
\class IconSelectButton
48
\brief This button is used by IconSelect and displays one PsiIcon
50
class IconSelectButton : public QAbstractButton
61
IconSelectButton(QWidget *parent)
62
: QAbstractButton(parent)
66
connect (this, SIGNAL(clicked()), SLOT(iconSelected()));
79
void setIcon(const PsiIcon *i)
89
ic = new PsiIcon(*((PsiIcon *)i));
94
const PsiIcon *icon() const
99
QSize sizeHint() const { return s; }
100
void setSizeHint(QSize sh) { s = sh; }
103
void iconSelected(const PsiIcon *);
104
void textSelected(QString);
107
void aboutToShow() { iconStart(); }
108
void aboutToHide() { iconStop(); }
114
connect(ic, SIGNAL(pixmapChanged()), SLOT(iconUpdated()));
116
ic->activated(false);
120
if ( !ic->text().isEmpty() ) {
121
// first, try to get the text by priorities
123
lang << QString(QTextCodec::locale()).left(2); // most prioritent, is the local language
124
lang << ""; // and then the language without name goes (international?)
125
lang << "en"; // then real English
128
QStringList::Iterator it = lang.begin();
129
for ( ; it != lang.end(); ++it) {
130
QHash<QString, QString>::const_iterator it2 = ic->text().find( *it );
131
if ( it2 != ic->text().end() ) {
137
// if all fails, just get the first text
140
QHashIterator<QString, QString> it ( ic->text() );
141
while ( it.hasNext() ) {
144
if ( !it.value().isEmpty() ) {
151
if ( !str.isEmpty() )
154
// and list of possible variants in the ToolTip
156
foreach ( QString icText, ic->text() ) {
157
if ( !toolTip.isEmpty() )
160
break; // comment this to get list of iconsets
162
if ( toolTip.length() > 30 )
163
toolTip = toolTip.left(30) + "...";
172
disconnect(ic, 0, this, 0 );
180
void enterEvent(QEvent *) { setFocus(); update(); } // focus follows mouse mode
181
void leaveEvent(QEvent *) { clearFocus(); update(); }
193
emit iconSelected(ic);
194
emit textSelected(text);
199
void paintEvent(QPaintEvent *)
202
QFlags<QStyle::StateFlag> flags = QStyle::State_Active | QStyle::State_Enabled;
205
flags |= QStyle::State_Selected;
207
QStyleOptionMenuItem opt;
208
opt.palette = palette();
212
style()->drawControl(QStyle::CE_MenuItem, &opt, &p, this);
215
QPixmap pix = ic->pixmap();
216
p.drawPixmap((width() - pix.width())/2, (height() - pix.height())/2, pix);
222
//----------------------------------------------------------------------------
223
// IconSelect -- the widget that does all dirty work
224
//----------------------------------------------------------------------------
226
class IconSelect : public QWidget
231
IconSelectPopup *menu;
237
IconSelect(IconSelectPopup *parentMenu);
240
void setIconset(const Iconset &);
241
const Iconset &iconset() const;
250
IconSelect::IconSelect(IconSelectPopup *parentMenu)
251
: QWidget(parentMenu)
254
connect(menu, SIGNAL(textSelected(QString)), SLOT(closeMenu()));
260
IconSelect::~IconSelect()
264
void IconSelect::closeMenu()
266
// this way all parent menus (if any) would be closed too
267
QMouseEvent me(QEvent::MouseButtonPress, menu->pos() - QPoint(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
268
menu->mousePressEvent(&me);
274
void IconSelect::noIcons()
276
grid = new QGridLayout(this);
278
QLabel *lbl = new QLabel(this);
279
grid->addWidget(lbl);
280
lbl->setText( tr("No icons available") );
283
void IconSelect::setIconset(const Iconset &iconset)
287
// delete all children
291
QList<QWidget *> list = findChildren<QWidget *>();
293
foreach (object, list)
302
// first we need to find optimal size for elements and don't forget about
303
// taking too much screen space
306
double count; // the 'double' type is somewhat important for MSVC.NET here
307
QListIterator<PsiIcon *> it = is.iterator();
308
for (count = 0; it.hasNext(); count++) {
309
PsiIcon *icon = it.next();
310
w += icon->pixmap().width();
311
h += icon->pixmap().height();
316
const int margin = 2;
317
int tileSize = (int)QMAX(w, h) + 2*margin;
319
QRect r = QApplication::desktop()->availableGeometry( menu );
320
int maxSize = QMIN(r.width(), r.height())*3/4;
322
int size = (int)ceil( sqrt( count ) );
324
if ( size*tileSize > maxSize ) { // too many icons. find reasonable size.
326
for (w = 0; w <= maxSize; w += tileSize)
331
// now, fill grid with elements
332
grid = new QGridLayout(this, size, size);
337
while ( it.hasNext() ) {
338
if ( ++count > size*size )
341
IconSelectButton *b = new IconSelectButton(this);
343
b->setIcon( it.next() );
344
b->setSizeHint( QSize(tileSize, tileSize) );
345
connect (b, SIGNAL(iconSelected(const PsiIcon *)), menu, SIGNAL(iconSelected(const PsiIcon *)));
346
connect (b, SIGNAL(textSelected(QString)), menu, SIGNAL(textSelected(QString)));
348
connect (menu, SIGNAL(aboutToShow()), b, SLOT(aboutToShow()));
349
connect (menu, SIGNAL(aboutToHide()), b, SLOT(aboutToHide()));
353
const Iconset &IconSelect::iconset() const
358
//----------------------------------------------------------------------------
360
//----------------------------------------------------------------------------
362
class IconSelectPopup::Private : public QObject
365
Private(IconSelectPopup *parent)
368
icsel = new IconSelect(parent);
374
IconSelectPopup::IconSelectPopup(QWidget *parent)
377
QGridLayout *grid = new QGridLayout(this);
378
grid->setMargin(style()->pixelMetric(QStyle::PM_MenuPanelWidth, 0, this));
379
grid->setAutoAdd(true);
381
d = new Private(this);
384
IconSelectPopup::~IconSelectPopup()
388
void IconSelectPopup::setIconset(const Iconset &i)
390
d->icsel->setIconset(i);
393
const Iconset &IconSelectPopup::iconset() const
395
return d->icsel->iconset();
399
It's used by child widget to close the menu by simulating a
400
click slightly outside of menu. This seems to be the best way
403
void IconSelectPopup::mousePressEvent(QMouseEvent *e)
405
QMenu::mousePressEvent(e);
409
Override QMenu's nasty sizeHint() and use standard QWidget one
410
which honors layouts and child widgets.
412
QSize IconSelectPopup::sizeHint() const
414
return QWidget::sizeHint();
417
#include "iconselect.moc"