/* * iconselect.cpp - class that allows user to select an Icon from an Iconset * Copyright (C) 2003 Michail Pishchagin * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "iconselect.h" #include #include #include #include #include #include #include #include #include #include #include #include "iconset.h" //---------------------------------------------------------------------------- // IconSelectButton //---------------------------------------------------------------------------- class IconSelectButton : public QButton { Q_OBJECT private: Icon *ic; QString text; QSize s; bool animated; public: IconSelectButton(QWidget *parent, const char *name = 0) : QButton(parent, name, WRepaintNoErase) { //setFocusPolicy(StrongFocus); ic = 0; animated = false; connect (this, SIGNAL(clicked()), SLOT(iconSelected())); } ~IconSelectButton() { iconStop(); if ( ic ) { delete ic; ic = 0; } } void setIcon(const Icon *i) { iconStop(); if ( ic ) { delete ic; ic = 0; } if ( i ) ic = new Icon(*((Icon *)i)); else ic = 0; } const Icon *icon() const { return ic; } QSize sizeHint() const { return s; } void setSizeHint(QSize sh) { s = sh; } signals: void iconSelected(const Icon *); void textSelected(QString); public slots: void aboutToShow() { iconStart(); } void aboutToHide() { iconStop(); } private: void iconStart() { if ( ic ) { connect(ic, SIGNAL(pixmapChanged(const QPixmap &)), SLOT(iconUpdated(const QPixmap &))); if ( !animated ) { ic->activated(false); animated = true; } if ( !ic->text().isEmpty() ) { // first, try to get the text by priorities QStringList lang; lang << QString(QTextCodec::locale()).left(2); // most prioritent, is the local language lang << ""; // and then the language without name goes (international?) lang << "en"; // then real English QString *str = 0; QStringList::Iterator it = lang.begin(); for ( ; it != lang.end(); ++it) { str = ic->text().find( *it ); if (str) break; } // if all fails, just get the first text if ( !str ) { QDictIterator it ( ic->text() ); for ( ; it.current(); ++it) { if ( it.current() && !it.current()->isEmpty() ) { str = it.current(); break; } } } if ( str ) text = *str; // and list of possible variants in the ToolTip QString toolTip; QDictIterator it2 ( ic->text() ); for ( ; it2.current(); ++it2) { if ( !toolTip.isEmpty() ) toolTip += ", "; toolTip += **it2; break; // comment this to get list of iconsets } if ( toolTip.length() > 30 ) toolTip = toolTip.left(30) + "..."; QToolTip::add(this, toolTip); } } } void iconStop() { if ( ic ) { disconnect(ic, 0, this, 0 ); if ( animated ) { ic->stop(); animated = false; } } } void enterEvent(QEvent *) { setFocus(); } // focus follows mouse mode void leaveEvent(QEvent *) { clearFocus(); } private slots: void iconUpdated(const QPixmap &) { update(); } void iconSelected() { clearFocus(); if ( ic ) { emit iconSelected(ic); emit textSelected(text); parentWidget()->parentWidget()->close(); } } private: void drawButton (QPainter *p) { int flags = QStyle::Style_Enabled; if ( hasFocus() /* && hasMouse()*/ /*|| isDown() || isOn()*/ ) flags |= QStyle::Style_Active; QMenuItem dummy; style().drawControl(QStyle::CE_PopupMenuItem, p, this, rect(), colorGroup(), flags, QStyleOption(&dummy, 0, 0)); if ( ic ) { QPixmap pix = ic->pixmap(); p->drawPixmap((width() - pix.width())/2, (height() - pix.height())/2, pix); } } }; //---------------------------------------------------------------------------- // IconSelect -- the widget that does all dirty work //---------------------------------------------------------------------------- class IconSelect : public QWidget { Q_OBJECT private: Iconset is; QGridLayout *grid; public: IconSelect(QWidget *parent, const char *name = 0); ~IconSelect(); void setIconset(const Iconset &); const Iconset &iconset() const; //bool isFocusEnabled () const { return true; } //void keyPressEvent(QKeyEvent *); /*void paintEvent(QPaintEvent *e) { QWidget *pw = (QWidget *)parent(); if ( !pw || !pw->paletteBackgroundPixmap() ) return; QPainter paint; paint.begin(this); QRect r = rect(); QPixmap pix(r.width(), r.height()); QPainter p; p.begin(&pix); p.drawTiledPixmap (r, *pw->paletteBackgroundPixmap(), mapToParent( r.topLeft() )); //QLabel::drawContents ( &p ); p.end(); paint.drawPixmap (r.topLeft(), pix ); paint.end(); }*/ void noIcons(); }; IconSelect::IconSelect(QWidget *parent, const char *name) : QWidget(parent, name) { grid = 0; noIcons(); setFocus(); } IconSelect::~IconSelect() { } void IconSelect::noIcons() { grid = new QGridLayout(this); grid->setAutoAdd(true); QLabel *lbl = new QLabel(this); lbl->setText( tr("No icons available") ); } void IconSelect::setIconset(const Iconset &iconset) { is = iconset; // delete all children if (grid) { delete grid; QObjectList *l = queryList(); l->setAutoDelete(true); delete l; } if ( !is.count() ) { noIcons(); return; } // first we need to find optimal size for elements and don't forget about // taking too much screen space float w = 0, h = 0; double count; // the 'double' type is somewhat important for MSVC.NET here QPtrListIterator it = is.iterator(); for (count = 0; it.current(); ++it, count++) { w += (*it)->pixmap().width(); h += (*it)->pixmap().height(); } w /= count; h /= count; const int margin = 2; int tileSize = (int)QMAX(w, h) + 2*margin; QRect r = QApplication::desktop()->availableGeometry( this ); int maxSize = QMIN(r.width(), r.height())*3/4; int size = (int)ceil( sqrt( count ) ); if ( size*tileSize > maxSize ) { // too many icons. find reasonable size. int c = 0; for (w = 0; w <= maxSize; w += tileSize) c++; size = c - 1; } // now, fill grid with elements grid = new QGridLayout(this, size, size); grid->setAutoAdd(true); count = 0; it = is.iterator(); for ( ; it.current(); ++it) { if ( ++count > size*size ) break; IconSelectButton *b = new IconSelectButton(this); b->setIcon( *it ); b->setSizeHint( QSize(tileSize, tileSize) ); connect (b, SIGNAL(iconSelected(const Icon *)), parent(), SIGNAL(iconSelected(const Icon *))); connect (b, SIGNAL(textSelected(QString)), parent(), SIGNAL(textSelected(QString))); connect (parent(), SIGNAL(aboutToShow()), b, SLOT(aboutToShow())); connect (parent(), SIGNAL(aboutToHide()), b, SLOT(aboutToHide())); } } const Iconset &IconSelect::iconset() const { return is; } /*void IconSelect::keyPressEvent(QKeyEvent *e) { int it = 0; switch ( e->key() ) { case Key_Tab: it = e->state() & ShiftButton ? -1 : 1; break; case Key_Up: case Key_Left: it = -1; break; case Key_Down: case Key_Right: it = 1; break; default: e->ignore(); } if ( it ) focusNextPrevChild ( it > 0 ); }*/ //---------------------------------------------------------------------------- // IconSelectPopup //---------------------------------------------------------------------------- class IconSelectPopup::Private : public QObject { public: Private(QWidget *parent) : QObject(parent) { icsel = new IconSelect(parent); } IconSelect *icsel; }; IconSelectPopup::IconSelectPopup(QWidget *parent, const char *name) : QPopupMenu(parent, name) { d = new Private(this); insertItem (d->icsel); } IconSelectPopup::~IconSelectPopup() { } void IconSelectPopup::setIconset(const Iconset &i) { d->icsel->setIconset(i); } const Iconset &IconSelectPopup::iconset() const { return d->icsel->iconset(); } #include "iconselect.moc"