diff options
Diffstat (limited to 'lib/kopainter/koIconChooser.cc')
-rw-r--r-- | lib/kopainter/koIconChooser.cc | 482 |
1 files changed, 482 insertions, 0 deletions
diff --git a/lib/kopainter/koIconChooser.cc b/lib/kopainter/koIconChooser.cc new file mode 100644 index 00000000..57fda8d8 --- /dev/null +++ b/lib/kopainter/koIconChooser.cc @@ -0,0 +1,482 @@ +/* This file is part of the KDE project + Copyright (c) 1999 Carsten Pfeiffer ([email protected]) + Copyright (c) 2002 Igor Jansen ([email protected]) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include <kdebug.h> +#include <koIconChooser.h> +#include <kglobal.h> + +#include <qpainter.h> +#include <qcursor.h> +#include <qapplication.h> +#include <qhbox.h> +#include <qlayout.h> +#include <kdebug.h> + +KoPixmapWidget::KoPixmapWidget(const QPixmap &aPixmap, QWidget *parent, const char *name): +QFrame(parent, name, WType_Popup) +{ + kdDebug() << "Popup created: " << name << "\n"; + setFrameStyle(QFrame::WinPanel | QFrame::Raised); + mPixmap = aPixmap; + int w = mPixmap.width() + 2 * lineWidth(); + int h = mPixmap.height() + 2 * lineWidth(); + resize(w, h); + +} + +KoPixmapWidget::~KoPixmapWidget() +{ +} + +// paint the centered pixmap; don't overpaint the frame +void KoPixmapWidget::paintEvent(QPaintEvent *e) +{ + QFrame::paintEvent(e); + QPainter p(this); + p.setClipRect(e->rect()); + p.drawPixmap(lineWidth(), lineWidth(), mPixmap); +} + + +void KoPixmapWidget::mouseReleaseEvent(QMouseEvent *) +{ + hide(); +} + + +KoIconChooser::KoIconChooser(QSize aIconSize, QWidget *parent, const char *name, bool sort): +QGridView(parent, name) +{ + QGridView::setBackgroundColor(Qt::white); + + mMargin = 2; + setCellWidth(aIconSize.width() + 2 * mMargin); + setCellHeight(aIconSize.height() + 2 * mMargin); + + mIconList.clear(); + mPixmapWidget = 0L; + mNCols = 0; + mCurRow = 0; + mCurCol = 0; + mItemCount = 0; + mItemWidth = aIconSize.width(); + mItemHeight = aIconSize.height(); + mMouseButtonDown = false; + mDragEnabled = false; + mSort = sort; +} + +KoIconChooser::~KoIconChooser() +{ + mIconList.clear(); + if(mPixmapWidget) + delete mPixmapWidget; +} + +void KoIconChooser::addItem(KoIconItem *item) +{ + Q_INT32 n = mItemCount; + KoIconItem *current = currentItem(); + + Q_ASSERT(item); + + int i; + + if (mSort) + { + i = sortInsertionIndex(item); + } + else + { + i = mItemCount; + } + + mIconList.insert(i, item); + mItemCount++; + calculateCells(); + + if (mSort) + { + setCurrentItem(current); + updateContents(); + } + else + { + updateCell(n / numCols(), n - (n / numCols()) * numCols()); + } +} + +bool KoIconChooser::removeItem(KoIconItem *item) +{ + int index = mIconList.find(item); + bool ok = mIconList.remove(item); + if( ok ) + { + mItemCount--; + // select same cell as deleted cell, or new last cell if we deleted + // last cell. + setCurrentItem(itemAt(kMin(index, mItemCount - 1))); + calculateCells(); + } + return ok; +} + +void KoIconChooser::clear() +{ + mItemCount = 0; + mIconList.clear(); + calculateCells(); +} + +// return 0L if there is no current item +KoIconItem *KoIconChooser::currentItem() +{ + return itemAt(mCurRow, mCurCol); +} + +// sets the current item to item +// does NOT emit selected() (should it?) +void KoIconChooser::setCurrentItem(KoIconItem *item) +{ + int index = mIconList.find(item); + + // item is available + if(index != -1 && mNCols > 0) + { + int oldRow = mCurRow; + int oldCol = mCurCol; + + mCurRow = index / mNCols; + mCurCol = index % mNCols; + + // repaint the old and the new item + repaintCell(oldRow, oldCol); + repaintCell(mCurRow, mCurCol); + + ensureCellVisible(mCurRow, mCurCol); + } +} + +// eventually select the item, clicked on +void KoIconChooser::mousePressEvent(QMouseEvent *e) +{ + QGridView::mousePressEvent(e); +} + +void KoIconChooser::mouseMoveEvent(QMouseEvent *e) +{ + if(mMouseButtonDown && mDragEnabled ) + { +#if 0 + if(mPixmapWidget) + { + delete mPixmapWidget; + mPixmapWidget = 0L; + } +#endif + if( ( mDragStartPos - e->pos() ).manhattanLength() > QApplication::startDragDistance() ) + startDrag(); + } +} + +void +KoIconChooser::startDrag() +{ + mMouseButtonDown = false; +} + +void KoIconChooser::mouseReleaseEvent(QMouseEvent * e) +{ + mMouseButtonDown = true; + if(e->button() == LeftButton) + { + QPoint p = e->pos(); + mDragStartPos = p; + int x = contentsX() + p.x(); + int y = contentsY() + p.y(); + QSize gridExtent = gridSize(); + + if (x < gridExtent.width() && y < gridExtent.height()) + { + int row = rowAt(y); + int col = columnAt(x); + + KoIconItem *item = itemAt(row, col); + if(item) + { + const QPixmap &pix = item->pixmap(); + if(pix.width() > mItemWidth || pix.height() > mItemHeight) + showFullPixmap(pix, p); + + setCurrentItem(item); + emit selected( item ); + } + } + } +} + +// FIXME: implement keyboard navigation +void KoIconChooser::keyPressEvent(QKeyEvent *e) +{ + QGridView::keyPressEvent(e); +} + +// recalculate the number of items that fit into one row +// set the current item again after calculating the new grid +void KoIconChooser::resizeEvent(QResizeEvent *e) +{ + QGridView::resizeEvent(e); + + KoIconItem *item = currentItem(); + int oldNCols = mNCols; + + if (cellWidth() != 0) + { + mNCols = e -> size().width() / cellWidth(); + } + + if(mNCols != oldNCols) + { + setNumCols(mNCols); + calculateCells(); + setCurrentItem(item); + updateContents(); + } +} + +// paint one cell +// mark the current item and center items smaller than the cellSize +// TODO: scale down big pixmaps and paint the size as text into the pixmap +void KoIconChooser::paintCell(QPainter *p, int row, int col) +{ + KoIconItem *item = itemAt(row, col); + + if(item) + { + const QPixmap &pix = item->pixmap(); + + int x = mMargin; + int y = mMargin; + int pw = pix.width(); + int ph = pix.height(); + int cw = cellWidth(); + int ch = cellHeight(); + + // center small pixmaps + if(pw < mItemWidth) + x = (cw - pw) / 2; + if(ph < mItemHeight) + y = (cw - ph) / 2; + + if((!item->hasValidThumb()) || (pw <= mItemWidth && ph <= mItemHeight)) + p->drawPixmap(x, y, pix, 0, 0, mItemWidth, mItemHeight); + else + { + const QPixmap &thumbpix = item->thumbPixmap(); + x = mMargin; + y = mMargin; + pw = thumbpix.width(); + ph = thumbpix.height(); + cw = cellWidth(); + ch = cellHeight(); + + // center small pixmaps + if(pw < mItemWidth) + x = (cw - pw) / 2; + if(ph < mItemHeight) + y = (cw - ph) / 2; + p->drawPixmap(x, y, thumbpix, 0, 0, mItemWidth, mItemHeight); + } + + // highlight current item + if(row == mCurRow && col == mCurCol) + { + p->setPen(blue); + p->drawRect(0, 0, cw, ch); + } + else + { + p->setPen(gray); + //p->drawRect(0, 0, cw, ch); + p->drawLine(cw-1, 0, cw-1, ch-1); + p->drawLine(0, ch-1, cw-1, ch-1); + } + } + else + { + // empty cell + p->fillRect(0, 0, cellWidth(), cellHeight(), QBrush(Qt::white)); + } +} + +// return the pointer of the item at (row,col) - beware, resizing disturbs +// rows and cols! +// return 0L if item is not found +KoIconItem *KoIconChooser::itemAt(int row, int col) +{ + return itemAt(cellIndex(row, col)); +} + +// return the pointer of the item at position index +// return 0L if item is not found +KoIconItem *KoIconChooser::itemAt(int index) +{ + if(index < 0) + return 0L; + return mIconList.count() > uint(index) ? mIconList.at(index) : 0; +} + +// return the index of a cell, given row and column position +// maps directly to the position in the itemlist +// return -1 on failure +int KoIconChooser::cellIndex(int row, int col) +{ + if(row < 0 || col < 0) + return -1; + else + return((row * mNCols) + col); +} + +// calculate the grid and set the number of rows and columns +// reorder all items approrpriately +void KoIconChooser::calculateCells() +{ + if(mNCols == 0) + return; + bool update = isUpdatesEnabled(); + int rows = mItemCount / mNCols; + setUpdatesEnabled(false); + if((rows * mNCols) < mItemCount) + rows++; + setNumRows(rows); + setUpdatesEnabled(update); + updateContents(); +} + +// show the full pixmap of a large item in an extra widget +void KoIconChooser::showFullPixmap(const QPixmap &pix, const QPoint &/*p*/) +{ + //delete mPixmapWidget; + mPixmapWidget = new KoPixmapWidget(pix, this); + + // center widget under mouse cursor + QPoint p = QCursor::pos(); + int w = mPixmapWidget->width(); + int h = mPixmapWidget->height(); + mPixmapWidget->move(p.x() - w / 2, p.y() - h / 2); + mPixmapWidget->show(); +} + +int KoIconChooser::sortInsertionIndex(const KoIconItem *item) +{ + int index = 0; + + if (!mIconList.isEmpty()) + { + // Binary insertion + int first = 0; + int last = mIconList.count() - 1; + + while (first != last) + { + int middle = (first + last) / 2; + + if (item -> compare(mIconList.at(middle)) < 0) + { + last = middle - 1; + + if (last < first) + { + last = first; + } + } + else + { + first = middle + 1; + + if (first > last) + { + first = last; + } + } + } + + if (item -> compare(mIconList.at(first)) < 0) + { + index = first; + } + else + { + index = first + 1; + } + } + + return index; +} + +KoPatternChooser::KoPatternChooser( const QPtrList<KoIconItem> &list, QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ + // only serves as beautifier for the iconchooser + //frame = new QHBox( this ); + //frame->setFrameStyle( QFrame::Panel | QFrame::Sunken ); + chooser = new KoIconChooser( QSize(30,30), this, "pattern chooser" ); + + QObject::connect( chooser, SIGNAL(selected( KoIconItem * ) ), + this, SIGNAL( selected( KoIconItem * ))); + + QPtrListIterator<KoIconItem> itr( list ); + for( itr.toFirst(); itr.current(); ++itr ) + chooser->addItem( itr.current() ); + + QVBoxLayout *mainLayout = new QVBoxLayout( this, 1, -1, "main layout" ); + mainLayout->addWidget( chooser, 10 ); +} + + +KoPatternChooser::~KoPatternChooser() +{ + delete chooser; + //delete frame; +} + +// set the active pattern in the chooser - does NOT emit selected() (should it?) +void KoPatternChooser::setCurrentPattern( KoIconItem *pattern ) +{ + chooser->setCurrentItem( pattern ); +} + +void KoPatternChooser::addPattern( KoIconItem *pattern ) +{ + chooser->addItem( pattern ); +} + +// return the active pattern +KoIconItem *KoPatternChooser::currentPattern() +{ + return chooser->currentItem(); +} + +void KoPatternChooser::removePattern( KoIconItem *pattern ) +{ + chooser->removeItem( pattern ); +} + +#include "koIconChooser.moc" |