lib

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