From e6f84716f0409293e69bde5d1fffbbd1196e0d62 Mon Sep 17 00:00:00 2001 From: Anatoly Mihalchenko Date: Thu, 12 Apr 2012 13:43:47 +0300 Subject: [PATCH] PDF view performance:multiple pages selection --- src/gui/UBThumbnailWidget.cpp | 1742 +++++++++++++++++---------------- src/gui/UBThumbnailWidget.h | 844 ++++++++-------- 2 files changed, 1302 insertions(+), 1284 deletions(-) diff --git a/src/gui/UBThumbnailWidget.cpp b/src/gui/UBThumbnailWidget.cpp index 302c6a23..cd0ebec3 100644 --- a/src/gui/UBThumbnailWidget.cpp +++ b/src/gui/UBThumbnailWidget.cpp @@ -1,863 +1,879 @@ -/* - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include -#include - -#include "UBThumbnailWidget.h" -#include "UBRubberBand.h" - -#include "core/UBSettings.h" -#include "core/UBApplication.h" - -#include "document/UBDocumentProxy.h" -#include "document/UBDocumentController.h" - -#include "core/memcheck.h" - -UBThumbnailWidget::UBThumbnailWidget(QWidget* parent) - : QGraphicsView(parent) - , mThumbnailWidth(UBSettings::defaultThumbnailWidth) - , mSpacing(UBSettings::thumbnailSpacing) - , mLastSelectedThumbnail(0) - , mSelectionSpan(0) - , mLassoRectItem(0) -{ - // By default, the drag is possible - bCanDrag = true; - setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::TextAntialiasing); - setFrameShape(QFrame::NoFrame); - setScene(&mThumbnailsScene); - - setAlignment(Qt::AlignLeft | Qt::AlignTop); - - connect(&mThumbnailsScene, SIGNAL(selectionChanged()), this, SLOT(sceneSelectionChanged())); -} - - -UBThumbnailWidget::~UBThumbnailWidget() -{ - disconnect(&mThumbnailsScene, SIGNAL(selectionChanged())); -} - - -void UBThumbnailWidget::setThumbnailWidth(qreal pThumbnailWidth) -{ - mThumbnailWidth = pThumbnailWidth; - - refreshScene(); -} - - -void UBThumbnailWidget::setSpacing(qreal pSpacing) -{ - mSpacing = pSpacing; - - refreshScene(); -} - - -void UBThumbnailWidget::setGraphicsItems(const QList& pGraphicsItems - , const QList& pItemsPaths - , const QStringList pLabels - , const QString& pMimeType) -{ - mGraphicItems = pGraphicsItems; - mItemsPaths = pItemsPaths; - mMimeType = pMimeType; - mLabels = pLabels; - - foreach(QGraphicsItem* it, mThumbnailsScene.items()) - { - mThumbnailsScene.removeItem(it, true); - } - - // set lasso to 0 as it has been cleared as well - mLassoRectItem = 0; - - foreach (QGraphicsItem* item, pGraphicsItems) - { - if (item->scene() != &mThumbnailsScene) - { - mThumbnailsScene.addItem(item); - } - } - - mLabelsItems.clear(); - - foreach (const QString label, pLabels) - { - QFontMetrics fm(font()); - UBThumbnailTextItem *labelItem = - new UBThumbnailTextItem(label); // deleted while replace or by the scene destruction - - mThumbnailsScene.addItem(labelItem); - mLabelsItems << labelItem; - } - - refreshScene(); - - mLastSelectedThumbnail = 0; -} - - -void UBThumbnailWidget::refreshScene() -{ - int nbColumns = (geometry().width() - mSpacing) / (mThumbnailWidth + mSpacing); - - int labelSpacing = 0; - - if (mLabelsItems.size() > 0) - { - QFontMetrics fm(mLabelsItems.at(0)->font()); - labelSpacing = UBSettings::thumbnailSpacing + fm.height(); // TODO UB 4.x where is 20 from ??? configure ?? compute based on mSpacing ?? JBA Is it the font height? - } - nbColumns = qMax(nbColumns, 1); - - qreal thumbnailHeight = mThumbnailWidth / UBSettings::minScreenRatio; - - for (int i = 0; i < mGraphicItems.size(); i++) - { - QGraphicsItem* item = mGraphicItems.at(i); - - qreal scaleWidth = mThumbnailWidth / item->boundingRect().width(); - qreal scaleHeight = thumbnailHeight / item->boundingRect().height(); - - qreal scaleFactor = qMin(scaleWidth, scaleHeight); - - //bitmap should not be stretched - UBThumbnail* pix = dynamic_cast(item); - if (pix) - scaleFactor = qMin(scaleFactor, 1.0); - - QTransform transform; - transform.scale(scaleFactor, scaleFactor); - - item->setTransform(transform); - - item->setFlag(QGraphicsItem::ItemIsSelectable, true); - - int columnIndex = i % nbColumns; - int rowIndex = i / nbColumns; - - if (pix) - { - pix->setColumn(columnIndex); - pix->setRow(rowIndex); - } - - int w = item->boundingRect().width(); - int h = item->boundingRect().height(); - QPointF pos( - mSpacing + (mThumbnailWidth - w * scaleFactor) / 2 + columnIndex * (mThumbnailWidth + mSpacing), - mSpacing + rowIndex * (thumbnailHeight + mSpacing + labelSpacing) + (thumbnailHeight - h * scaleFactor) / 2); - - item->setPos(pos); - - if (mLabelsItems.size() > i) - { - QFontMetrics fm(mLabelsItems.at(i)->font(), this); - QString elidedText = fm.elidedText(mLabels.at(i), Qt::ElideRight, mThumbnailWidth); - - mLabelsItems.at(i)->setPlainText(elidedText); - mLabelsItems.at(i)->setWidth(fm.width(elidedText) + 2 * mLabelsItems.at(i)->document()->documentMargin()); - - pos.setY(pos.y() + (thumbnailHeight + h * scaleFactor) / 2 + 5); - qreal labelWidth = fm.width(elidedText); - pos.setX(mSpacing + (mThumbnailWidth - labelWidth) / 2 + columnIndex * (mThumbnailWidth + mSpacing)); - mLabelsItems.at(i)->setPos(pos); - } - } - - QScrollBar *vertScrollBar = verticalScrollBar(); - int scrollBarThickness = 0; - if (vertScrollBar && vertScrollBar->isVisible()) - scrollBarThickness = vertScrollBar->width(); - - setSceneRect(0, 0, - geometry().width() - scrollBarThickness, - mSpacing + ((((mGraphicItems.size() - 1) / nbColumns) + 1) * (thumbnailHeight + mSpacing + labelSpacing))); -} - - -QList UBThumbnailWidget::selectedItems() -{ - QList sortedSelectedItems = mThumbnailsScene.selectedItems(); - qSort(sortedSelectedItems.begin(), sortedSelectedItems.end(), thumbnailLessThan); - return sortedSelectedItems; -} - - -void UBThumbnailWidget::mousePressEvent(QMouseEvent *event) -{ - mClickTime = QTime::currentTime(); - mMousePressPos = event->pos(); - mMousePressScenePos = mapToScene(mMousePressPos); - QGraphicsItem* underlyingItem = itemAt(mMousePressPos); - - UBThumbnail *previousSelectedThumbnail = mLastSelectedThumbnail; - - if (!dynamic_cast(underlyingItem)) - { - deleteLasso(); - - UBRubberBand rubberBand(QRubberBand::Rectangle); - QStyleOption option; - option.initFrom(&rubberBand); - - mLassoRectItem = new QGraphicsRectItem(0, scene()); - -#ifdef Q_WS_MAC - // The following code must stay in synch with \src\gui\styles\qmacstyle_mac.mm - QColor strokeColor; - strokeColor.setHsvF(0, 0, 0.86, 1.0); - mLassoRectItem->setPen(QPen(strokeColor)); - QColor fillColor(option.palette.color(QPalette::Disabled, QPalette::Highlight)); - fillColor.setHsvF(0, 0, 0.53, 0.25); - mLassoRectItem->setBrush(fillColor); -#else - // The following code must stay in synch with \src\gui\styles\qwindowsxpstyle.cpp - QColor highlight = option.palette.color(QPalette::Active, QPalette::Highlight); - mLassoRectItem->setPen(highlight.darker(120)); - QColor dimHighlight(qMin(highlight.red() / 2 + 110, 255), - qMin(highlight.green() / 2 + 110, 255), - qMin(highlight.blue() / 2 + 110, 255), - 127); - mLassoRectItem->setBrush(dimHighlight); -#endif - - mLassoRectItem->setZValue(10000); - mLassoRectItem->setRect(QRectF(mMousePressScenePos, QSizeF())); - - if (Qt::ControlModifier & event->modifiers() || Qt::ShiftModifier & event->modifiers()) - { - mSelectedThumbnailItems = selectedItems(); - return; - } - - mSelectedThumbnailItems.clear(); - QGraphicsView::mousePressEvent(event); - } - else if (Qt::ShiftModifier & event->modifiers()) - { - if (previousSelectedThumbnail) - { - QGraphicsItem* previousSelectedItem = dynamic_cast(previousSelectedThumbnail); - if (previousSelectedItem) - { - int index1 = mGraphicItems.indexOf(previousSelectedItem); - int index2 = mGraphicItems.indexOf(underlyingItem); - if (-1 == index2) - { - mSelectedThumbnailItems = selectedItems(); - return; - } - mSelectionSpan = index2 - index1; - selectItems(qMin(index1, index2), mSelectionSpan < 0 ? - mSelectionSpan + 1 : mSelectionSpan + 1); - return; - } - } - } - else - { - mLastSelectedThumbnail = dynamic_cast(underlyingItem); - if (!underlyingItem->isSelected()) - { - int index = mGraphicItems.indexOf(underlyingItem); - selectItemAt(index, Qt::ControlModifier & event->modifiers()); - } - else - { - QGraphicsView::mousePressEvent(event); - } - if (!mLastSelectedThumbnail && mGraphicItems.count() > 0) - mLastSelectedThumbnail = dynamic_cast(mGraphicItems.at(0)); - mSelectionSpan = 0; - return; - } -} - - -void UBThumbnailWidget::mouseMoveEvent(QMouseEvent *event) -{ - int distance = (mMousePressPos - event->pos()).manhattanLength(); - - if (0 == (event->buttons() & Qt::LeftButton) || distance < QApplication::startDragDistance()) - return; - - if (mLassoRectItem) - { - bSelectionInProgress = true; - QPointF currentScenePos = mapToScene(event->pos()); - QRectF lassoRect( - qMin(mMousePressScenePos.x(), currentScenePos.x()), qMin(mMousePressScenePos.y(), currentScenePos.y()), - qAbs(mMousePressScenePos.x() - currentScenePos.x()), qAbs(mMousePressScenePos.y() - currentScenePos.y())); - mLassoRectItem->setRect(lassoRect); - - QList lassoSelectedItems = scene()->items(lassoRect, Qt::IntersectsItemBoundingRect); - QList lassoSelectedThumbnailItems; - foreach (QGraphicsItem *lassoSelectedItem, lassoSelectedItems) - { - UBThumbnail *thumbnailItem = dynamic_cast(lassoSelectedItem); - if (thumbnailItem) - lassoSelectedThumbnailItems.append(lassoSelectedItems); - } - - unselectAll(); - foreach (QGraphicsItem *lassoSelectedItem, lassoSelectedThumbnailItems) - { - if (Qt::ControlModifier & event->modifiers()) - { - if (!mSelectedThumbnailItems.contains(lassoSelectedItem)) - selectItemAt(mGraphicItems.indexOf(lassoSelectedItem), true); - } - else - { - selectItemAt(mGraphicItems.indexOf(lassoSelectedItem), true); - } - } - if (Qt::ControlModifier & event->modifiers()) - { - foreach (QGraphicsItem *selectedItem, mSelectedThumbnailItems) - { - if (!lassoSelectedThumbnailItems.contains(selectedItem)) - selectItemAt(mGraphicItems.indexOf(selectedItem), true); - } - } - } - else - { - bSelectionInProgress = false; - if (0 == selectedItems().size()) - return; - - if(bCanDrag) - { - QDrag *drag = new QDrag(this); - QMimeData *mime = new QMimeData(); - - if (mMimeType.length() > 0) - mime->setData(mMimeType, QByteArray()); // trick the d&d system to register our own mime type - - drag->setMimeData(mime); - - QList qlElements; - - foreach (QGraphicsItem* item, selectedItems()) - { - if (mGraphicItems.contains(item)) - { - if (mGraphicItems.indexOf(item) <= mItemsPaths.size()){ - qlElements << mItemsPaths.at(mGraphicItems.indexOf(item)); - } - } - } - - if (qlElements.size() > 0){ - mime->setUrls(qlElements); - drag->setMimeData(mime); - drag->exec(Qt::CopyAction); - } - } - } - - QGraphicsView::mouseMoveEvent(event); -} - - -void UBThumbnailWidget::mouseReleaseEvent(QMouseEvent *event) -{ - int elapsedTimeSincePress = mClickTime.elapsed(); - deleteLasso(); - QGraphicsView::mouseReleaseEvent(event); - - if(elapsedTimeSincePress < STARTDRAGTIME) { - emit mouseClick(itemAt(event->pos()), 0); - } -} - - -void UBThumbnailWidget::keyPressEvent(QKeyEvent *event) -{ - if (mLastSelectedThumbnail) - { - QGraphicsItem *lastSelectedGraphicsItem = dynamic_cast(mLastSelectedThumbnail); - if (!lastSelectedGraphicsItem) return; - int startSelectionIndex = mGraphicItems.indexOf(lastSelectedGraphicsItem); - int previousSelectedThumbnailIndex = startSelectionIndex + mSelectionSpan; - - switch (event->key()) - { - case Qt::Key_Down: - case Qt::Key_Up: - { - if (rowCount() <= 1) break; - if (Qt::ShiftModifier & event->modifiers()) - { - int endSelectionIndex; - if (Qt::Key_Down == event->key()) - { - endSelectionIndex = previousSelectedThumbnailIndex + columnCount(); - if (endSelectionIndex >= mGraphicItems.count()) break; - } - else - { - endSelectionIndex = previousSelectedThumbnailIndex - columnCount(); - if (endSelectionIndex < 0) break; - } - - int startIndex = startSelectionIndex < endSelectionIndex ? startSelectionIndex : endSelectionIndex; - int count = startSelectionIndex < endSelectionIndex ? endSelectionIndex - startSelectionIndex + 1 : startSelectionIndex - endSelectionIndex + 1; - mSelectionSpan = startSelectionIndex < endSelectionIndex ? (count - 1) : - (count - 1); - selectItems(startIndex, count); - } - else - { - int toSelectIndex; - if (Qt::Key_Down == event->key()) - { - toSelectIndex = previousSelectedThumbnailIndex + columnCount(); - if (toSelectIndex >= mGraphicItems.count()) break; - } - else - { - toSelectIndex = previousSelectedThumbnailIndex - columnCount(); - if (toSelectIndex < 0) break; - } - - selectItemAt(toSelectIndex, Qt::ControlModifier & event->modifiers()); - mSelectionSpan = 0; - } - } - break; - - case Qt::Key_Left: - case Qt::Key_Right: - { - QGraphicsItem *previousSelectedItem = mGraphicItems.at(previousSelectedThumbnailIndex); - UBThumbnail *previousSelectedThumbnail = dynamic_cast(previousSelectedItem); - if (!previousSelectedThumbnail) break; - - if (Qt::Key_Left == event->key()) - { - if (0 == previousSelectedThumbnail->column()) break; - } - else - { - if (previousSelectedThumbnail->column() == columnCount() - 1 || - previousSelectedThumbnailIndex == mGraphicItems.count() - 1) break; - } - - if (Qt::ShiftModifier & event->modifiers()) - { - int endSelectionIndex; - if (Qt::Key_Left == event->key()) - { - endSelectionIndex = previousSelectedThumbnailIndex - 1; - if (endSelectionIndex < 0) break; - } - else - { - endSelectionIndex = previousSelectedThumbnailIndex + 1; - if (endSelectionIndex >= mGraphicItems.count()) break; - } - - int startIndex = startSelectionIndex < endSelectionIndex ? startSelectionIndex : endSelectionIndex; - int count = startSelectionIndex < endSelectionIndex ? endSelectionIndex - startSelectionIndex + 1 : startSelectionIndex - endSelectionIndex + 1; - mSelectionSpan = startSelectionIndex < endSelectionIndex ? (count - 1) : - (count - 1); - selectItems(startIndex, count); - } - else - { - if (Qt::Key_Left == event->key()) - selectItemAt(previousSelectedThumbnailIndex - 1, Qt::ControlModifier & event->modifiers()); - else - selectItemAt(previousSelectedThumbnailIndex + 1, Qt::ControlModifier & event->modifiers()); - - mSelectionSpan = 0; - } - } - break; - - case Qt::Key_Home: - { - if (Qt::ShiftModifier & event->modifiers()) - { - mSelectionSpan = - startSelectionIndex; - selectItems(0, startSelectionIndex + 1); - } - else - { - selectItemAt(0, Qt::ControlModifier & event->modifiers()); - mSelectionSpan = 0; - } - } - break; - - case Qt::Key_End: - { - if (Qt::ShiftModifier & event->modifiers()) - { - mSelectionSpan = mGraphicItems.count() - startSelectionIndex - 1; - selectItems(startSelectionIndex, mSelectionSpan + 1); - } - else - { - selectItemAt(mGraphicItems.count() - 1, Qt::ControlModifier & event->modifiers()); - mSelectionSpan = 0; - } - } - break; - case Qt::Key_A: - { - if (Qt::ControlModifier & event->modifiers()) - selectAll(); - } - break; - } - } - QGraphicsView::keyPressEvent(event); -} - - -void UBThumbnailWidget::focusInEvent(QFocusEvent *event) -{ - Q_UNUSED(event); - - if (0 == selectedItems().count() && mGraphicItems.count() > 0 && Qt::TabFocusReason == event->reason()) - { - selectItemAt(0); - mSelectionSpan = 0; - } -} - - -void UBThumbnailWidget::resizeEvent(QResizeEvent *event) -{ - Q_UNUSED(event); - - refreshScene(); - - emit resized(); -} - - -void UBThumbnailWidget::sceneSelectionChanged() -{ - emit selectionChanged(); -} - - -void UBThumbnailWidget::selectItemAt(int pIndex, bool extend) -{ - QGraphicsItem* itemToSelect = 0; - - if (pIndex >= 0 && pIndex < mGraphicItems.size()) - itemToSelect = mGraphicItems.at(pIndex); - - foreach (QGraphicsItem* item, items()) - { - if (item == itemToSelect) - { - mLastSelectedThumbnail = dynamic_cast(item); - item->setSelected(true); - ensureVisible(item); - } - else if (!extend) - { - item->setSelected(false); - } - } -} - -void UBThumbnailWidget::unselectItemAt(int pIndex) -{ - if (pIndex >= 0 && pIndex < mGraphicItems.size()) - { - QGraphicsItem *itemToUnselect = mGraphicItems.at(pIndex); - itemToUnselect->setSelected(false); - } -} - - -void UBThumbnailWidget::selectItems(int startIndex, int count) -{ - for (int i = 0; i < mGraphicItems.count(); i++) - { - mGraphicItems.at(i)->setSelected(i >= startIndex && i < startIndex + count); - } -} - - -void UBThumbnailWidget::selectAll() -{ - foreach (QGraphicsItem* item, mGraphicItems) - { - item->setSelected(true); - } -} - -void UBThumbnailWidget::unselectAll() -{ - foreach (QGraphicsItem* item, mGraphicItems) - { - item->setSelected(false); - } -} - -int UBThumbnailWidget::rowCount() const -{ - UBThumbnail *lastThumbnail = dynamic_cast(mGraphicItems.last()); - return lastThumbnail ? lastThumbnail->row() + 1 : 0; -} - -int UBThumbnailWidget::columnCount() const -{ - UBThumbnail *lastThumbnail = dynamic_cast(mGraphicItems.last()); - if (!lastThumbnail) return 0; - int lastRow = lastThumbnail->row(); - int lastColumn = lastThumbnail->column(); - return lastRow > 0 ? (mGraphicItems.count() - lastColumn - 1) / lastRow : mGraphicItems.count(); -} - - -void UBThumbnailWidget::mouseDoubleClickEvent(QMouseEvent * event) -{ - QGraphicsItem* item = itemAt(event->pos()); - - if (item) - { - int index = mGraphicItems.indexOf(item); - emit mouseDoubleClick(item, index); - } -} - - -bool UBThumbnailWidget::thumbnailLessThan(QGraphicsItem* item1, QGraphicsItem* item2) -{ - UBThumbnail *thumbnail1 = dynamic_cast(item1); - UBThumbnail *thumbnail2 = dynamic_cast(item2); - if (thumbnail1 && thumbnail2) - { - if (thumbnail1->row() != thumbnail2->row()) - return thumbnail1->row() < thumbnail2->row(); - else - return thumbnail1->column() < thumbnail2->column(); - } - return false; -} - -void UBThumbnailWidget::deleteLasso() -{ - if (mLassoRectItem && scene()) - { - scene()->removeItem(mLassoRectItem); - delete mLassoRectItem; - mLassoRectItem = 0; - } -} - - -UBThumbnail::UBThumbnail() - : mAddedToScene(false) -{ - mSelectionItem = new QGraphicsRectItem(0, 0, 0, 0); - mSelectionItem->setPen(QPen(UBSettings::treeViewBackgroundColor, 8)); - // TODO UB 4.x fix nasty dependencies : 8 is a bit less than half of UBThumbnailWidget.mSpacing -} - -UBThumbnail::~UBThumbnail() -{ - if (mSelectionItem && !mAddedToScene) - delete mSelectionItem; -} - - -UBSceneThumbnailNavigPixmap::UBSceneThumbnailNavigPixmap(const QPixmap& pix, UBDocumentProxy* proxy, int pSceneIndex) - : UBSceneThumbnailPixmap(pix, proxy, pSceneIndex) - , bButtonsVisible(false) - , bCanDelete(false) - , bCanMoveUp(false) - , bCanMoveDown(false) -{ - setAcceptsHoverEvents(true); - setFlag(QGraphicsItem::ItemIsSelectable, true); -} - -UBSceneThumbnailNavigPixmap::~UBSceneThumbnailNavigPixmap() -{ - -} - -void UBSceneThumbnailNavigPixmap::hoverEnterEvent(QGraphicsSceneHoverEvent *event) -{ - event->accept(); - updateButtonsState(); - update(); -} - -void UBSceneThumbnailNavigPixmap::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) -{ - event->accept(); - bButtonsVisible = false; - update(); -} - -void UBSceneThumbnailNavigPixmap::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) -{ - Q_UNUSED(option); - Q_UNUSED(widget); - - UBSceneThumbnailPixmap::paint(painter, option, widget); - if(bButtonsVisible) - { - if(bCanDelete) - painter->drawPixmap(0, 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/close.svg")); - else - painter->drawPixmap(0, 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/closeDisabled.svg")); - if(bCanMoveUp) - painter->drawPixmap(BUTTONSIZE + BUTTONSPACING, 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/moveUp.svg")); - else - painter->drawPixmap(BUTTONSIZE + BUTTONSPACING, 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/moveUpDisabled.svg")); - if(bCanMoveDown) - painter->drawPixmap(2*(BUTTONSIZE + BUTTONSPACING), 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/menu.svg")); - else - painter->drawPixmap(2*(BUTTONSIZE + BUTTONSPACING), 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/menuDisabled.svg")); - } -} - -void UBSceneThumbnailNavigPixmap::mousePressEvent(QGraphicsSceneMouseEvent *event) -{ - QPointF p = event->pos(); - - // Here we check the position of the click and verify if it has to trig an action or not. - if(bCanDelete && p.x() >= 0 && p.x() <= BUTTONSIZE && p.y() >= 0 && p.y() <= BUTTONSIZE) - { - deletePage(); - } - if(bCanMoveUp && p.x() >= BUTTONSIZE + BUTTONSPACING && p.x() <= 2*BUTTONSIZE + BUTTONSPACING && p.y() >= 0 && p.y() <= BUTTONSIZE) - { - moveUpPage(); - } - if(bCanMoveDown && p.x() >= 2*(BUTTONSIZE + BUTTONSPACING) && p.x() <= 2*(BUTTONSIZE + BUTTONSPACING) + BUTTONSIZE && p.y() >= 0 && p.y() <= BUTTONSIZE) - { - moveDownPage(); - } - event->accept(); -} - -void UBSceneThumbnailNavigPixmap::updateButtonsState() -{ - bCanDelete = false; - bCanMoveUp = false; - bCanMoveDown = false; - - UBDocumentProxy* p = proxy(); - if(NULL != p) - { - int iNbPages = p->pageCount(); - if(1 < iNbPages) - { - bCanDelete = true; - if(sceneIndex() > 0) - { - bCanMoveUp = true; - } - if(sceneIndex() != iNbPages - 1) - { - bCanMoveDown = true; - } - } - } - - if(bCanDelete || bCanMoveUp || bCanMoveDown) - { - bButtonsVisible = true; - } -} - -void UBSceneThumbnailNavigPixmap::deletePage() -{ - QList itemsToDelete; - itemsToDelete << this; - - UBApplication::documentController->deletePages(itemsToDelete); -} - -void UBSceneThumbnailNavigPixmap::moveUpPage() -{ - UBApplication::documentController->moveSceneToIndex(proxy(), sceneIndex(), sceneIndex() - 1); -} - -void UBSceneThumbnailNavigPixmap::moveDownPage() -{ - UBApplication::documentController->moveSceneToIndex(proxy(), sceneIndex(), sceneIndex() + 1); -} - -void UBImgTextThumbnailElement::Place(int row, int col, qreal width, qreal height) -{ - int labelSpacing = 0; - if(this->caption) - { - QFontMetrics fm(this->caption->font()); - labelSpacing = UBSettings::thumbnailSpacing + fm.height(); - } - if(this->thumbnail) - { - int w = this->thumbnail->boundingRect().width(); - int h = this->thumbnail->boundingRect().height(); - - qreal scaleWidth = width / w; - qreal scaleHeight = height / h; - qreal scaleFactor = qMin(scaleWidth, scaleHeight); - UBThumbnail* pix = dynamic_cast(this->thumbnail); - - if(pix) - { - scaleFactor = qMin(scaleFactor, 1.0); - } - - QTransform transform; - transform.scale(scaleFactor, scaleFactor); - - // Apply the scaling - this->thumbnail->setTransform(transform); - this->thumbnail->setFlag(QGraphicsItem::ItemIsSelectable, true); - - if(pix) - { - pix->setColumn(col); - pix->setRow(row); - } - - QPointF pos(border + (width - w * scaleFactor) / 2 + col * (width + border), - border + row * (height + border + labelSpacing) + (height - h * scaleFactor) / 2); - - this->thumbnail->setPos(pos); - - if(this->caption) - { - QFontMetrics fm(this->caption->font()); - QString elidedText = fm.elidedText(this->caption->toPlainText(), Qt::ElideRight, width); - - this->caption->setPlainText(elidedText); - this->caption->setWidth(fm.width(elidedText) + 2 * this->caption->document()->documentMargin()); - pos.setY(pos.y() + (height + h * scaleFactor) / 2 + 5); // What is this 5 ?? - qreal labelWidth = fm.width(elidedText); - pos.setX(border + (width - labelWidth) / 2 + col * (width + border)); - this->caption->setPos(pos); - } - } -} +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include + +#include "UBThumbnailWidget.h" +#include "UBRubberBand.h" + +#include "core/UBSettings.h" +#include "core/UBApplication.h" + +#include "document/UBDocumentProxy.h" +#include "document/UBDocumentController.h" + +#include "core/memcheck.h" + +UBThumbnailWidget::UBThumbnailWidget(QWidget* parent) + : QGraphicsView(parent) + , mThumbnailWidth(UBSettings::defaultThumbnailWidth) + , mSpacing(UBSettings::thumbnailSpacing) + , mLastSelectedThumbnail(0) + , mSelectionSpan(0) + , mLassoRectItem(0) +{ + // By default, the drag is possible + bCanDrag = true; + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::TextAntialiasing); + setFrameShape(QFrame::NoFrame); + setScene(&mThumbnailsScene); + + setAlignment(Qt::AlignLeft | Qt::AlignTop); + + connect(&mThumbnailsScene, SIGNAL(selectionChanged()), this, SLOT(sceneSelectionChanged())); +} + + +UBThumbnailWidget::~UBThumbnailWidget() +{ + disconnect(&mThumbnailsScene, SIGNAL(selectionChanged())); +} + + +void UBThumbnailWidget::setThumbnailWidth(qreal pThumbnailWidth) +{ + mThumbnailWidth = pThumbnailWidth; + + refreshScene(); +} + + +void UBThumbnailWidget::setSpacing(qreal pSpacing) +{ + mSpacing = pSpacing; + + refreshScene(); +} + + +void UBThumbnailWidget::setGraphicsItems(const QList& pGraphicsItems + , const QList& pItemsPaths + , const QStringList pLabels + , const QString& pMimeType) +{ + mGraphicItems = pGraphicsItems; + mItemsPaths = pItemsPaths; + mMimeType = pMimeType; + mLabels = pLabels; + + foreach(QGraphicsItem* it, mThumbnailsScene.items()) + { + mThumbnailsScene.removeItem(it, true); + } + + // set lasso to 0 as it has been cleared as well + mLassoRectItem = 0; + + foreach (QGraphicsItem* item, pGraphicsItems) + { + if (item->scene() != &mThumbnailsScene) + { + mThumbnailsScene.addItem(item); + } + } + + mLabelsItems.clear(); + + foreach (const QString label, pLabels) + { + QFontMetrics fm(font()); + UBThumbnailTextItem *labelItem = + new UBThumbnailTextItem(label); // deleted while replace or by the scene destruction + + mThumbnailsScene.addItem(labelItem); + mLabelsItems << labelItem; + } + + refreshScene(); + + mLastSelectedThumbnail = 0; +} + + +void UBThumbnailWidget::refreshScene() +{ + int nbColumns = (geometry().width() - mSpacing) / (mThumbnailWidth + mSpacing); + + int labelSpacing = 0; + + if (mLabelsItems.size() > 0) + { + QFontMetrics fm(mLabelsItems.at(0)->font()); + labelSpacing = UBSettings::thumbnailSpacing + fm.height(); // TODO UB 4.x where is 20 from ??? configure ?? compute based on mSpacing ?? JBA Is it the font height? + } + nbColumns = qMax(nbColumns, 1); + + qreal thumbnailHeight = mThumbnailWidth / UBSettings::minScreenRatio; + + for (int i = 0; i < mGraphicItems.size(); i++) + { + QGraphicsItem* item = mGraphicItems.at(i); + + qreal scaleWidth = mThumbnailWidth / item->boundingRect().width(); + qreal scaleHeight = thumbnailHeight / item->boundingRect().height(); + + qreal scaleFactor = qMin(scaleWidth, scaleHeight); + + //bitmap should not be stretched + UBThumbnail* pix = dynamic_cast(item); + if (pix) + scaleFactor = qMin(scaleFactor, 1.0); + + QTransform transform; + transform.scale(scaleFactor, scaleFactor); + + item->setTransform(transform); + + item->setFlag(QGraphicsItem::ItemIsSelectable, true); + + int columnIndex = i % nbColumns; + int rowIndex = i / nbColumns; + + if (pix) + { + pix->setColumn(columnIndex); + pix->setRow(rowIndex); + } + + int w = item->boundingRect().width(); + int h = item->boundingRect().height(); + QPointF pos( + mSpacing + (mThumbnailWidth - w * scaleFactor) / 2 + columnIndex * (mThumbnailWidth + mSpacing), + mSpacing + rowIndex * (thumbnailHeight + mSpacing + labelSpacing) + (thumbnailHeight - h * scaleFactor) / 2); + + item->setPos(pos); + + if (mLabelsItems.size() > i) + { + QFontMetrics fm(mLabelsItems.at(i)->font(), this); + QString elidedText = fm.elidedText(mLabels.at(i), Qt::ElideRight, mThumbnailWidth); + + mLabelsItems.at(i)->setPlainText(elidedText); + mLabelsItems.at(i)->setWidth(fm.width(elidedText) + 2 * mLabelsItems.at(i)->document()->documentMargin()); + + pos.setY(pos.y() + (thumbnailHeight + h * scaleFactor) / 2 + 5); + qreal labelWidth = fm.width(elidedText); + pos.setX(mSpacing + (mThumbnailWidth - labelWidth) / 2 + columnIndex * (mThumbnailWidth + mSpacing)); + mLabelsItems.at(i)->setPos(pos); + } + } + + QScrollBar *vertScrollBar = verticalScrollBar(); + int scrollBarThickness = 0; + if (vertScrollBar && vertScrollBar->isVisible()) + scrollBarThickness = vertScrollBar->width(); + + setSceneRect(0, 0, + geometry().width() - scrollBarThickness, + mSpacing + ((((mGraphicItems.size() - 1) / nbColumns) + 1) * (thumbnailHeight + mSpacing + labelSpacing))); +} + + +QList UBThumbnailWidget::selectedItems() +{ + QList sortedSelectedItems = mThumbnailsScene.selectedItems(); + qSort(sortedSelectedItems.begin(), sortedSelectedItems.end(), thumbnailLessThan); + return sortedSelectedItems; +} + + +void UBThumbnailWidget::mousePressEvent(QMouseEvent *event) +{ + mClickTime = QTime::currentTime(); + mMousePressPos = event->pos(); + mMousePressScenePos = mapToScene(mMousePressPos); + QGraphicsItem* underlyingItem = itemAt(mMousePressPos); + + UBThumbnail *previousSelectedThumbnail = mLastSelectedThumbnail; + + if (!dynamic_cast(underlyingItem)) + { + deleteLasso(); + + UBRubberBand rubberBand(QRubberBand::Rectangle); + QStyleOption option; + option.initFrom(&rubberBand); + + mLassoRectItem = new QGraphicsRectItem(0, scene()); + +#ifdef Q_WS_MAC + // The following code must stay in synch with \src\gui\styles\qmacstyle_mac.mm + QColor strokeColor; + strokeColor.setHsvF(0, 0, 0.86, 1.0); + mLassoRectItem->setPen(QPen(strokeColor)); + QColor fillColor(option.palette.color(QPalette::Disabled, QPalette::Highlight)); + fillColor.setHsvF(0, 0, 0.53, 0.25); + mLassoRectItem->setBrush(fillColor); +#else + // The following code must stay in synch with \src\gui\styles\qwindowsxpstyle.cpp + QColor highlight = option.palette.color(QPalette::Active, QPalette::Highlight); + mLassoRectItem->setPen(highlight.darker(120)); + QColor dimHighlight(qMin(highlight.red() / 2 + 110, 255), + qMin(highlight.green() / 2 + 110, 255), + qMin(highlight.blue() / 2 + 110, 255), + 127); + mLassoRectItem->setBrush(dimHighlight); +#endif + + mLassoRectItem->setZValue(10000); + mLassoRectItem->setRect(QRectF(mMousePressScenePos, QSizeF())); + + if (Qt::ControlModifier & event->modifiers() || Qt::ShiftModifier & event->modifiers()) + { + // mSelectedThumbnailItems = selectedItems().toSet(); + return; + } + + mSelectedThumbnailItems.clear(); + QGraphicsView::mousePressEvent(event); + } + else if (Qt::ShiftModifier & event->modifiers()) + { + if (previousSelectedThumbnail) + { + QGraphicsItem* previousSelectedItem = dynamic_cast(previousSelectedThumbnail); + if (previousSelectedItem) + { + int index1 = mGraphicItems.indexOf(previousSelectedItem); + int index2 = mGraphicItems.indexOf(underlyingItem); + if (-1 == index2) + { + mSelectedThumbnailItems = selectedItems().toSet(); + return; + } + mSelectionSpan = index2 - index1; + selectItems(qMin(index1, index2), mSelectionSpan < 0 ? - mSelectionSpan + 1 : mSelectionSpan + 1); + return; + } + } + } + else + { + mLastSelectedThumbnail = dynamic_cast(underlyingItem); + if (!underlyingItem->isSelected()) + { + int index = mGraphicItems.indexOf(underlyingItem); + selectItemAt(index, Qt::ControlModifier & event->modifiers()); + } + else + { + QGraphicsView::mousePressEvent(event); + } + if (!mLastSelectedThumbnail && mGraphicItems.count() > 0) + mLastSelectedThumbnail = dynamic_cast(mGraphicItems.at(0)); + mSelectionSpan = 0; + return; + } +} + + +void UBThumbnailWidget::mouseMoveEvent(QMouseEvent *event) +{ + int distance = (mMousePressPos - event->pos()).manhattanLength(); + + if (0 == (event->buttons() & Qt::LeftButton) || distance < QApplication::startDragDistance()) + return; + + if (mLassoRectItem) + { + bSelectionInProgress = true; + int incrementLassoMinWidth = 2; + QPointF currentScenePos = mapToScene(event->pos()); + QRectF lassoRect( + qMin(mMousePressScenePos.x(), currentScenePos.x()), qMin(mMousePressScenePos.y(), currentScenePos.y()), + qAbs(mMousePressScenePos.x() - currentScenePos.x()), qAbs(mMousePressScenePos.y() - currentScenePos.y())); + QRectF incrementXSelection( + qMin(prevMoveMousePos.x(), currentScenePos.x()), qMin(mMousePressScenePos.y(), currentScenePos.y()), + qAbs(prevMoveMousePos.x() - currentScenePos.x())+incrementLassoMinWidth, qAbs(mMousePressScenePos.y() - currentScenePos.y())); + QRectF incrementYSelection( + qMin(mMousePressScenePos.x(), currentScenePos.x()), qMin(prevMoveMousePos.y(), currentScenePos.y()), + qAbs(mMousePressScenePos.x() - currentScenePos.x()), qAbs(prevMoveMousePos.y() - currentScenePos.y())+incrementLassoMinWidth); + + prevMoveMousePos = currentScenePos; + mLassoRectItem->setRect(lassoRect); + + + QSet incSelectedItems = scene()->items(incrementXSelection, Qt::IntersectsItemBoundingRect).toSet() + + scene()->items(incrementYSelection, Qt::IntersectsItemBoundingRect).toSet(); + + mPreviouslyIncrementalSelectedItems = incSelectedItems; + QSet lassoSelectedItems; + QSet lassoSelectedThumbnailItems; + foreach (QGraphicsItem *lassoSelectedItem, incSelectedItems) + { + if (lassoSelectedItem) + { + UBSceneThumbnailPixmap *thumbnailItem = dynamic_cast(lassoSelectedItem); + + if (thumbnailItem) + { + lassoSelectedItem->setSelected(true); + lassoSelectedThumbnailItems += lassoSelectedItem; + } + } + } + + QSet toUnset; + toUnset = mSelectedThumbnailItems - lassoSelectedThumbnailItems; + foreach(QGraphicsItem* item, toUnset) + { + item->setSelected(false); + } + + + mSelectedThumbnailItems += lassoSelectedItems; + // foreach (QGraphicsItem *lassoSelectedItem, lassoSelectedThumbnailItems) + { + + } + if (Qt::ControlModifier & event->modifiers()) + { + for (int i = 0; i < mSelectedThumbnailItems.count()-1; i++) + { + mSelectedThumbnailItems.values().at(i)->setSelected(true); + } + // foreach (QGraphicsItem *selectedItem, mSelectedThumbnailItems) + { + // selectedItem->setSelected(true); + } + } + } + else + { + bSelectionInProgress = false; + if (0 == selectedItems().size()) + return; + + if(bCanDrag) + { + QDrag *drag = new QDrag(this); + QMimeData *mime = new QMimeData(); + + if (mMimeType.length() > 0) + mime->setData(mMimeType, QByteArray()); // trick the d&d system to register our own mime type + + drag->setMimeData(mime); + + QList qlElements; + + foreach (QGraphicsItem* item, selectedItems()) + { + if (mGraphicItems.contains(item)) + { + if (mGraphicItems.indexOf(item) <= mItemsPaths.size()){ + qlElements << mItemsPaths.at(mGraphicItems.indexOf(item)); + } + } + } + + if (qlElements.size() > 0){ + mime->setUrls(qlElements); + drag->setMimeData(mime); + drag->exec(Qt::CopyAction); + } + } + } + + QGraphicsView::mouseMoveEvent(event); +} + + +void UBThumbnailWidget::mouseReleaseEvent(QMouseEvent *event) +{ + int elapsedTimeSincePress = mClickTime.elapsed(); + deleteLasso(); + QGraphicsView::mouseReleaseEvent(event); + + if(elapsedTimeSincePress < STARTDRAGTIME) { + emit mouseClick(itemAt(event->pos()), 0); + } +} + + +void UBThumbnailWidget::keyPressEvent(QKeyEvent *event) +{ + if (mLastSelectedThumbnail) + { + QGraphicsItem *lastSelectedGraphicsItem = dynamic_cast(mLastSelectedThumbnail); + if (!lastSelectedGraphicsItem) return; + int startSelectionIndex = mGraphicItems.indexOf(lastSelectedGraphicsItem); + int previousSelectedThumbnailIndex = startSelectionIndex + mSelectionSpan; + + switch (event->key()) + { + case Qt::Key_Down: + case Qt::Key_Up: + { + if (rowCount() <= 1) break; + if (Qt::ShiftModifier & event->modifiers()) + { + int endSelectionIndex; + if (Qt::Key_Down == event->key()) + { + endSelectionIndex = previousSelectedThumbnailIndex + columnCount(); + if (endSelectionIndex >= mGraphicItems.count()) break; + } + else + { + endSelectionIndex = previousSelectedThumbnailIndex - columnCount(); + if (endSelectionIndex < 0) break; + } + + int startIndex = startSelectionIndex < endSelectionIndex ? startSelectionIndex : endSelectionIndex; + int count = startSelectionIndex < endSelectionIndex ? endSelectionIndex - startSelectionIndex + 1 : startSelectionIndex - endSelectionIndex + 1; + mSelectionSpan = startSelectionIndex < endSelectionIndex ? (count - 1) : - (count - 1); + selectItems(startIndex, count); + } + else + { + int toSelectIndex; + if (Qt::Key_Down == event->key()) + { + toSelectIndex = previousSelectedThumbnailIndex + columnCount(); + if (toSelectIndex >= mGraphicItems.count()) break; + } + else + { + toSelectIndex = previousSelectedThumbnailIndex - columnCount(); + if (toSelectIndex < 0) break; + } + + selectItemAt(toSelectIndex, Qt::ControlModifier & event->modifiers()); + mSelectionSpan = 0; + } + } + break; + + case Qt::Key_Left: + case Qt::Key_Right: + { + QGraphicsItem *previousSelectedItem = mGraphicItems.at(previousSelectedThumbnailIndex); + UBThumbnail *previousSelectedThumbnail = dynamic_cast(previousSelectedItem); + if (!previousSelectedThumbnail) break; + + if (Qt::Key_Left == event->key()) + { + if (0 == previousSelectedThumbnail->column()) break; + } + else + { + if (previousSelectedThumbnail->column() == columnCount() - 1 || + previousSelectedThumbnailIndex == mGraphicItems.count() - 1) break; + } + + if (Qt::ShiftModifier & event->modifiers()) + { + int endSelectionIndex; + if (Qt::Key_Left == event->key()) + { + endSelectionIndex = previousSelectedThumbnailIndex - 1; + if (endSelectionIndex < 0) break; + } + else + { + endSelectionIndex = previousSelectedThumbnailIndex + 1; + if (endSelectionIndex >= mGraphicItems.count()) break; + } + + int startIndex = startSelectionIndex < endSelectionIndex ? startSelectionIndex : endSelectionIndex; + int count = startSelectionIndex < endSelectionIndex ? endSelectionIndex - startSelectionIndex + 1 : startSelectionIndex - endSelectionIndex + 1; + mSelectionSpan = startSelectionIndex < endSelectionIndex ? (count - 1) : - (count - 1); + selectItems(startIndex, count); + } + else + { + if (Qt::Key_Left == event->key()) + selectItemAt(previousSelectedThumbnailIndex - 1, Qt::ControlModifier & event->modifiers()); + else + selectItemAt(previousSelectedThumbnailIndex + 1, Qt::ControlModifier & event->modifiers()); + + mSelectionSpan = 0; + } + } + break; + + case Qt::Key_Home: + { + if (Qt::ShiftModifier & event->modifiers()) + { + mSelectionSpan = - startSelectionIndex; + selectItems(0, startSelectionIndex + 1); + } + else + { + selectItemAt(0, Qt::ControlModifier & event->modifiers()); + mSelectionSpan = 0; + } + } + break; + + case Qt::Key_End: + { + if (Qt::ShiftModifier & event->modifiers()) + { + mSelectionSpan = mGraphicItems.count() - startSelectionIndex - 1; + selectItems(startSelectionIndex, mSelectionSpan + 1); + } + else + { + selectItemAt(mGraphicItems.count() - 1, Qt::ControlModifier & event->modifiers()); + mSelectionSpan = 0; + } + } + break; + case Qt::Key_A: + { + if (Qt::ControlModifier & event->modifiers()) + selectAll(); + } + break; + } + } + QGraphicsView::keyPressEvent(event); +} + + +void UBThumbnailWidget::focusInEvent(QFocusEvent *event) +{ + Q_UNUSED(event); + + if (0 == selectedItems().count() && mGraphicItems.count() > 0 && Qt::TabFocusReason == event->reason()) + { + selectItemAt(0); + mSelectionSpan = 0; + } +} + + +void UBThumbnailWidget::resizeEvent(QResizeEvent *event) +{ + Q_UNUSED(event); + + refreshScene(); + + emit resized(); +} + + +void UBThumbnailWidget::sceneSelectionChanged() +{ + emit selectionChanged(); +} + + +void UBThumbnailWidget::selectItemAt(int pIndex, bool extend) +{ + QGraphicsItem* itemToSelect = 0; + + if (pIndex >= 0 && pIndex < mGraphicItems.size()) + itemToSelect = mGraphicItems.at(pIndex); + + foreach (QGraphicsItem* item, items()) + { + if (item == itemToSelect) + { + mLastSelectedThumbnail = dynamic_cast(item); + item->setSelected(true); + ensureVisible(item); + } + else if (!extend) + { + item->setSelected(false); + } + } +} + +void UBThumbnailWidget::unselectItemAt(int pIndex) +{ + if (pIndex >= 0 && pIndex < mGraphicItems.size()) + { + QGraphicsItem *itemToUnselect = mGraphicItems.at(pIndex); + itemToUnselect->setSelected(false); + } +} + + +void UBThumbnailWidget::selectItems(int startIndex, int count) +{ + for (int i = 0; i < mGraphicItems.count(); i++) + { + mGraphicItems.at(i)->setSelected(i >= startIndex && i < startIndex + count); + } +} + + +void UBThumbnailWidget::selectAll() +{ + foreach (QGraphicsItem* item, mGraphicItems) + { + item->setSelected(true); + } +} + +int UBThumbnailWidget::rowCount() const +{ + UBThumbnail *lastThumbnail = dynamic_cast(mGraphicItems.last()); + return lastThumbnail ? lastThumbnail->row() + 1 : 0; +} + +int UBThumbnailWidget::columnCount() const +{ + UBThumbnail *lastThumbnail = dynamic_cast(mGraphicItems.last()); + if (!lastThumbnail) return 0; + int lastRow = lastThumbnail->row(); + int lastColumn = lastThumbnail->column(); + return lastRow > 0 ? (mGraphicItems.count() - lastColumn - 1) / lastRow : mGraphicItems.count(); +} + + +void UBThumbnailWidget::mouseDoubleClickEvent(QMouseEvent * event) +{ + QGraphicsItem* item = itemAt(event->pos()); + + if (item) + { + int index = mGraphicItems.indexOf(item); + emit mouseDoubleClick(item, index); + } +} + + +bool UBThumbnailWidget::thumbnailLessThan(QGraphicsItem* item1, QGraphicsItem* item2) +{ + UBThumbnail *thumbnail1 = dynamic_cast(item1); + UBThumbnail *thumbnail2 = dynamic_cast(item2); + if (thumbnail1 && thumbnail2) + { + if (thumbnail1->row() != thumbnail2->row()) + return thumbnail1->row() < thumbnail2->row(); + else + return thumbnail1->column() < thumbnail2->column(); + } + return false; +} + +void UBThumbnailWidget::deleteLasso() +{ + if (mLassoRectItem && scene()) + { + scene()->removeItem(mLassoRectItem); + delete mLassoRectItem; + mLassoRectItem = 0; + } +} + + +UBThumbnail::UBThumbnail() + : mAddedToScene(false) +{ + mSelectionItem = new QGraphicsRectItem(0, 0, 0, 0); + mSelectionItem->setPen(QPen(UBSettings::treeViewBackgroundColor, 8)); + // TODO UB 4.x fix nasty dependencies : 8 is a bit less than half of UBThumbnailWidget.mSpacing +} + +UBThumbnail::~UBThumbnail() +{ + if (mSelectionItem && !mAddedToScene) + delete mSelectionItem; +} + + +UBSceneThumbnailNavigPixmap::UBSceneThumbnailNavigPixmap(const QPixmap& pix, UBDocumentProxy* proxy, int pSceneIndex) + : UBSceneThumbnailPixmap(pix, proxy, pSceneIndex) + , bButtonsVisible(false) + , bCanDelete(false) + , bCanMoveUp(false) + , bCanMoveDown(false) +{ + setAcceptsHoverEvents(true); + setFlag(QGraphicsItem::ItemIsSelectable, true); +} + +UBSceneThumbnailNavigPixmap::~UBSceneThumbnailNavigPixmap() +{ + +} + +void UBSceneThumbnailNavigPixmap::hoverEnterEvent(QGraphicsSceneHoverEvent *event) +{ + event->accept(); + updateButtonsState(); + update(); +} + +void UBSceneThumbnailNavigPixmap::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) +{ + event->accept(); + bButtonsVisible = false; + update(); +} + +void UBSceneThumbnailNavigPixmap::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + Q_UNUSED(option); + Q_UNUSED(widget); + + UBSceneThumbnailPixmap::paint(painter, option, widget); + if(bButtonsVisible) + { + if(bCanDelete) + painter->drawPixmap(0, 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/close.svg")); + else + painter->drawPixmap(0, 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/closeDisabled.svg")); + if(bCanMoveUp) + painter->drawPixmap(BUTTONSIZE + BUTTONSPACING, 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/moveUp.svg")); + else + painter->drawPixmap(BUTTONSIZE + BUTTONSPACING, 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/moveUpDisabled.svg")); + if(bCanMoveDown) + painter->drawPixmap(2*(BUTTONSIZE + BUTTONSPACING), 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/menu.svg")); + else + painter->drawPixmap(2*(BUTTONSIZE + BUTTONSPACING), 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/menuDisabled.svg")); + } +} + +void UBSceneThumbnailNavigPixmap::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + QPointF p = event->pos(); + + // Here we check the position of the click and verify if it has to trig an action or not. + if(bCanDelete && p.x() >= 0 && p.x() <= BUTTONSIZE && p.y() >= 0 && p.y() <= BUTTONSIZE) + { + deletePage(); + } + if(bCanMoveUp && p.x() >= BUTTONSIZE + BUTTONSPACING && p.x() <= 2*BUTTONSIZE + BUTTONSPACING && p.y() >= 0 && p.y() <= BUTTONSIZE) + { + moveUpPage(); + } + if(bCanMoveDown && p.x() >= 2*(BUTTONSIZE + BUTTONSPACING) && p.x() <= 2*(BUTTONSIZE + BUTTONSPACING) + BUTTONSIZE && p.y() >= 0 && p.y() <= BUTTONSIZE) + { + moveDownPage(); + } + event->accept(); +} + +void UBSceneThumbnailNavigPixmap::updateButtonsState() +{ + bCanDelete = false; + bCanMoveUp = false; + bCanMoveDown = false; + + UBDocumentProxy* p = proxy(); + if(NULL != p) + { + int iNbPages = p->pageCount(); + if(1 < iNbPages) + { + bCanDelete = true; + if(sceneIndex() > 0) + { + bCanMoveUp = true; + } + if(sceneIndex() != iNbPages - 1) + { + bCanMoveDown = true; + } + } + } + + if(bCanDelete || bCanMoveUp || bCanMoveDown) + { + bButtonsVisible = true; + } +} + +void UBSceneThumbnailNavigPixmap::deletePage() +{ + QList itemsToDelete; + itemsToDelete << this; + + UBApplication::documentController->deletePages(itemsToDelete); +} + +void UBSceneThumbnailNavigPixmap::moveUpPage() +{ + UBApplication::documentController->moveSceneToIndex(proxy(), sceneIndex(), sceneIndex() - 1); +} + +void UBSceneThumbnailNavigPixmap::moveDownPage() +{ + UBApplication::documentController->moveSceneToIndex(proxy(), sceneIndex(), sceneIndex() + 1); +} + +void UBImgTextThumbnailElement::Place(int row, int col, qreal width, qreal height) +{ + int labelSpacing = 0; + if(this->caption) + { + QFontMetrics fm(this->caption->font()); + labelSpacing = UBSettings::thumbnailSpacing + fm.height(); + } + if(this->thumbnail) + { + int w = this->thumbnail->boundingRect().width(); + int h = this->thumbnail->boundingRect().height(); + + qreal scaleWidth = width / w; + qreal scaleHeight = height / h; + qreal scaleFactor = qMin(scaleWidth, scaleHeight); + UBThumbnail* pix = dynamic_cast(this->thumbnail); + + if(pix) + { + scaleFactor = qMin(scaleFactor, 1.0); + } + + QTransform transform; + transform.scale(scaleFactor, scaleFactor); + + // Apply the scaling + this->thumbnail->setTransform(transform); + this->thumbnail->setFlag(QGraphicsItem::ItemIsSelectable, true); + + if(pix) + { + pix->setColumn(col); + pix->setRow(row); + } + + QPointF pos(border + (width - w * scaleFactor) / 2 + col * (width + border), + border + row * (height + border + labelSpacing) + (height - h * scaleFactor) / 2); + + this->thumbnail->setPos(pos); + + if(this->caption) + { + QFontMetrics fm(this->caption->font()); + QString elidedText = fm.elidedText(this->caption->toPlainText(), Qt::ElideRight, width); + + this->caption->setPlainText(elidedText); + this->caption->setWidth(fm.width(elidedText) + 2 * this->caption->document()->documentMargin()); + pos.setY(pos.y() + (height + h * scaleFactor) / 2 + 5); // What is this 5 ?? + qreal labelWidth = fm.width(elidedText); + pos.setX(border + (width - labelWidth) / 2 + col * (width + border)); + this->caption->setPos(pos); + } + } +} diff --git a/src/gui/UBThumbnailWidget.h b/src/gui/UBThumbnailWidget.h index e00029c5..2ad70c37 100644 --- a/src/gui/UBThumbnailWidget.h +++ b/src/gui/UBThumbnailWidget.h @@ -1,421 +1,423 @@ -/* - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef UBTHUMBNAILWIDGET_H_ -#define UBTHUMBNAILWIDGET_H_ - -#include -#include -#include -#include - -#include "frameworks/UBCoreGraphicsScene.h" -#include "core/UBSettings.h" -#include "domain/UBItem.h" - -#define STARTDRAGTIME 1000000 -#define BUTTONSIZE 48 -#define BUTTONSPACING 5 - -class UBDocumentProxy; -class UBThumbnailTextItem; -class UBThumbnail; - -class UBThumbnailWidget : public QGraphicsView -{ - Q_OBJECT; - - public: - UBThumbnailWidget(QWidget* parent); - virtual ~UBThumbnailWidget(); - - QList selectedItems(); - void selectItemAt(int pIndex, bool extend = false); - void unselectItemAt(int pIndex); - - qreal thumbnailWidth() - { - return mThumbnailWidth; - } - - void setBackgroundBrush(const QBrush& brush) - { - mThumbnailsScene.setBackgroundBrush(brush); - } - - public slots: - void setThumbnailWidth(qreal pThumbnailWidth); - void setSpacing(qreal pSpacing); - virtual void setGraphicsItems(const QList& pGraphicsItems, const QList& pItemPaths, const QStringList pLabels = QStringList(), const QString& pMimeType = QString("")); - void refreshScene(); - void sceneSelectionChanged(); - - signals: - void resized(); - void selectionChanged(); - void mouseDoubleClick(QGraphicsItem* item, int index); - void mouseClick(QGraphicsItem* item, int index); - - - protected: - virtual void mousePressEvent(QMouseEvent *event); - virtual void mouseMoveEvent(QMouseEvent *event); - virtual void mouseReleaseEvent(QMouseEvent *event); - virtual void resizeEvent(QResizeEvent * event); - void mouseDoubleClickEvent(QMouseEvent * event); - - virtual void keyPressEvent(QKeyEvent *event); - virtual void focusInEvent(QFocusEvent *event); - - QList mGraphicItems; - QList mLabelsItems; - QPointF mMousePressScenePos; - QPoint mMousePressPos; - - protected: - qreal spacing() { return mSpacing; } - QList mItemsPaths; - QStringList mLabels; - bool bSelectionInProgress; - bool bCanDrag; - - private: - void selectAll(); - void unselectAll(); - void selectItems(int startIndex, int count); - int rowCount() const; - int columnCount() const; - - static bool thumbnailLessThan(QGraphicsItem* item1, QGraphicsItem* item2); - - void deleteLasso(); - - UBCoreGraphicsScene mThumbnailsScene; - - QString mMimeType; - - qreal mThumbnailWidth; - qreal mThumbnailHeight; - qreal mSpacing; - - UBThumbnail *mLastSelectedThumbnail; - int mSelectionSpan; - QGraphicsRectItem *mLassoRectItem; - QList mSelectedThumbnailItems; - QTime mClickTime; -}; - - -class UBThumbnail -{ - public: - UBThumbnail(); - - virtual ~UBThumbnail(); - - QStyleOptionGraphicsItem muteStyleOption(const QStyleOptionGraphicsItem *option) - { - // Never draw the rubber band, we draw our custom selection with the DelegateFrame - QStyleOptionGraphicsItem styleOption = QStyleOptionGraphicsItem(*option); - styleOption.state &= ~QStyle::State_Selected; - - return styleOption; - } - - virtual void itemChange(QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value) - { - Q_UNUSED(value); - - if ((change == QGraphicsItem::ItemSelectedHasChanged - || change == QGraphicsItem::ItemTransformHasChanged - || change == QGraphicsItem::ItemPositionHasChanged) - && item->scene()) - { - if (item->isSelected()) - { - if (!mSelectionItem->scene()) - { - item->scene()->addItem(mSelectionItem); - mSelectionItem->setZValue(item->zValue() - 1); -// UBGraphicsItem::assignZValue(mSelectionItem, item->zValue() - 1); - mAddedToScene = true; - } - - mSelectionItem->setRect( - item->sceneBoundingRect().x() - 5, - item->sceneBoundingRect().y() - 5, - item->sceneBoundingRect().width() + 10, - item->sceneBoundingRect().height() + 10); - - mSelectionItem->show(); - - } - else - { - mSelectionItem->hide(); - } - } - } - - int column() { return mColumn; } - void setColumn(int column) { mColumn = column; } - int row() { return mRow; } - void setRow(int row) { mRow = row; } - - protected: - QGraphicsRectItem *mSelectionItem; - private: - bool mAddedToScene; - - int mColumn; - int mRow; -}; - - -class UBThumbnailSvg : public QGraphicsSvgItem, public UBThumbnail -{ - public: - UBThumbnailSvg(const QString& path) - : QGraphicsSvgItem(path) - { - setFlag(QGraphicsItem::ItemSendsGeometryChanges, true); - } - - virtual ~UBThumbnailSvg() - { - // NOOP - } - - virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) - { - QStyleOptionGraphicsItem styleOption = UBThumbnail::muteStyleOption(option); - QGraphicsSvgItem::paint(painter, &styleOption, widget); - } - - virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value) - { - UBThumbnail::itemChange(this, change, value); - return QGraphicsSvgItem::itemChange(change, value); - } - -}; - - -class UBThumbnailPixmap : public QGraphicsPixmapItem, public UBThumbnail -{ - public: - UBThumbnailPixmap(const QPixmap& pix) - : QGraphicsPixmapItem(pix) - { - setTransformationMode(Qt::SmoothTransformation); // UB 4.3 may be expensive -- make configurable - setShapeMode(QGraphicsPixmapItem::BoundingRectShape); - setFlag(QGraphicsItem::ItemSendsGeometryChanges, true); - } - - virtual ~UBThumbnailPixmap() - { - // NOOP - } - - virtual QPainterPath shape () const - { - QPainterPath path; - path.addRect(boundingRect()); - return path; - } - - - virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) - { - QStyleOptionGraphicsItem styleOption = UBThumbnail::muteStyleOption(option); - QGraphicsPixmapItem::paint(painter, &styleOption, widget); - } - - virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value) - { - UBThumbnail::itemChange(this, change, value); - return QGraphicsPixmapItem::itemChange(change, value); - } -}; - - -class UBSceneThumbnailPixmap : public UBThumbnailPixmap -{ - public: - UBSceneThumbnailPixmap(const QPixmap& pix, UBDocumentProxy* proxy, int pSceneIndex) - : UBThumbnailPixmap(pix) - , mProxy(proxy) - , mSceneIndex(pSceneIndex) - { - // NOOP - } - - virtual ~UBSceneThumbnailPixmap() - { - // NOOP - } - - UBDocumentProxy* proxy() - { - return mProxy; - } - - int sceneIndex() - { - return mSceneIndex; - } - - void highlight() - { - //NOOP - } - - private: - UBDocumentProxy* mProxy; - int mSceneIndex; -}; - -class UBSceneThumbnailNavigPixmap : public UBSceneThumbnailPixmap -{ - public: - UBSceneThumbnailNavigPixmap(const QPixmap& pix, UBDocumentProxy* proxy, int pSceneIndex); - ~UBSceneThumbnailNavigPixmap(); - - protected: - void hoverEnterEvent(QGraphicsSceneHoverEvent *event); - void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); - void mousePressEvent(QGraphicsSceneMouseEvent *event); - - private: - void updateButtonsState(); - void deletePage(); - void moveUpPage(); - void moveDownPage(); - - bool bButtonsVisible; - bool bCanDelete; - bool bCanMoveUp; - bool bCanMoveDown; -}; - -class UBThumbnailVideo : public UBThumbnailPixmap -{ - public: - UBThumbnailVideo(const QUrl &path) - : UBThumbnailPixmap(QPixmap(":/images/movie.svg")) - , mPath(path) - { - // NOOP - } - - virtual ~UBThumbnailVideo() - { - // NOOP - } - - QUrl path() - { - return mPath; - } - - private: - - QUrl mPath; -}; - -class UBThumbnailTextItem : public QGraphicsTextItem -{ - public: - UBThumbnailTextItem(const QString& text) - : QGraphicsTextItem(text) - , mUnelidedText(text) - , mIsHighlighted(false) - { - setFlag(QGraphicsItem::ItemSendsGeometryChanges, true); - } - - QRectF boundingRect() const { return QRectF(QPointF(0.0, 0.0), QSize(mWidth, QFontMetricsF(font()).height() + 5));} - - void setWidth(qreal pWidth) - { - if (mWidth != pWidth) - { - prepareGeometryChange(); - mWidth = pWidth; - computeText(); - } - }; - - qreal width() {return mWidth;} - - void highlight() - { - if (!mIsHighlighted) - { - mIsHighlighted = true; - computeText(); - } - } - - void computeText() - { - QFontMetricsF fm(font()); - QString elidedText = fm.elidedText(mUnelidedText, Qt::ElideRight, mWidth); - - if (mIsHighlighted) - { - setHtml("" + elidedText + ""); - } - else - { - setPlainText(elidedText); - } - } - - private: - qreal mWidth; - QString mUnelidedText; - bool mIsHighlighted; -}; - -class UBImgTextThumbnailElement -{ -private: - QGraphicsItem* thumbnail; - UBThumbnailTextItem* caption; - int border; - -public: - UBImgTextThumbnailElement(QGraphicsItem* thumb, UBThumbnailTextItem* text): border(0) - { - this->thumbnail = thumb; - this->caption = text; - } - - QGraphicsItem* getThumbnail() const { return this->thumbnail; } - void setThumbnail(QGraphicsItem* newGItem) { this->thumbnail = newGItem; } - - UBThumbnailTextItem* getCaption() const { return this->caption; } - void setCaption(UBThumbnailTextItem* newcaption) { this->caption = newcaption; } - - void Place(int row, int col, qreal width, qreal height); - - int getBorder() const { return this->border; } - void setBorder(int newBorder) { this->border = newBorder; } -}; - - -#endif /* UBTHUMBNAILWIDGET_H_ */ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef UBTHUMBNAILWIDGET_H_ +#define UBTHUMBNAILWIDGET_H_ + +#include +#include +#include +#include + +#include "frameworks/UBCoreGraphicsScene.h" +#include "core/UBSettings.h" +#include "domain/UBItem.h" + +#define STARTDRAGTIME 1000000 +#define BUTTONSIZE 48 +#define BUTTONSPACING 5 + +class UBDocumentProxy; +class UBThumbnailTextItem; +class UBThumbnail; + +class UBThumbnailWidget : public QGraphicsView +{ + Q_OBJECT; + + public: + UBThumbnailWidget(QWidget* parent); + virtual ~UBThumbnailWidget(); + + QList selectedItems(); + void selectItemAt(int pIndex, bool extend = false); + void unselectItemAt(int pIndex); + + qreal thumbnailWidth() + { + return mThumbnailWidth; + } + + void setBackgroundBrush(const QBrush& brush) + { + mThumbnailsScene.setBackgroundBrush(brush); + } + + public slots: + void setThumbnailWidth(qreal pThumbnailWidth); + void setSpacing(qreal pSpacing); + virtual void setGraphicsItems(const QList& pGraphicsItems, const QList& pItemPaths, const QStringList pLabels = QStringList(), const QString& pMimeType = QString("")); + void refreshScene(); + void sceneSelectionChanged(); + + signals: + void resized(); + void selectionChanged(); + void mouseDoubleClick(QGraphicsItem* item, int index); + void mouseClick(QGraphicsItem* item, int index); + + + protected: + virtual void mousePressEvent(QMouseEvent *event); + virtual void mouseMoveEvent(QMouseEvent *event); + virtual void mouseReleaseEvent(QMouseEvent *event); + virtual void resizeEvent(QResizeEvent * event); + void mouseDoubleClickEvent(QMouseEvent * event); + + virtual void keyPressEvent(QKeyEvent *event); + virtual void focusInEvent(QFocusEvent *event); + + QList mGraphicItems; + QList mLabelsItems; + QPointF mMousePressScenePos; + QPoint mMousePressPos; + + protected: + qreal spacing() { return mSpacing; } + QList mItemsPaths; + QStringList mLabels; + bool bSelectionInProgress; + bool bCanDrag; + + private: + void selectAll(); + void selectItems(int startIndex, int count); + int rowCount() const; + int columnCount() const; + + static bool thumbnailLessThan(QGraphicsItem* item1, QGraphicsItem* item2); + + void deleteLasso(); + + UBCoreGraphicsScene mThumbnailsScene; + + QString mMimeType; + + QPointF prevMoveMousePos; + + qreal mThumbnailWidth; + qreal mThumbnailHeight; + qreal mSpacing; + + UBThumbnail *mLastSelectedThumbnail; + int mSelectionSpan; + QGraphicsRectItem *mLassoRectItem; + QSet mSelectedThumbnailItems; + QSet mPreviouslyIncrementalSelectedItems; + QTime mClickTime; +}; + + +class UBThumbnail +{ + public: + UBThumbnail(); + + virtual ~UBThumbnail(); + + QStyleOptionGraphicsItem muteStyleOption(const QStyleOptionGraphicsItem *option) + { + // Never draw the rubber band, we draw our custom selection with the DelegateFrame + QStyleOptionGraphicsItem styleOption = QStyleOptionGraphicsItem(*option); + styleOption.state &= ~QStyle::State_Selected; + + return styleOption; + } + + virtual void itemChange(QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value) + { + Q_UNUSED(value); + + if ((change == QGraphicsItem::ItemSelectedHasChanged + || change == QGraphicsItem::ItemTransformHasChanged + || change == QGraphicsItem::ItemPositionHasChanged) + && item->scene()) + { + if (item->isSelected()) + { + if (!mSelectionItem->scene()) + { + item->scene()->addItem(mSelectionItem); + mSelectionItem->setZValue(item->zValue() - 1); +// UBGraphicsItem::assignZValue(mSelectionItem, item->zValue() - 1); + mAddedToScene = true; + } + + mSelectionItem->setRect( + item->sceneBoundingRect().x() - 5, + item->sceneBoundingRect().y() - 5, + item->sceneBoundingRect().width() + 10, + item->sceneBoundingRect().height() + 10); + + mSelectionItem->show(); + + } + else + { + mSelectionItem->hide(); + } + } + } + + int column() { return mColumn; } + void setColumn(int column) { mColumn = column; } + int row() { return mRow; } + void setRow(int row) { mRow = row; } + + protected: + QGraphicsRectItem *mSelectionItem; + private: + bool mAddedToScene; + + int mColumn; + int mRow; +}; + + +class UBThumbnailSvg : public QGraphicsSvgItem, public UBThumbnail +{ + public: + UBThumbnailSvg(const QString& path) + : QGraphicsSvgItem(path) + { + setFlag(QGraphicsItem::ItemSendsGeometryChanges, true); + } + + virtual ~UBThumbnailSvg() + { + // NOOP + } + + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) + { + QStyleOptionGraphicsItem styleOption = UBThumbnail::muteStyleOption(option); + QGraphicsSvgItem::paint(painter, &styleOption, widget); + } + + virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value) + { + UBThumbnail::itemChange(this, change, value); + return QGraphicsSvgItem::itemChange(change, value); + } + +}; + + +class UBThumbnailPixmap : public QGraphicsPixmapItem, public UBThumbnail +{ + public: + UBThumbnailPixmap(const QPixmap& pix) + : QGraphicsPixmapItem(pix) + { + setTransformationMode(Qt::SmoothTransformation); // UB 4.3 may be expensive -- make configurable + setShapeMode(QGraphicsPixmapItem::BoundingRectShape); + setFlag(QGraphicsItem::ItemSendsGeometryChanges, true); + } + + virtual ~UBThumbnailPixmap() + { + // NOOP + } + + virtual QPainterPath shape () const + { + QPainterPath path; + path.addRect(boundingRect()); + return path; + } + + + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) + { + QStyleOptionGraphicsItem styleOption = UBThumbnail::muteStyleOption(option); + QGraphicsPixmapItem::paint(painter, &styleOption, widget); + } + + virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value) + { + UBThumbnail::itemChange(this, change, value); + return QGraphicsPixmapItem::itemChange(change, value); + } +}; + + +class UBSceneThumbnailPixmap : public UBThumbnailPixmap +{ + public: + UBSceneThumbnailPixmap(const QPixmap& pix, UBDocumentProxy* proxy, int pSceneIndex) + : UBThumbnailPixmap(pix) + , mProxy(proxy) + , mSceneIndex(pSceneIndex) + { + // NOOP + } + + virtual ~UBSceneThumbnailPixmap() + { + // NOOP + } + + UBDocumentProxy* proxy() + { + return mProxy; + } + + int sceneIndex() + { + return mSceneIndex; + } + + void highlight() + { + //NOOP + } + + private: + UBDocumentProxy* mProxy; + int mSceneIndex; +}; + +class UBSceneThumbnailNavigPixmap : public UBSceneThumbnailPixmap +{ + public: + UBSceneThumbnailNavigPixmap(const QPixmap& pix, UBDocumentProxy* proxy, int pSceneIndex); + ~UBSceneThumbnailNavigPixmap(); + + protected: + void hoverEnterEvent(QGraphicsSceneHoverEvent *event); + void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + void mousePressEvent(QGraphicsSceneMouseEvent *event); + + private: + void updateButtonsState(); + void deletePage(); + void moveUpPage(); + void moveDownPage(); + + bool bButtonsVisible; + bool bCanDelete; + bool bCanMoveUp; + bool bCanMoveDown; +}; + +class UBThumbnailVideo : public UBThumbnailPixmap +{ + public: + UBThumbnailVideo(const QUrl &path) + : UBThumbnailPixmap(QPixmap(":/images/movie.svg")) + , mPath(path) + { + // NOOP + } + + virtual ~UBThumbnailVideo() + { + // NOOP + } + + QUrl path() + { + return mPath; + } + + private: + + QUrl mPath; +}; + +class UBThumbnailTextItem : public QGraphicsTextItem +{ + public: + UBThumbnailTextItem(const QString& text) + : QGraphicsTextItem(text) + , mUnelidedText(text) + , mIsHighlighted(false) + { + setFlag(QGraphicsItem::ItemSendsGeometryChanges, true); + } + + QRectF boundingRect() const { return QRectF(QPointF(0.0, 0.0), QSize(mWidth, QFontMetricsF(font()).height() + 5));} + + void setWidth(qreal pWidth) + { + if (mWidth != pWidth) + { + prepareGeometryChange(); + mWidth = pWidth; + computeText(); + } + }; + + qreal width() {return mWidth;} + + void highlight() + { + if (!mIsHighlighted) + { + mIsHighlighted = true; + computeText(); + } + } + + void computeText() + { + QFontMetricsF fm(font()); + QString elidedText = fm.elidedText(mUnelidedText, Qt::ElideRight, mWidth); + + if (mIsHighlighted) + { + setHtml("" + elidedText + ""); + } + else + { + setPlainText(elidedText); + } + } + + private: + qreal mWidth; + QString mUnelidedText; + bool mIsHighlighted; +}; + +class UBImgTextThumbnailElement +{ +private: + QGraphicsItem* thumbnail; + UBThumbnailTextItem* caption; + int border; + +public: + UBImgTextThumbnailElement(QGraphicsItem* thumb, UBThumbnailTextItem* text): border(0) + { + this->thumbnail = thumb; + this->caption = text; + } + + QGraphicsItem* getThumbnail() const { return this->thumbnail; } + void setThumbnail(QGraphicsItem* newGItem) { this->thumbnail = newGItem; } + + UBThumbnailTextItem* getCaption() const { return this->caption; } + void setCaption(UBThumbnailTextItem* newcaption) { this->caption = newcaption; } + + void Place(int row, int col, qreal width, qreal height); + + int getBorder() const { return this->border; } + void setBorder(int newBorder) { this->border = newBorder; } +}; + + +#endif /* UBTHUMBNAILWIDGET_H_ */