lib Library API Documentation

koIconChooser.cc

00001 /* This file is part of the KDE project
00002   Copyright (c) 1999 Carsten Pfeiffer (pfeiffer@kde.org)
00003   Copyright (c) 2002 Igor Jansen (rm@kde.org)
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018    Boston, MA 02111-1307, USA.
00019 */
00020 
00021 #include <kdebug.h>
00022 #include <koIconChooser.h>
00023 #include <kglobal.h>
00024 
00025 #include <qpainter.h>
00026 #include <qcursor.h>
00027 #include <qapplication.h>
00028 #include <qhbox.h>
00029 #include <qlayout.h>
00030 #include <kdebug.h>
00031 
00032 KoPixmapWidget::KoPixmapWidget(const QPixmap &aPixmap, QWidget *parent, const char *name):
00033 QFrame(parent, name, WStyle_Customize | WStyle_NoBorder | WType_Dialog)
00034 {
00035   setFrameStyle(QFrame::WinPanel | QFrame::Raised);
00036   mPixmap = aPixmap;
00037   int w = mPixmap.width() + 2 * lineWidth();
00038   int h = mPixmap.height() + 2 * lineWidth();
00039   resize(w, h);
00040 
00041   // center widget under mouse cursor
00042   QPoint p = QCursor::pos();
00043   move(p.x() - w / 2, p.y() - h / 2);
00044   show();
00045 }
00046 
00047 KoPixmapWidget::~KoPixmapWidget()
00048 {
00049 }
00050 
00051 // paint the centered pixmap; don't overpaint the frame
00052 void KoPixmapWidget::paintEvent(QPaintEvent *e)
00053 {
00054   QFrame::paintEvent(e);
00055   QPainter p(this);
00056   p.setClipRect(e->rect());
00057   p.drawPixmap(lineWidth(), lineWidth(), mPixmap);
00058 }
00059 
00060 
00061 
00062 KoIconChooser::KoIconChooser(QSize aIconSize, QWidget *parent, const char *name, bool sort):
00063 QGridView(parent, name)
00064 {
00065   QGridView::setBackgroundColor(Qt::white);
00066 
00067   mMargin = 2;
00068   setCellWidth(aIconSize.width() + 2 * mMargin);
00069   setCellHeight(aIconSize.height() + 2 * mMargin);
00070 
00071   mIconList.clear();
00072   mPixmapWidget = 0L;
00073   mNCols = 0;
00074   mCurRow = 0;
00075   mCurCol = 0;
00076   mItemCount = 0;
00077   mItemWidth = aIconSize.width();
00078   mItemHeight = aIconSize.height();
00079   mMouseButtonDown = false;
00080   mDragEnabled = false;
00081   mSort = sort;
00082 }
00083 
00084 KoIconChooser::~KoIconChooser()
00085 {
00086   mIconList.clear();
00087   if(mPixmapWidget)
00088     delete mPixmapWidget;
00089 }
00090 
00091 void KoIconChooser::addItem(KoIconItem *item)
00092 {
00093   Q_INT32 n = mItemCount;
00094   KoIconItem *current = currentItem();
00095 
00096   Q_ASSERT(item);
00097 
00098   int i;
00099 
00100   if (mSort)
00101   {
00102     i = sortInsertionIndex(item);
00103   }
00104   else
00105   {
00106     i = mItemCount;
00107   }
00108 
00109   mIconList.insert(i, item);
00110   mItemCount++;
00111   calculateCells();
00112 
00113   if (mSort)
00114   {
00115     setCurrentItem(current);
00116     updateContents();
00117   }
00118   else
00119   {
00120     updateCell(n / numCols(), n - (n / numCols()) * numCols());
00121   }
00122 }
00123 
00124 bool KoIconChooser::removeItem(KoIconItem *item)
00125 {
00126   int index = mIconList.find(item);
00127   bool ok = mIconList.remove(item);
00128   if( ok )
00129   {
00130     mItemCount--;
00131     // select same cell as deleted cell, or new last cell if we deleted
00132     // last cell.
00133     setCurrentItem(itemAt(kMin(index, mItemCount - 1)));
00134     calculateCells();
00135   }
00136   return ok;
00137 }
00138 
00139 void KoIconChooser::clear()
00140 {
00141   mItemCount = 0;
00142   mIconList.clear();
00143   calculateCells();
00144 }
00145 
00146 // return 0L if there is no current item
00147 KoIconItem *KoIconChooser::currentItem()
00148 {
00149   return itemAt(mCurRow, mCurCol);
00150 }
00151 
00152 // sets the current item to item
00153 // does NOT emit selected()  (should it?)
00154 void KoIconChooser::setCurrentItem(KoIconItem *item)
00155 {
00156   int index = mIconList.find(item);
00157 
00158   // item is available
00159   if(index != -1 && mNCols > 0)
00160   {
00161     int oldRow = mCurRow;
00162     int oldCol = mCurCol;
00163 
00164     mCurRow = index / mNCols;
00165     mCurCol = index % mNCols;
00166 
00167     // repaint the old and the new item
00168     repaintCell(oldRow, oldCol);
00169     repaintCell(mCurRow, mCurCol);
00170 
00171     ensureCellVisible(mCurRow, mCurCol);
00172   }
00173 }
00174 
00175 // eventually select the item, clicked on
00176 void KoIconChooser::mousePressEvent(QMouseEvent *e)
00177 {
00178   QGridView::mousePressEvent(e);
00179   mMouseButtonDown = true;
00180   if(e->button() == LeftButton)
00181   {
00182     QPoint p = e->pos();
00183     mDragStartPos = p;
00184     int x = contentsX() + p.x();
00185     int y = contentsY() + p.y();
00186     QSize gridExtent = gridSize();
00187 
00188     if (x < gridExtent.width() && y < gridExtent.height())
00189     {
00190       int row = rowAt(y);
00191       int col = columnAt(x);
00192 
00193       KoIconItem *item = itemAt(row, col);
00194       if(item)
00195       {
00196         const QPixmap &pix = item->pixmap();
00197         if(pix.width() > mItemWidth || pix.height() > mItemHeight)
00198           showFullPixmap(pix, p);
00199 
00200         setCurrentItem(item);
00201         emit selected( item );
00202       }
00203     }
00204   }
00205 }
00206 
00207 void KoIconChooser::mouseMoveEvent(QMouseEvent *e)
00208 {
00209   if(mMouseButtonDown && mDragEnabled )
00210   {
00211     if(mPixmapWidget)
00212     {
00213       delete mPixmapWidget;
00214       mPixmapWidget = 0L;
00215     }
00216     if( ( mDragStartPos - e->pos() ).manhattanLength() > QApplication::startDragDistance() )
00217       startDrag();
00218   }
00219 }
00220 
00221 void
00222 KoIconChooser::startDrag()
00223 {
00224   mMouseButtonDown = false;
00225 }
00226 
00227 // when a big item is shown in full size, delete it on mouseRelease
00228 void KoIconChooser::mouseReleaseEvent(QMouseEvent * /*e*/)
00229 {
00230   mMouseButtonDown = false;
00231   if(mPixmapWidget)
00232   {
00233     delete mPixmapWidget;
00234     mPixmapWidget = 0L;
00235   }
00236 }
00237 
00238 // FIXME: implement keyboard navigation
00239 void KoIconChooser::keyPressEvent(QKeyEvent *e)
00240 {
00241   QGridView::keyPressEvent(e);
00242 }
00243 
00244 // recalculate the number of items that fit into one row
00245 // set the current item again after calculating the new grid
00246 void KoIconChooser::resizeEvent(QResizeEvent *e)
00247 {
00248   QGridView::resizeEvent(e);
00249 
00250   KoIconItem *item = currentItem();
00251   int oldNCols = mNCols;
00252 
00253   if (cellWidth() != 0)
00254   {
00255     mNCols = e -> size().width() / cellWidth();
00256   }
00257 
00258   if(mNCols != oldNCols)
00259   {
00260     setNumCols(mNCols);
00261     calculateCells();
00262     setCurrentItem(item);
00263     updateContents();
00264   }
00265 }
00266 
00267 // paint one cell
00268 // mark the current item and center items smaller than the cellSize
00269 // TODO: scale down big pixmaps and paint the size as text into the pixmap
00270 void KoIconChooser::paintCell(QPainter *p, int row, int col)
00271 {
00272   KoIconItem *item = itemAt(row, col);
00273 
00274   if(item)
00275   {
00276     const QPixmap &pix = item->pixmap();
00277 
00278     int x = mMargin;
00279     int y = mMargin;
00280     int pw = pix.width();
00281     int ph = pix.height();
00282     int cw = cellWidth();
00283     int ch = cellHeight();
00284 
00285     // center small pixmaps
00286     if(pw < mItemWidth)
00287       x = (cw - pw) / 2;
00288     if(ph < mItemHeight)
00289       y = (cw - ph) / 2;
00290 
00291     if((!item->hasValidThumb()) || (pw <= mItemWidth && ph <= mItemHeight))
00292       p->drawPixmap(x, y, pix, 0, 0, mItemWidth, mItemHeight);
00293     else
00294     {
00295       const QPixmap &thumbpix = item->thumbPixmap();
00296       x = mMargin;
00297       y = mMargin;
00298       pw = thumbpix.width();
00299       ph = thumbpix.height();
00300       cw = cellWidth();
00301       ch = cellHeight();
00302 
00303       // center small pixmaps
00304       if(pw < mItemWidth)
00305         x = (cw - pw) / 2;
00306       if(ph < mItemHeight)
00307         y = (cw - ph) / 2;
00308       p->drawPixmap(x, y, thumbpix, 0, 0, mItemWidth, mItemHeight);
00309     }
00310 
00311     // highlight current item
00312     if(row == mCurRow && col == mCurCol)
00313     {
00314       p->setPen(blue);
00315       p->drawRect(0, 0, cw, ch);
00316     }
00317     else
00318     {
00319       p->setPen(gray);
00320       //p->drawRect(0, 0, cw, ch);
00321       p->drawLine(cw-1, 0, cw-1, ch-1);
00322       p->drawLine(0, ch-1, cw-1, ch-1);
00323     }
00324   }
00325   else
00326   {
00327     // empty cell
00328     p->fillRect(0, 0, cellWidth(), cellHeight(), QBrush(Qt::white));
00329   }
00330 }
00331 
00332 // return the pointer of the item at (row,col) - beware, resizing disturbs
00333 // rows and cols!
00334 // return 0L if item is not found
00335 KoIconItem *KoIconChooser::itemAt(int row, int col)
00336 {
00337   return itemAt(cellIndex(row, col));
00338 }
00339 
00340 // return the pointer of the item at position index
00341 // return 0L if item is not found
00342 KoIconItem *KoIconChooser::itemAt(int index)
00343 {
00344   return mIconList.count() > index ? mIconList.at(index) : 0;
00345 }
00346 
00347 // return the index of a cell, given row and column position
00348 // maps directly to the position in the itemlist
00349 // return -1 on failure
00350 int KoIconChooser::cellIndex(int row, int col)
00351 {
00352   if(row < 0 || col < 0)
00353     return -1;
00354   else
00355     return((row * mNCols) + col);
00356 }
00357 
00358 // calculate the grid and set the number of rows and columns
00359 // reorder all items approrpriately
00360 void KoIconChooser::calculateCells()
00361 {
00362   if(mNCols == 0)
00363     return;
00364   bool update = isUpdatesEnabled();
00365   int rows = mItemCount / mNCols;
00366   setUpdatesEnabled(false);
00367   if((rows * mNCols) < mItemCount)
00368     rows++;
00369   setNumRows(rows);
00370   setUpdatesEnabled(update);
00371   updateContents();
00372 }
00373 
00374 // show the full pixmap of a large item in an extra widget
00375 void KoIconChooser::showFullPixmap(const QPixmap &pix, const QPoint &/*p*/)
00376 {
00377   mPixmapWidget = new KoPixmapWidget(pix, this);
00378 }
00379 
00380 int KoIconChooser::sortInsertionIndex(const KoIconItem *item)
00381 {
00382   int index = 0;
00383 
00384   if (!mIconList.isEmpty())
00385   {
00386     // Binary insertion
00387     int first = 0;
00388     int last = mIconList.count() - 1;
00389     
00390     while (first != last)
00391     {
00392       int middle = (first + last) / 2;
00393     
00394       if (item -> compare(mIconList.at(middle)) < 0)
00395       {
00396         last = middle - 1;
00397 
00398         if (last < first)
00399         {
00400           last = first;
00401         }
00402       }
00403       else
00404       {
00405         first = middle + 1;
00406 
00407         if (first > last)
00408         {
00409           first = last;
00410         }
00411       }
00412     }
00413 
00414     if (item -> compare(mIconList.at(first)) < 0)
00415     {
00416       index = first;
00417     }
00418     else
00419     {
00420       index = first + 1;
00421     }
00422   }
00423 
00424   return index;
00425 }
00426 
00427 KoPatternChooser::KoPatternChooser( const QPtrList<KoIconItem> &list, QWidget *parent, const char *name )
00428  : QWidget( parent, name )
00429 {
00430     // only serves as beautifier for the iconchooser
00431     //frame = new QHBox( this );
00432     //frame->setFrameStyle( QFrame::Panel | QFrame::Sunken );
00433     chooser = new KoIconChooser( QSize(30,30), this, "pattern chooser" );
00434 
00435     QObject::connect( chooser, SIGNAL(selected( KoIconItem * ) ),
00436                                 this, SIGNAL( selected( KoIconItem * )));
00437 
00438     QPtrListIterator<KoIconItem> itr( list );
00439     for( itr.toFirst(); itr.current(); ++itr )
00440         chooser->addItem( itr.current() );
00441 
00442     QVBoxLayout *mainLayout = new QVBoxLayout( this, 1, -1, "main layout" );
00443     mainLayout->addWidget( chooser, 10 );
00444 }
00445 
00446 
00447 KoPatternChooser::~KoPatternChooser()
00448 {
00449   delete chooser;
00450   //delete frame;
00451 }
00452 
00453 // set the active pattern in the chooser - does NOT emit selected() (should it?)
00454 void KoPatternChooser::setCurrentPattern( KoIconItem *pattern )
00455 {
00456     chooser->setCurrentItem( pattern );
00457 }
00458 
00459 void KoPatternChooser::addPattern( KoIconItem *pattern )
00460 {
00461     chooser->addItem( pattern );
00462 }
00463 
00464 // return the active pattern
00465 KoIconItem *KoPatternChooser::currentPattern()
00466 {
00467     return chooser->currentItem();
00468 }
00469 
00470 #include "koIconChooser.moc"
KDE Logo
This file is part of the documentation for lib Library Version 1.4.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Mon Feb 13 09:40:01 2006 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003