From 7b1f64eabf0147f3fa2551f2c25673dd64157bf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Sun, 24 Sep 2017 21:25:12 +0200 Subject: [PATCH] merge 1.4-dev + thumbnail views & fixes --- OpenBoard.pro | 7 +- resources/OpenBoard.qrc | 2 + resources/etc/OpenBoard.config | 5 +- resources/forms/brushProperties.ui | 75 +++- resources/images/moveDown.svg | 8 + resources/images/moveDownDisabled.svg | 64 ++++ resources/style.qss | 2 +- src/board/UBBoardController.cpp | 34 +- src/board/UBBoardPaletteManager.cpp | 2 - src/board/UBBoardView.cpp | 7 +- src/core/UBApplication.cpp | 3 + src/core/UBPersistenceManager.cpp | 1 - src/core/UBPreferencesController.cpp | 12 + src/core/UBPreferencesController.h | 1 + src/core/UBSettings.cpp | 17 + src/core/UBSettings.h | 10 + src/document/UBDocumentContainer.cpp | 20 +- src/document/UBDocumentContainer.h | 7 + src/document/UBDocumentController.cpp | 29 +- src/domain/UBDragableThumbnail.cpp | 128 +++++++ src/domain/UBDragableThumbnail.h | 31 ++ src/domain/UBGraphicsPolygonItem.cpp | 2 +- src/domain/UBGraphicsPolygonItem.h | 2 + src/domain/UBGraphicsScene.cpp | 87 +++++ src/domain/UBGraphicsScene.h | 5 + src/domain/UBGraphicsStroke.cpp | 4 +- src/domain/UBGraphicsTextItem.cpp | 5 + src/domain/UBGraphicsTextItem.h | 2 + src/domain/UBGraphicsTextItemDelegate.cpp | 10 +- src/gui/UBBoardThumbnailsView.cpp | 301 +++++++++++++++ ...entNavigator.h => UBBoardThumbnailsView.h} | 72 ++-- src/gui/UBDocumentNavigator.cpp | 311 --------------- src/gui/UBDocumentThumbnailWidget.cpp | 16 +- src/gui/UBDocumentThumbnailWidget.h | 2 +- src/gui/UBPageNavigationWidget.cpp | 2 +- src/gui/UBPageNavigationWidget.h | 4 +- src/gui/UBThumbnailView.cpp | 41 +- src/gui/UBThumbnailView.h | 17 +- src/gui/UBThumbnailWidget.cpp | 283 ++++++++------ src/gui/UBThumbnailWidget.h | 354 ++++++++++++------ src/gui/gui.pri | 8 +- src/tools/UBGraphicsCompass.cpp | 1 + 42 files changed, 1331 insertions(+), 663 deletions(-) create mode 100644 resources/images/moveDown.svg create mode 100644 resources/images/moveDownDisabled.svg create mode 100644 src/domain/UBDragableThumbnail.cpp create mode 100644 src/domain/UBDragableThumbnail.h create mode 100644 src/gui/UBBoardThumbnailsView.cpp rename src/gui/{UBDocumentNavigator.h => UBBoardThumbnailsView.h} (52%) delete mode 100644 src/gui/UBDocumentNavigator.cpp diff --git a/OpenBoard.pro b/OpenBoard.pro index 4c838820..6559b873 100644 --- a/OpenBoard.pro +++ b/OpenBoard.pro @@ -11,9 +11,10 @@ CONFIG += debug_and_release \ VERSION_MAJ = 1 VERSION_MIN = 4 VERSION_PATCH = 0 -VERSION_TYPE = a # a = alpha, b = beta, rc = release candidate, r = release, other => error +VERSION_TYPE = b # a = alpha, b = beta, rc = release candidate, r = release, other => error VERSION_BUILD = 1 + VERSION = "$${VERSION_MAJ}.$${VERSION_MIN}.$${VERSION_PATCH}-$${VERSION_TYPE}.$${VERSION_BUILD}" equals(VERSION_TYPE, r) { @@ -454,3 +455,7 @@ INSTALLS = UB_ETC \ UB_LIBRARY \ UB_THIRDPARTY_INTERACTIVE +DISTFILES += \ + resources/images/moveDown.svg \ + resources/images/moveDownDisabled.svg + diff --git a/resources/OpenBoard.qrc b/resources/OpenBoard.qrc index 1a2f3d1e..df2116b3 100644 --- a/resources/OpenBoard.qrc +++ b/resources/OpenBoard.qrc @@ -339,6 +339,8 @@ images/left_arrow.png images/right_arrow.png images/moveUp.svg + images/moveDown.svg + images/moveDownDisabled.svg images/closeDisabled.svg images/menuDisabled.svg images/moveUpDisabled.svg diff --git a/resources/etc/OpenBoard.config b/resources/etc/OpenBoard.config index 2c505d04..c8762800 100644 --- a/resources/etc/OpenBoard.config +++ b/resources/etc/OpenBoard.config @@ -65,9 +65,10 @@ RightLibPaletteDesktopModeWidth=270 ShowEraserPreviewCircle=true ShowMarkerPreviewCircle=true ShowPenPreviewCircle=true +PenPreviewFromSize=5 ShowToolsPalette=false -SimplifyMarkerStrokes=true -SimplifyPenStrokes=true +SimplifyMarkerStrokes=false +SimplifyPenStrokes=false SimplifyPenStrokesThresholdAngle=3 SimplifyPenStrokesThresholdWidthDifference=2 StartupKeyboardLocale=0 diff --git a/resources/forms/brushProperties.ui b/resources/forms/brushProperties.ui index 4f9d7268..f149562f 100644 --- a/resources/forms/brushProperties.ui +++ b/resources/forms/brushProperties.ui @@ -497,7 +497,80 @@ - + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Show preview circle from + + + + + + + + + + px + + + + + + + Qt::Horizontal + + + + 198 + 20 + + + + + + + + diff --git a/resources/images/moveDown.svg b/resources/images/moveDown.svg new file mode 100644 index 00000000..16b78e93 --- /dev/null +++ b/resources/images/moveDown.svg @@ -0,0 +1,8 @@ + + + + + + + diff --git a/resources/images/moveDownDisabled.svg b/resources/images/moveDownDisabled.svg new file mode 100644 index 00000000..4894f3ae --- /dev/null +++ b/resources/images/moveDownDisabled.svg @@ -0,0 +1,64 @@ + + + +image/svg+xml + + + + \ No newline at end of file diff --git a/resources/style.qss b/resources/style.qss index e53e0ee6..92bd8d6b 100644 --- a/resources/style.qss +++ b/resources/style.qss @@ -1,5 +1,5 @@ QWidget#DockPaletteWidgetBox, -QWidget#documentNavigator, +QWidget#UBBoardThumbnailsView, QWidget#UBLibPathViewer, QWidget#UBLibNavigatorWidget, QWidget#UBLibItemProperties, diff --git a/src/board/UBBoardController.cpp b/src/board/UBBoardController.cpp index 414d146e..ea9f195a 100644 --- a/src/board/UBBoardController.cpp +++ b/src/board/UBBoardController.cpp @@ -583,6 +583,7 @@ void UBBoardController::duplicateScene(int nIndex) duplicatePages(scIndexes); insertThumbPage(nIndex); emit documentThumbnailsUpdated(this); + emit addThumbnailRequired(this, nIndex + 1); selectedDocument()->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); setActiveDocumentScene(nIndex + 1); @@ -1399,7 +1400,6 @@ UBItem *UBBoardController::downloadFinished(bool pSuccess, QUrl sourceUrl, QUrl if (result){ selectedDocument()->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); - reloadThumbnails(); } } else if (UBMimeType::OpenboardTool == itemMimeType) @@ -1542,11 +1542,11 @@ void UBBoardController::setActiveDocumentScene(UBDocumentProxy* pDocumentProxy, mActiveSceneIndex = index; setDocument(pDocumentProxy, forceReload); + emit initThumbnailsRequired(this); updateSystemScaleFactor(); mControlView->setScene(mActiveScene); - disconnect(mControlView, SIGNAL(mouseReleased()), mActiveScene, SLOT(updateSelectionFrame())); - connect(mControlView, SIGNAL(mouseReleased()), mActiveScene, SLOT(updateSelectionFrame())); + mDisplayView->setScene(mActiveScene); mActiveScene->setBackgroundZoomFactor(mControlView->transform().m11()); pDocumentProxy->setDefaultDocumentSize(mActiveScene->nominalSize()); @@ -1584,9 +1584,11 @@ void UBBoardController::moveSceneToIndex(int source, int target) selectedDocument()->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); UBPersistenceManager::persistenceManager()->persistDocumentMetadata(selectedDocument()); mMovingSceneIndex = source; + mActiveSceneIndex = target; setActiveDocumentScene(target); mMovingSceneIndex = -1; + emit activeSceneChanged(); } } @@ -1636,6 +1638,23 @@ void UBBoardController::ClearUndoStack() findUniquesItems(UBApplication::undoStack->command(i), uniqueItems); } + // Get items from clipboard in order not to delete an item that was cut + // (using source URL of graphics items as a surrogate for equality testing) + // This ensures that we can cut and paste a media item, widget, etc. from one page to the next. + QClipboard *clipboard = QApplication::clipboard(); + const QMimeData* data = clipboard->mimeData(); + QList sourceURLs; + + if (data && data->hasFormat(UBApplication::mimeTypeUniboardPageItem)) { + const UBMimeDataGraphicsItem* mimeDataGI = qobject_cast (data); + + if (mimeDataGI) { + foreach (UBItem* sourceItem, mimeDataGI->items()) { + sourceURLs << sourceItem->sourceUrl(); + } + } + } + // go through all unique items, and check, if they are on scene, or not. // if not on scene, than item can be deleted QSetIterator itUniq(uniqueItems); @@ -1647,7 +1666,12 @@ void UBBoardController::ClearUndoStack() scene = dynamic_cast(item->scene()); } - if(!scene) + bool inClipboard = false; + UBItem* ubi = dynamic_cast(item); + if (ubi && sourceURLs.contains(ubi->sourceUrl())) + inClipboard = true; + + if(!scene && !inClipboard) { if (!mActiveScene->deleteItem(item)){ delete item; @@ -1798,6 +1822,7 @@ void UBBoardController::documentSceneChanged(UBDocumentProxy* pDocumentProxy, in if(selectedDocument() == pDocumentProxy) { setActiveDocumentScene(mActiveSceneIndex); + updatePage(pIndex); } } @@ -1941,7 +1966,6 @@ void UBBoardController::persistCurrentScene(bool isAnAutomaticBackup, bool force && (mActiveScene->isModified())) { UBPersistenceManager::persistenceManager()->persistDocumentScene(selectedDocument(), mActiveScene, mActiveSceneIndex, isAnAutomaticBackup,forceImmediateSave); - updatePage(mActiveSceneIndex); } } diff --git a/src/board/UBBoardPaletteManager.cpp b/src/board/UBBoardPaletteManager.cpp index 06cec6ed..581eb6b1 100644 --- a/src/board/UBBoardPaletteManager.cpp +++ b/src/board/UBBoardPaletteManager.cpp @@ -135,7 +135,6 @@ void UBBoardPaletteManager::setupDockPaletteWidgets() //------------------------------------------------// // Create the widgets for the dock palettes - mpPageNavigWidget = new UBPageNavigationWidget(); mpCachePropWidget = new UBCachePropertiesWidget(); @@ -146,7 +145,6 @@ void UBBoardPaletteManager::setupDockPaletteWidgets() mLeftPalette = new UBLeftPalette(mContainer); // LEFT palette widgets - mpPageNavigWidget = new UBPageNavigationWidget(); mLeftPalette->registerWidget(mpPageNavigWidget); mLeftPalette->addTab(mpPageNavigWidget); diff --git a/src/board/UBBoardView.cpp b/src/board/UBBoardView.cpp index 768f90a2..97e8233c 100644 --- a/src/board/UBBoardView.cpp +++ b/src/board/UBBoardView.cpp @@ -1719,7 +1719,12 @@ void UBBoardView::setToolCursor (int tool) switch (tool) { case UBStylusTool::Pen: - controlViewport->setCursor (UBResources::resources ()->penCursor); + if (UBSettings::settings()->showPenPreviewCircle->get().toBool() && + UBSettings::settings()->currentPenWidth() >= UBSettings::settings()->penPreviewFromSize->get().toInt()) { + controlViewport->setCursor (QCursor (Qt::BlankCursor)); + } else { + controlViewport->setCursor (UBResources::resources ()->penCursor); + } break; case UBStylusTool::Eraser: controlViewport->setCursor (UBResources::resources ()->eraserCursor); diff --git a/src/core/UBApplication.cpp b/src/core/UBApplication.cpp index 9f4a8301..b6c771c9 100644 --- a/src/core/UBApplication.cpp +++ b/src/core/UBApplication.cpp @@ -58,6 +58,7 @@ #include "gui/UBMainWindow.h" #include "gui/UBResources.h" +#include "gui/UBThumbnailWidget.h" #include "adaptors/publishing/UBSvgSubsetRasterizer.h" @@ -286,6 +287,8 @@ int UBApplication::exec(const QString& pFileToImport) mainWindow->actionPaste->setShortcuts(QKeySequence::Paste); mainWindow->actionCut->setShortcuts(QKeySequence::Cut); + UBThumbnailUI::_private::initCatalog(); + connect(mainWindow->actionBoard, SIGNAL(triggered()), this, SLOT(showBoard())); connect(mainWindow->actionWeb, SIGNAL(triggered()), this, SLOT(showInternet())); connect(mainWindow->actionWeb, SIGNAL(triggered()), this, SLOT(stopScript())); diff --git a/src/core/UBPersistenceManager.cpp b/src/core/UBPersistenceManager.cpp index 41a45bba..e2dc31ea 100644 --- a/src/core/UBPersistenceManager.cpp +++ b/src/core/UBPersistenceManager.cpp @@ -744,7 +744,6 @@ UBGraphicsScene* UBPersistenceManager::loadDocumentScene(UBDocumentProxy* proxy, if (scene) mSceneCache.insert(proxy, sceneIndex, scene); } - if (cacheNeighboringScenes) { if(sceneIndex + 1 < proxy->pageCount() && !mSceneCache.contains(proxy, sceneIndex + 1)) mWorker->readScene(proxy,sceneIndex+1); diff --git a/src/core/UBPreferencesController.cpp b/src/core/UBPreferencesController.cpp index 8e787e56..4c87c6ac 100644 --- a/src/core/UBPreferencesController.cpp +++ b/src/core/UBPreferencesController.cpp @@ -165,6 +165,8 @@ void UBPreferencesController::wire() connect(mPenProperties->mediumSlider, SIGNAL(valueChanged(int)), this, SLOT(widthSliderChanged(int))); connect(mPenProperties->strongSlider, SIGNAL(valueChanged(int)), this, SLOT(widthSliderChanged(int))); connect(mPenProperties->pressureSensitiveCheckBox, SIGNAL(clicked(bool)), settings, SLOT(setPenPressureSensitive(bool))); + connect(mPenProperties->circleCheckBox, SIGNAL(clicked(bool)), settings, SLOT(setPenPreviewCircle(bool))); + connect(mPenProperties->circleSpinBox, SIGNAL(valueChanged(int)), this, SLOT(penPreviewFromSizeChanged(int))); // marker QList markerLightBackgroundColors = settings->boardMarkerLightBackgroundColors->colors(); @@ -178,6 +180,8 @@ void UBPreferencesController::wire() mMarkerProperties->pressureSensitiveCheckBox->setText(tr("Marker is pressure sensitive")); + mMarkerProperties->circleFrame->hide(); + connect(mMarkerProperties->fineSlider, SIGNAL(valueChanged(int)), this, SLOT(widthSliderChanged(int))); connect(mMarkerProperties->mediumSlider, SIGNAL(valueChanged(int)), this, SLOT(widthSliderChanged(int))); connect(mMarkerProperties->strongSlider, SIGNAL(valueChanged(int)), this, SLOT(widthSliderChanged(int))); @@ -229,6 +233,8 @@ void UBPreferencesController::init() mPenProperties->mediumSlider->setValue(settings->boardPenMediumWidth->get().toDouble() * sSliderRatio); mPenProperties->strongSlider->setValue(settings->boardPenStrongWidth->get().toDouble() * sSliderRatio); mPenProperties->pressureSensitiveCheckBox->setChecked(settings->boardPenPressureSensitive->get().toBool()); + mPenProperties->circleCheckBox->setChecked(settings->showPenPreviewCircle->get().toBool()); + mPenProperties->circleSpinBox->setValue(settings->penPreviewFromSize->get().toInt()); // marker tab mMarkerProperties->fineSlider->setValue(settings->boardMarkerFineWidth->get().toDouble() * sSliderRatio); @@ -278,6 +284,8 @@ void UBPreferencesController::defaultSettings() mPenProperties->mediumSlider->setValue(settings->boardPenMediumWidth->reset().toDouble() * sSliderRatio); mPenProperties->strongSlider->setValue(settings->boardPenStrongWidth->reset().toDouble() * sSliderRatio); mPenProperties->pressureSensitiveCheckBox->setChecked(settings->boardPenPressureSensitive->reset().toBool()); + mPenProperties->circleCheckBox->setChecked(settings->showPenPreviewCircle->reset().toBool()); + mPenProperties->circleSpinBox->setValue(settings->penPreviewFromSize->reset().toInt()); settings->boardPenLightBackgroundSelectedColors->reset(); QList lightBackgroundSelectedColors = settings->boardPenLightBackgroundSelectedColors->colors(); @@ -332,6 +340,10 @@ void UBPreferencesController::defaultSettings() } +void UBPreferencesController::penPreviewFromSizeChanged(int value) +{ + UBSettings::settings()->setPenPreviewFromSize(value); +} void UBPreferencesController::widthSliderChanged(int value) { diff --git a/src/core/UBPreferencesController.h b/src/core/UBPreferencesController.h index 3c129d03..ea4d8b32 100644 --- a/src/core/UBPreferencesController.h +++ b/src/core/UBPreferencesController.h @@ -89,6 +89,7 @@ class UBPreferencesController : public QObject void close(); void defaultSettings(); + void penPreviewFromSizeChanged(int value); void widthSliderChanged(int value); void opacitySliderChanged(int value); void colorSelected(const QColor&); diff --git a/src/core/UBSettings.cpp b/src/core/UBSettings.cpp index 1e2601be..68b29e6e 100644 --- a/src/core/UBSettings.cpp +++ b/src/core/UBSettings.cpp @@ -85,6 +85,12 @@ QColor UBSettings::markerCircleBrushColorLightBackground = QColor(255, 255, 255, QColor UBSettings::markerCirclePenColorDarkBackground = QColor(255, 255, 255, 127); QColor UBSettings::markerCirclePenColorLightBackground = QColor(0, 0, 0, 127); +QColor UBSettings::penCircleBrushColorDarkBackground = QColor(127, 127, 127, 80); +QColor UBSettings::penCircleBrushColorLightBackground = QColor(255, 255, 255, 30); + +QColor UBSettings::penCirclePenColorDarkBackground = QColor(255, 255, 255, 127); +QColor UBSettings::penCirclePenColorLightBackground = QColor(0, 0, 0, 127); + QColor UBSettings::documentSizeMarkColorDarkBackground = QColor(44, 44, 44, 200); QColor UBSettings::documentSizeMarkColorLightBackground = QColor(241, 241, 241); @@ -323,6 +329,8 @@ void UBSettings::init() showEraserPreviewCircle = new UBSetting(this, "Board", "ShowEraserPreviewCircle", true); showMarkerPreviewCircle = new UBSetting(this, "Board", "ShowMarkerPreviewCircle", true); + showPenPreviewCircle = new UBSetting(this, "Board", "ShowPenPreviewCircle", true); + penPreviewFromSize = new UBSetting(this, "Board", "PenPreviewFromSize", 5); webUseExternalBrowser = new UBSetting(this, "Web", "UseExternalBrowser", false); @@ -784,6 +792,15 @@ void UBSettings::setPenPressureSensitive(bool sensitive) boardPenPressureSensitive->set(sensitive); } +void UBSettings::setPenPreviewCircle(bool circle) +{ + showPenPreviewCircle->set(circle); +} + +void UBSettings::setPenPreviewFromSize(int size) +{ + penPreviewFromSize->set(size); +} void UBSettings::setMarkerPressureSensitive(bool sensitive) { diff --git a/src/core/UBSettings.h b/src/core/UBSettings.h index 84ae5667..7aa121d8 100644 --- a/src/core/UBSettings.h +++ b/src/core/UBSettings.h @@ -177,6 +177,12 @@ class UBSettings : public QObject static QColor markerCirclePenColorDarkBackground; static QColor markerCirclePenColorLightBackground; + static QColor penCircleBrushColorDarkBackground; + static QColor penCircleBrushColorLightBackground; + + static QColor penCirclePenColorDarkBackground; + static QColor penCirclePenColorLightBackground; + static QColor documentSizeMarkColorDarkBackground; static QColor documentSizeMarkColorLightBackground; @@ -303,6 +309,8 @@ class UBSettings : public QObject UBSetting* showEraserPreviewCircle; UBSetting* showMarkerPreviewCircle; + UBSetting* showPenPreviewCircle; + UBSetting* penPreviewFromSize; UBSetting* webUseExternalBrowser; UBSetting* webShowPageImmediatelyOnMirroredScreen; @@ -410,6 +418,8 @@ class UBSettings : public QObject void setStylusPaletteVisible(bool visible); void setPenPressureSensitive(bool sensitive); + void setPenPreviewCircle(bool sensitive); + void setPenPreviewFromSize(int size); void setMarkerPressureSensitive(bool sensitive); QVariant value ( const QString & key, const QVariant & defaultValue = QVariant() ); diff --git a/src/document/UBDocumentContainer.cpp b/src/document/UBDocumentContainer.cpp index e6f30d03..b63ee837 100644 --- a/src/document/UBDocumentContainer.cpp +++ b/src/document/UBDocumentContainer.cpp @@ -51,8 +51,9 @@ void UBDocumentContainer::setDocument(UBDocumentProxy* document, bool forceReloa if (mCurrentDocument != document || forceReload) { mCurrentDocument = document; - reloadThumbnails(); + emit documentSet(mCurrentDocument); + reloadThumbnails(); } } @@ -68,10 +69,14 @@ void UBDocumentContainer::duplicatePages(QList& pageIndexes) bool UBDocumentContainer::movePageToIndex(int source, int target) { + //on document view UBPersistenceManager::persistenceManager()->moveSceneToIndex(mCurrentDocument, source, target); deleteThumbPage(source); insertThumbPage(target); emit documentThumbnailsUpdated(this); + + //on board thumbnails view + emit moveThumbnailRequired(source, target); return true; } @@ -82,16 +87,26 @@ void UBDocumentContainer::deletePages(QList& pageIndexes) foreach(int index, pageIndexes) { deleteThumbPage(index - offset); + emit removeThumbnailRequired(index - offset); offset++; + } - emit documentThumbnailsUpdated(this); + } void UBDocumentContainer::addPage(int index) { UBPersistenceManager::persistenceManager()->createDocumentSceneAt(mCurrentDocument, index); insertThumbPage(index); + emit documentThumbnailsUpdated(this); + emit addThumbnailRequired(this, index); +} + +void UBDocumentContainer::initThumbPage() +{ + for (int i=0; i < selectedDocument()->pageCount(); i++) + insertThumbPage(i); } void UBDocumentContainer::updatePage(int index) @@ -108,7 +123,6 @@ void UBDocumentContainer::deleteThumbPage(int index) void UBDocumentContainer::updateThumbPage(int index) { mDocumentThumbs[index] = UBThumbnailAdaptor::get(mCurrentDocument, index); - emit documentPageUpdated(index); } void UBDocumentContainer::insertThumbPage(int index) diff --git a/src/document/UBDocumentContainer.h b/src/document/UBDocumentContainer.h index 4fc35b96..c378ddd5 100644 --- a/src/document/UBDocumentContainer.h +++ b/src/document/UBDocumentContainer.h @@ -53,6 +53,7 @@ class UBDocumentContainer : public QObject void duplicatePages(QList& pageIndexes); bool movePageToIndex(int source, int target); void deletePages(QList& pageIndexes); + void initThumbPage(); void addPage(int index); void updatePage(int index); void addEmptyThumbPage(); @@ -73,6 +74,12 @@ class UBDocumentContainer : public QObject signals: void documentSet(UBDocumentProxy* document); void documentPageUpdated(int index); + + void initThumbnailsRequired(UBDocumentContainer* source); + void addThumbnailRequired(UBDocumentContainer* source, int index); + void removeThumbnailRequired(int index); + void moveThumbnailRequired(int from, int to); + void documentThumbnailsUpdated(UBDocumentContainer* source); }; diff --git a/src/document/UBDocumentController.cpp b/src/document/UBDocumentController.cpp index 088544f8..7d3f776b 100644 --- a/src/document/UBDocumentController.cpp +++ b/src/document/UBDocumentController.cpp @@ -467,15 +467,16 @@ void UBDocumentController::openSelectedItem() if (selectedItems.count() > 0) { - UBSceneThumbnailPixmap* thumb = dynamic_cast (selectedItems.last()); + UBThumbnailPixmap* thumb = dynamic_cast (selectedItems.last()); if (thumb) { - UBDocumentProxy* proxy = thumb->proxy(); + UBDocumentProxy* proxy = thumb->documentProxy(); if (proxy && isOKToOpenDocument(proxy)) { UBApplication::applicationController->showBoard(); + UBApplication::applicationController->showBoard(); } } } @@ -504,10 +505,10 @@ void UBDocumentController::duplicateSelectedItem() QList selectedSceneIndexes; foreach (QGraphicsItem *item, selectedItems) { - UBSceneThumbnailPixmap *thumb = dynamic_cast(item); + UBThumbnailPixmap *thumb = dynamic_cast(item); if (thumb) { - UBDocumentProxy *proxy = thumb->proxy(); + UBDocumentProxy *proxy = thumb->documentProxy(); if (proxy) { @@ -1365,7 +1366,7 @@ void UBDocumentController::selectionChanged() mMainWindow->actionDuplicate->setEnabled(!trashSelected); else{ for(int i = 0; i < selection.count() && !firstSceneSelected; i += 1){ - if(dynamic_cast(selection.at(i))->sceneIndex() == 0){ + if(dynamic_cast(selection.at(i))->sceneIndex() == 0){ mMainWindow->actionDuplicate->setEnabled(!trashSelected); firstSceneSelected = true; } @@ -1515,11 +1516,11 @@ void UBDocumentController::addToDocument() foreach (QGraphicsItem* item, selectedItems) { - UBSceneThumbnailPixmap* thumb = dynamic_cast (item); + UBThumbnailPixmap* thumb = dynamic_cast (item); - if (thumb && thumb->proxy()) + if (thumb && thumb->documentProxy()) { - QPair pageInfo(thumb->proxy(), thumb->sceneIndex()); + QPair pageInfo(thumb->documentProxy(), thumb->sceneIndex()); pageInfoList << pageInfo; } } @@ -1808,11 +1809,11 @@ void UBDocumentController::deletePages(QList itemsToDelete) foreach (QGraphicsItem* item, itemsToDelete) { - UBSceneThumbnailPixmap* thumb = dynamic_cast (item); + UBThumbnailPixmap* thumb = dynamic_cast (item); if (thumb) { - proxy = thumb->proxy(); + proxy = thumb->documentProxy(); if (proxy) { sceneIndexes.append(thumb->sceneIndex()); @@ -1842,7 +1843,7 @@ int UBDocumentController::getSelectedItemIndex() if (selectedItems.count() > 0) { - UBSceneThumbnailPixmap* thumb = dynamic_cast (selectedItems.last()); + UBThumbnailPixmap* thumb = dynamic_cast (selectedItems.last()); return thumb->sceneIndex(); } else return -1; @@ -1867,11 +1868,11 @@ void UBDocumentController::refreshDocumentThumbnailsView(UBDocumentContainer*) if (proxy) { setDocument(proxy); - + initThumbPage(); for (int i = 0; i < selectedDocument()->pageCount(); i++) { const QPixmap* pix = pageAt(i); - QGraphicsPixmapItem *pixmapItem = new UBSceneThumbnailPixmap(*pix, proxy, i); // deleted by the tree widget + QGraphicsPixmapItem *pixmapItem = new UBThumbnailPixmap(*pix, proxy, i); // deleted by the tree widget if (proxy == mBoardController->selectedDocument() && mBoardController->activeSceneIndex() == i) { @@ -1898,7 +1899,7 @@ void UBDocumentController::refreshDocumentThumbnailsView(UBDocumentContainer*) if (selection) { disconnect(mDocumentUI->thumbnailWidget->scene(), SIGNAL(selectionChanged()), this, SLOT(pageSelectionChanged())); - UBSceneThumbnailPixmap *currentScene = dynamic_cast(selection); + UBThumbnailPixmap *currentScene = dynamic_cast(selection); if (currentScene) mDocumentUI->thumbnailWidget->hightlightItem(currentScene->sceneIndex()); connect(mDocumentUI->thumbnailWidget->scene(), SIGNAL(selectionChanged()), this, SLOT(pageSelectionChanged())); diff --git a/src/domain/UBDragableThumbnail.cpp b/src/domain/UBDragableThumbnail.cpp new file mode 100644 index 00000000..a8e05ec8 --- /dev/null +++ b/src/domain/UBDragableThumbnail.cpp @@ -0,0 +1,128 @@ +#include "UBDragableThumbnail.h" + +#include +#include +#include + +UBDraggableThumbnail::UBDraggableThumbnail(QWidget* parent, const QPixmap& pixmap) : + QFrame(parent) + , mThumbnail(new QLabel(this)) + , mHBoxLayout(new QHBoxLayout(this)) +{ + setFrameStyle(QFrame::Sunken | QFrame::StyledPanel); + setAcceptDrops(true); + + //set stylesheet + setObjectName("DockPaletteWidgetBox"); + setStyleSheet("background:white"); + + mHBoxLayout->setAlignment(Qt::AlignHCenter); + + setThumbnail(pixmap); + + setLayout(mHBoxLayout); +} + +void UBDraggableThumbnail::setThumbnail(const QPixmap& pixmap) +{ + mThumbnail->setAttribute(Qt::WA_DeleteOnClose); + setPixmap(pixmap); + + mHBoxLayout->addWidget(mThumbnail); +} + +void UBDraggableThumbnail::setPixmap(const QPixmap& pixmap) +{ + mThumbnail->setPixmap(pixmap); +} + +void UBDraggableThumbnail::dragEnterEvent(QDragEnterEvent *event) +{ + if (event->mimeData()->hasFormat("application/x-dnditemdata")) { + if (event->source() == this) { + event->setDropAction(Qt::MoveAction); + event->accept(); + } else { + event->acceptProposedAction(); + } + } else { + event->ignore(); + } + } + + void UBDraggableThumbnail::dragMoveEvent(QDragMoveEvent *event) + { + if (event->mimeData()->hasFormat("application/x-dnditemdata")) { + if (event->source() == this) { + event->setDropAction(Qt::MoveAction); + event->accept(); + } else { + event->acceptProposedAction(); + } + } else { + event->ignore(); + } +} + +void UBDraggableThumbnail::dropEvent(QDropEvent *event) +{ + if (event->mimeData()->hasFormat("application/x-dnditemdata")) { + QByteArray itemData = event->mimeData()->data("application/x-dnditemdata"); + QDataStream dataStream(&itemData, QIODevice::ReadOnly); + + QPixmap pixmap; + QPoint offset; + dataStream >> pixmap >> offset; + + //don't have to delete previous Thumbnail (Drag'n'Drop behavior with WA_DeleteOnClose attribute will do it) + mThumbnail = new QLabel(this); + setThumbnail(pixmap); + + if (event->source() == this) { + event->setDropAction(Qt::MoveAction); + event->accept(); + } else { + event->acceptProposedAction(); + } + } else { + event->ignore(); + } +} + + +void UBDraggableThumbnail::mousePressEvent(QMouseEvent *event) +{ + QLabel *child = static_cast(childAt(event->pos())); + if (!child) + return; + + QPixmap pixmap = *child->pixmap(); + + QByteArray itemData; + QDataStream dataStream(&itemData, QIODevice::WriteOnly); + dataStream << pixmap << QPoint(event->pos() - child->pos()); + + QMimeData *mimeData = new QMimeData; + mimeData->setData("application/x-dnditemdata", itemData); + + QDrag *drag = new QDrag(this); + drag->setMimeData(mimeData); + drag->setPixmap(pixmap); + drag->setHotSpot(event->pos() - child->pos()); + + QPixmap tempPixmap = pixmap; + QPainter painter; + painter.begin(&tempPixmap); + painter.fillRect(pixmap.rect(), QColor(127, 127, 127, 127)); + painter.end(); + + child->setPixmap(tempPixmap); + + if (drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction) == Qt::MoveAction) + child->close(); + else { + child->show(); + child->setPixmap(pixmap); + } +} + diff --git a/src/domain/UBDragableThumbnail.h b/src/domain/UBDragableThumbnail.h new file mode 100644 index 00000000..fe25c2c5 --- /dev/null +++ b/src/domain/UBDragableThumbnail.h @@ -0,0 +1,31 @@ +#ifndef UBDRAGABLELABEL_H +#define UBDRAGABLELABEL_H + +#include +#include +#include +#include +#include +#include +#include + +class UBDraggableThumbnail : public QFrame +{ + public: + UBDraggableThumbnail(QWidget* parent =0, const QPixmap& pixmap = QPixmap(":images/libpalette/notFound.png")); + + void setThumbnail(const QPixmap &pixmap); + void setPixmap(const QPixmap & pixmap); + + protected: + void dragEnterEvent(QDragEnterEvent *event); + void dragMoveEvent(QDragMoveEvent *event); + void dropEvent(QDropEvent *event); + void mousePressEvent(QMouseEvent *event); + + private: + QLabel* mThumbnail; + QHBoxLayout* mHBoxLayout; +}; + +#endif // UBDRAGABLELABEL_H diff --git a/src/domain/UBGraphicsPolygonItem.cpp b/src/domain/UBGraphicsPolygonItem.cpp index 4e74420a..ad1cdb9c 100644 --- a/src/domain/UBGraphicsPolygonItem.cpp +++ b/src/domain/UBGraphicsPolygonItem.cpp @@ -184,7 +184,7 @@ void UBGraphicsPolygonItem::copyItemParameters(UBItem *copy) const void UBGraphicsPolygonItem::paint ( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget) { if(mHasAlpha && scene() && scene()->isLightBackground()) - painter->setCompositionMode(QPainter::CompositionMode_SourceOver); + painter->setCompositionMode(QPainter::CompositionMode_Darken); painter->setRenderHints(QPainter::Antialiasing); diff --git a/src/domain/UBGraphicsPolygonItem.h b/src/domain/UBGraphicsPolygonItem.h index eb5eb815..8dcc26b1 100644 --- a/src/domain/UBGraphicsPolygonItem.h +++ b/src/domain/UBGraphicsPolygonItem.h @@ -109,6 +109,8 @@ class UBGraphicsPolygonItem : public QGraphicsPolygonItem, public UBItem qreal originalWidth() { return mOriginalWidth;} bool isNominalLine() {return mIsNominalLine;} + void setNominalLine(bool isNominalLine) { mIsNominalLine = isNominalLine; } + QColor colorOnDarkBackground() const { return mColorOnDarkBackground; diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index 147e2d70..14f1c5e3 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -48,6 +48,7 @@ #include "gui/UBMagnifer.h" #include "gui/UBMainWindow.h" #include "gui/UBToolWidget.h" +#include "gui/UBResources.h" #include "tools/UBGraphicsRuler.h" #include "tools/UBGraphicsProtractor.h" @@ -317,6 +318,7 @@ UBGraphicsScene::UBGraphicsScene(UBDocumentProxy* parent, bool enableUndoRedoSta , mEraser(0) , mPointer(0) , mMarkerCircle(0) + , mPenCircle(0) , mDocument(parent) , mDarkBackground(false) , mPageBackground(UBPageBackground::plain) @@ -346,6 +348,7 @@ UBGraphicsScene::UBGraphicsScene(UBDocumentProxy* parent, bool enableUndoRedoSta createEraiser(); createPointer(); createMarkerCircle(); + createPenCircle(); if (UBApplication::applicationController) { @@ -410,6 +413,10 @@ bool UBGraphicsScene::inputDevicePress(const QPointF& scenePos, const qreal& pre if (currentTool == UBStylusTool::Marker) hideMarkerCircle(); + // hide the pen preview circle + if (currentTool == UBStylusTool::Pen) + hidePenCircle(); + // --------------------------------------------------------------- // Create a new Stroke. A Stroke is a collection of QGraphicsLines // --------------------------------------------------------------- @@ -492,6 +499,15 @@ bool UBGraphicsScene::inputDeviceMove(const QPointF& scenePos, const qreal& pres } } + else if (currentTool == UBStylusTool::Pen) { + if (mInputDeviceIsPressed) + hidePenCircle(); + else { + drawPenCircle(position); + accepted = true; + } + } + if (mInputDeviceIsPressed) { if (dc->isDrawingTool()) @@ -799,6 +815,28 @@ void UBGraphicsScene::drawMarkerCircle(const QPointF &pPoint) } +void UBGraphicsScene::drawPenCircle(const QPointF &pPoint) +{ + if (mPenCircle && UBSettings::settings()->showPenPreviewCircle->get().toBool() && + UBSettings::settings()->currentPenWidth() >= UBSettings::settings()->penPreviewFromSize->get().toInt()) { + qreal penDiameter = UBSettings::settings()->currentPenWidth(); + penDiameter /= UBApplication::boardController->systemScaleFactor(); + penDiameter /= UBApplication::boardController->currentZoom(); + qreal penRadius = penDiameter/2; + + mPenCircle->setRect(QRectF(pPoint.x() - penRadius, pPoint.y() - penRadius, + penDiameter, penDiameter)); + + controlView()->viewport()->setCursor(QCursor (Qt::BlankCursor)); + mPenCircle->show(); + } + else + { + controlView()->viewport()->setCursor(UBResources::resources()->penCursor); + } + +} + void UBGraphicsScene::hideMarkerCircle() { if (mMarkerCircle) { @@ -806,6 +844,12 @@ void UBGraphicsScene::hideMarkerCircle() } } +void UBGraphicsScene::hidePenCircle() +{ + if (mPenCircle) + mPenCircle->hide(); +} + // call this function when user release mouse button in Magnifier mode void UBGraphicsScene::DisposeMagnifierQWidgets() { @@ -989,6 +1033,7 @@ void UBGraphicsScene::eraseLineTo(const QPointF &pEndPoint, const qreal &pWidth) UBGraphicsPolygonItem* polygonItem = new UBGraphicsPolygonItem(intersectedPolygons[i][j], intersectedPolygonItem->parentItem()); intersectedPolygonItem->copyItemParameters(polygonItem); + polygonItem->setNominalLine(false); polygonItem->setStroke(intersectedPolygonItem->stroke()); polygonItem->setStrokesGroup(intersectedPolygonItem->strokesGroup()); intersectedPolygonItem->strokesGroup()->addToGroup(polygonItem); @@ -1050,6 +1095,7 @@ void UBGraphicsScene::setBackground(bool pIsDark, UBPageBackground pBackground) updateEraserColor(); updateMarkerCircleColor(); + updatePenCircleColor(); recolorAllItems(); needRepaint = true; @@ -1270,6 +1316,7 @@ void UBGraphicsScene::hideTool() { hideEraser(); hideMarkerCircle(); + hidePenCircle(); } void UBGraphicsScene::leaveEvent(QEvent * event) @@ -2791,6 +2838,25 @@ void UBGraphicsScene::createMarkerCircle() } } +void UBGraphicsScene::createPenCircle() +{ + if (UBSettings::settings()->showPenPreviewCircle->get().toBool()) { + mPenCircle = new QGraphicsEllipseItem(); + + mPenCircle->setRect(QRect(0, 0, 0, 0)); + mPenCircle->setVisible(false); + + mPenCircle->setPen(Qt::DotLine); + updatePenCircleColor(); + + mPenCircle->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Control)); + mPenCircle->setData(UBGraphicsItemData::itemLayerType, QVariant(itemLayerType::Eraiser)); + + mTools << mPenCircle; + addItem(mPenCircle); + } +} + void UBGraphicsScene::updateEraserColor() { if (!mEraser) @@ -2828,6 +2894,27 @@ void UBGraphicsScene::updateMarkerCircleColor() mMarkerCircle->setPen(mcPen); } +void UBGraphicsScene::updatePenCircleColor() +{ + if (!mPenCircle) + return; + + QPen mcPen = mPenCircle->pen(); + + if (mDarkBackground) { + mcPen.setColor(UBSettings::penCirclePenColorDarkBackground); + mPenCircle->setBrush(UBSettings::penCircleBrushColorDarkBackground); + } + + else { + mcPen.setColor(UBSettings::penCirclePenColorLightBackground); + mPenCircle->setBrush(UBSettings::penCircleBrushColorLightBackground); + } + + mcPen.setStyle(Qt::DotLine); + mPenCircle->setPen(mcPen); +} + void UBGraphicsScene::setToolCursor(int tool) { if (tool == (int)UBStylusTool::Selector || diff --git a/src/domain/UBGraphicsScene.h b/src/domain/UBGraphicsScene.h index 84d01514..1f1b2a1e 100644 --- a/src/domain/UBGraphicsScene.h +++ b/src/domain/UBGraphicsScene.h @@ -383,7 +383,9 @@ public slots: void hideEraser(); void drawPointer(const QPointF& pEndPoint, bool isFirstDraw = false); void drawMarkerCircle(const QPointF& pEndPoint); + void drawPenCircle(const QPointF& pEndPoint); void hideMarkerCircle(); + void hidePenCircle(); void DisposeMagnifierQWidgets(); @@ -404,14 +406,17 @@ public slots: void createEraiser(); void createPointer(); void createMarkerCircle(); + void createPenCircle(); void updateEraserColor(); void updateMarkerCircleColor(); + void updatePenCircleColor(); bool hasTextItemWithFocus(UBGraphicsGroupContainerItem* item); void simplifyCurrentStroke(); QGraphicsEllipseItem* mEraser; QGraphicsEllipseItem* mPointer; // "laser" pointer QGraphicsEllipseItem* mMarkerCircle; // dotted circle around marker + QGraphicsEllipseItem* mPenCircle; // dotted circle around pen QSet mAddedItems; QSet mRemovedItems; diff --git a/src/domain/UBGraphicsStroke.cpp b/src/domain/UBGraphicsStroke.cpp index 7349e70b..3cf10a65 100644 --- a/src/domain/UBGraphicsStroke.cpp +++ b/src/domain/UBGraphicsStroke.cpp @@ -164,12 +164,10 @@ bool UBGraphicsStroke::hasPressure() if (!pol->isNominalLine() || pol->originalWidth() != nominalWidth) return true; } + return false; } - else return true; - - return false; } diff --git a/src/domain/UBGraphicsTextItem.cpp b/src/domain/UBGraphicsTextItem.cpp index f2326bb9..1f29eeee 100644 --- a/src/domain/UBGraphicsTextItem.cpp +++ b/src/domain/UBGraphicsTextItem.cpp @@ -188,6 +188,11 @@ void UBGraphicsTextItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) } } +void UBGraphicsTextItem::dragMoveEvent(QGraphicsSceneDragDropEvent *event) +{ + +} + void UBGraphicsTextItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { // scene()->itemAt(pos) returns 0 if pos is not over text, but over text item, but mouse press comes. diff --git a/src/domain/UBGraphicsTextItem.h b/src/domain/UBGraphicsTextItem.h index bb031f71..e3a3688b 100644 --- a/src/domain/UBGraphicsTextItem.h +++ b/src/domain/UBGraphicsTextItem.h @@ -118,6 +118,8 @@ class UBGraphicsTextItem : public QGraphicsTextItem, public UBItem, public UBRes virtual void keyPressEvent(QKeyEvent *event); virtual void keyReleaseEvent(QKeyEvent *event); + virtual void dragMoveEvent(QGraphicsSceneDragDropEvent *event); + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value); diff --git a/src/domain/UBGraphicsTextItemDelegate.cpp b/src/domain/UBGraphicsTextItemDelegate.cpp index 34b866e6..1c817860 100644 --- a/src/domain/UBGraphicsTextItemDelegate.cpp +++ b/src/domain/UBGraphicsTextItemDelegate.cpp @@ -339,7 +339,10 @@ void UBGraphicsTextItemDelegate::pickFont() curCursor.mergeCharFormat(format); delegated()->setTextCursor(curCursor); - delegated()->setFont(selectedFont); + + if (curCursor.selectedText().length() == 0) + delegated()->setFont(selectedFont); + delegated()->setSelected(true); delegated()->document()->adjustSize(); delegated()->contentsChanged(); @@ -751,10 +754,5 @@ QVariant UBGraphicsTextItemDelegate::itemChange(QGraphicsItem::GraphicsItemChang } } - if (value.toBool() == false && delegated()->document()->toPlainText().isEmpty()) { - int wdth = QFontMetrics(delegated()->font()).width(delegated()->mTypeTextHereLabel); - delegated()->setTextWidth(qMax(wdth, (int)(delegated()->textWidth()))); - } - return UBGraphicsItemDelegate::itemChange(change, value); } diff --git a/src/gui/UBBoardThumbnailsView.cpp b/src/gui/UBBoardThumbnailsView.cpp new file mode 100644 index 00000000..8840e45f --- /dev/null +++ b/src/gui/UBBoardThumbnailsView.cpp @@ -0,0 +1,301 @@ +/* + * Copyright (C) 2015-2016 Département de l'Instruction Publique (DIP-SEM) + * + * Copyright (C) 2013 Open Education Foundation + * + * Copyright (C) 2010-2013 Groupement d'Intérêt Public pour + * l'Education Numérique en Afrique (GIP ENA) + * + * This file is part of OpenBoard. + * + * OpenBoard 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, version 3 of the License, + * with a specific linking exception for the OpenSSL project's + * "OpenSSL" library (or with modified versions of it that use the + * same license as the "OpenSSL" library). + * + * OpenBoard 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 OpenBoard. If not, see . + */ + + + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "core/UBApplication.h" +#include "UBBoardThumbnailsView.h" +#include "board/UBBoardController.h" +#include "adaptors/UBThumbnailAdaptor.h" +#include "adaptors/UBSvgSubsetAdaptor.h" +#include "document/UBDocumentController.h" +#include "domain/UBGraphicsScene.h" +#include "board/UBBoardPaletteManager.h" +#include "core/UBApplicationController.h" +#include "core/UBPersistenceManager.h" +#include "UBThumbnailView.h" + +UBBoardThumbnailsView::UBBoardThumbnailsView(QWidget *parent, const char *name) + : QGraphicsView(parent) + , mThumbnailWidth(0) + , mThumbnailMinWidth(100) + , mMargin(20) + , mDropSource(NULL) + , mDropTarget(NULL) + , mDropBar(new QGraphicsRectItem(0)) + , mLongPressInterval(150) +{ + setScene(new QGraphicsScene(this)); + + mDropBar->setPen(QPen(Qt::darkGray)); + mDropBar->setBrush(QBrush(Qt::lightGray)); + scene()->addItem(mDropBar); + mDropBar->hide(); + + setObjectName(name); + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setFrameShadow(QFrame::Plain); + + mThumbnailWidth = width() - 2*mMargin; + + mLongPressTimer.setInterval(mLongPressInterval); + mLongPressTimer.setSingleShot(true); + + connect(UBApplication::boardController, SIGNAL(initThumbnailsRequired(UBDocumentContainer*)), this, SLOT(initThumbnails(UBDocumentContainer*)), Qt::UniqueConnection); + connect(UBApplication::boardController, SIGNAL(addThumbnailRequired(UBDocumentContainer*, int)), this, SLOT(addThumbnail(UBDocumentContainer*, int)), Qt::UniqueConnection); + connect(UBApplication::boardController, SIGNAL(moveThumbnailRequired(int, int)), this, SLOT(moveThumbnail(int, int)), Qt::UniqueConnection); + connect(this, SIGNAL(moveThumbnailRequired(int, int)), this, SLOT(moveThumbnail(int, int)), Qt::UniqueConnection); + connect(UBApplication::boardController, SIGNAL(removeThumbnailRequired(int)), this, SLOT(removeThumbnail(int)), Qt::UniqueConnection); + + connect(&mLongPressTimer, SIGNAL(timeout()), this, SLOT(longPressTimeout()), Qt::UniqueConnection); + + connect(this, SIGNAL(mousePressAndHoldEventRequired(QPoint)), this, SLOT(mousePressAndHoldEvent(QPoint)), Qt::UniqueConnection); + + connect(UBApplication::boardController, SIGNAL(pageSelectionChanged(int)), this, SLOT(scrollToSelectedPage(int)), Qt::UniqueConnection); +} + +void UBBoardThumbnailsView::moveThumbnail(int from, int to) +{ + mThumbnails.move(from, to); + + updateThumbnailsPos(); +} + +void UBBoardThumbnailsView::removeThumbnail(int i) +{ + UBDraggableThumbnailView* item = mThumbnails.at(i); + + scene()->removeItem(item->pageNumber()); + scene()->removeItem(item); + + mThumbnails.removeAt(i); + + updateThumbnailsPos(); +} + +UBDraggableThumbnailView* UBBoardThumbnailsView::createThumbnail(UBDocumentContainer* source, int i) +{ + UBGraphicsScene* pageScene = UBPersistenceManager::persistenceManager()->loadDocumentScene(source->selectedDocument(), i); + UBThumbnailView* pageView = new UBThumbnailView(pageScene); + + return new UBDraggableThumbnailView(pageView, source->selectedDocument(), i); +} + +void UBBoardThumbnailsView::addThumbnail(UBDocumentContainer* source, int i) +{ + UBDraggableThumbnailView* item = createThumbnail(source, i); + mThumbnails.insert(i, item); + + scene()->addItem(item); + scene()->addItem(item->pageNumber()); + + updateThumbnailsPos(); +} + +void UBBoardThumbnailsView::clearThumbnails() +{ + qDeleteAll(mThumbnails); + mThumbnails.clear(); +} + +void UBBoardThumbnailsView::initThumbnails(UBDocumentContainer* source) +{ + clearThumbnails(); + + for(int i = 0; i < source->selectedDocument()->pageCount(); i++) + { + mThumbnails.append(createThumbnail(source, i)); + + scene()->addItem(mThumbnails.last()); + scene()->addItem(mThumbnails.last()->pageNumber()); + } + + updateThumbnailsPos(); +} + +void UBBoardThumbnailsView::scrollToSelectedPage(int index) +{ + centerOn(mThumbnails.at(index)); +} + +void UBBoardThumbnailsView::updateThumbnailsPos() +{ + qreal thumbnailHeight = mThumbnailWidth / UBSettings::minScreenRatio; + + for (int i=0; i < mThumbnails.length(); i++) + { + mThumbnails.at(i)->setSceneIndex(i); + mThumbnails.at(i)->setPageNumber(i); + mThumbnails.at(i)->updatePos(mThumbnailWidth, thumbnailHeight); + } + + scene()->setSceneRect(scene()->itemsBoundingRect()); +} + +void UBBoardThumbnailsView::resizeEvent(QResizeEvent *event) +{ + Q_UNUSED(event); + + // Update the thumbnails width + mThumbnailWidth = (width() > mThumbnailMinWidth) ? width() - 2*mMargin : mThumbnailMinWidth; + + // Refresh the scene + updateThumbnailsPos(); +} + +void UBBoardThumbnailsView::mousePressEvent(QMouseEvent *event) +{ + mLongPressTimer.start(); + mLastPressedMousePos = event->pos(); + QGraphicsView::mousePressEvent(event); +} + +void UBBoardThumbnailsView::mouseMoveEvent(QMouseEvent *event) +{ + mLastPressedMousePos = event->pos(); + QGraphicsView::mouseMoveEvent(event); +} + +void UBBoardThumbnailsView::longPressTimeout() +{ + emit mousePressAndHoldEventRequired(mLastPressedMousePos); + mLongPressTimer.stop(); +} + +void UBBoardThumbnailsView::mousePressAndHoldEvent(QPoint pos) +{ + UBDraggableThumbnailView* item = dynamic_cast(itemAt(pos)); + if (item) + { + mDropSource = item; + mDropTarget = item; + + QPixmap pixmap = item->widget()->grab().scaledToWidth(UBSettings::defaultThumbnailWidth); + + QDrag *drag = new QDrag(this); + drag->setMimeData(new QMimeData()); + drag->setPixmap(pixmap); + drag->setHotSpot(QPoint(pixmap.width()/2, pixmap.height()/2)); + + drag->exec(); + } +} + +void UBBoardThumbnailsView::mouseReleaseEvent(QMouseEvent *event) +{ + mLongPressTimer.stop(); + + UBDraggableThumbnailView* item = dynamic_cast(itemAt(event->pos())); + + if (item) + UBApplication::boardController->setActiveDocumentScene(item->sceneIndex()); + + QGraphicsView::mouseReleaseEvent(event); +} + +void UBBoardThumbnailsView::dragEnterEvent(QDragEnterEvent *event) +{ + mDropBar->show(); + + if (event->source() == this) + { + event->setDropAction(Qt::MoveAction); + event->accept(); + } + else + { + event->acceptProposedAction(); + } +} + +void UBBoardThumbnailsView::dragMoveEvent(QDragMoveEvent *event) +{ + QPointF position = event->pos(); + + //autoscroll during drag'n'drop + QPointF scenePos = mapToScene(position.toPoint()); + int thumbnailHeight = mThumbnailWidth / UBSettings::minScreenRatio; + QRectF thumbnailArea(0, scenePos.y() - thumbnailHeight/2, mThumbnailWidth, thumbnailHeight); + + ensureVisible(thumbnailArea); + + UBDraggableThumbnailView* item = dynamic_cast(itemAt(position.toPoint())); + if (item) + { + if (item != mDropTarget) + mDropTarget = item; + + qreal scale = item->transform().m11(); + + QPointF itemCenter(item->pos().x() + item->boundingRect().width() * scale / 2, + item->pos().y() + item->boundingRect().height() * scale / 2); + + bool dropAbove = mapToScene(position.toPoint()).y() < itemCenter.y(); + bool movingUp = mDropSource->sceneIndex() > item->sceneIndex(); + qreal y = 0; + + if (movingUp) + { + if (dropAbove) + { + y = item->pos().y() - UBSettings::thumbnailSpacing / 2; + if (mDropBar->y() != y) + mDropBar->setRect(QRectF(item->pos().x(), y, item->boundingRect().width() * scale, 3)); + } + } + else + { + if (!dropAbove) + { + y = item->pos().y() + item->boundingRect().height() * scale + UBSettings::thumbnailSpacing / 2; + if (mDropBar->y() != y) + mDropBar->setRect(QRectF(item->pos().x(), y, item->boundingRect().width() * scale, 3)); + } + } + } + event->acceptProposedAction(); +} + +void UBBoardThumbnailsView::dropEvent(QDropEvent *event) +{ + Q_UNUSED(event); + + UBApplication::boardController->moveSceneToIndex(mDropSource->sceneIndex(), mDropTarget->sceneIndex()); + + mDropSource = NULL; + mDropTarget = NULL; + mDropBar->hide(); +} diff --git a/src/gui/UBDocumentNavigator.h b/src/gui/UBBoardThumbnailsView.h similarity index 52% rename from src/gui/UBDocumentNavigator.h rename to src/gui/UBBoardThumbnailsView.h index aebcce18..77a3b0ba 100644 --- a/src/gui/UBDocumentNavigator.h +++ b/src/gui/UBBoardThumbnailsView.h @@ -27,63 +27,67 @@ -#ifndef UBDOCUMENTNAVIGATOR_H -#define UBDOCUMENTNAVIGATOR_H +#ifndef UBBOARDTHUMBNAILSVIEW_H +#define UBBOARDTHUMBNAILSVIEW_H #include #include #include #include -#include -#include "document/UBDocumentProxy.h" #include "document/UBDocumentContainer.h" #include "UBThumbnailWidget.h" -#define NO_PAGESELECTED -1 - -class UBDocumentNavigator : public QGraphicsView +class UBBoardThumbnailsView : public QGraphicsView { Q_OBJECT public: - UBDocumentNavigator(QWidget* parent=0, const char* name="documentNavigator"); - ~UBDocumentNavigator(); - - void setNbColumns(int nbColumns); - int nbColumns(); - void setThumbnailMinWidth(int width); - int thumbnailMinWidth(); + UBBoardThumbnailsView(QWidget* parent=0, const char* name="UBBoardThumbnailsView"); public slots: - void onScrollToSelectedPage(int index);// { if (mCrntItem) centerOn(mCrntItem); } - void generateThumbnails(UBDocumentContainer* source); - void updateSpecificThumbnail(int iPage); + void scrollToSelectedPage(int index); + + void clearThumbnails(); + void initThumbnails(UBDocumentContainer* source); + void addThumbnail(UBDocumentContainer* source, int i); + void moveThumbnail(int from, int to); + void removeThumbnail(int i); + + void longPressTimeout(); + void mousePressAndHoldEvent(QPoint pos); protected: virtual void resizeEvent(QResizeEvent *event); + + virtual void dragEnterEvent(QDragEnterEvent* event); + virtual void dragMoveEvent(QDragMoveEvent* event); + virtual void dropEvent(QDropEvent* event); + virtual void mousePressEvent(QMouseEvent *event); + virtual void mouseMoveEvent(QMouseEvent *event); virtual void mouseReleaseEvent(QMouseEvent *event); -private: +signals: + void mousePressAndHoldEventRequired(QPoint pos); + void moveThumbnailRequired(int from, int to); - void refreshScene(); - int border(); +private: + UBDraggableThumbnailView* createThumbnail(UBDocumentContainer* source, int i); + void updateThumbnailsPos(); + QList mThumbnails; - /** The scene */ - QGraphicsScene* mScene; - /** The current selected item */ - //UBSceneThumbnailNavigPixmap* mCrntItem; - /** The list of current thumbnails with labels*/ - QList mThumbsWithLabels; - /** The current number of columns */ - int mNbColumns; - /** The current thumbnails width */ int mThumbnailWidth; - /** The current thumbnails minimum width */ - int mThumbnailMinWidth; - /** The selected thumbnail */ - UBSceneThumbnailNavigPixmap* mSelectedThumbnail; + const int mThumbnailMinWidth; + const int mMargin; + + UBDraggableThumbnailView* mDropSource; + UBDraggableThumbnailView* mDropTarget; + QGraphicsRectItem *mDropBar; + + int mLongPressInterval; + QTimer mLongPressTimer; + QPoint mLastPressedMousePos; }; -#endif // UBDOCUMENTNAVIGATOR_H +#endif // UBBOARDTHUMBNAILSVIEW_H diff --git a/src/gui/UBDocumentNavigator.cpp b/src/gui/UBDocumentNavigator.cpp deleted file mode 100644 index db8c19ce..00000000 --- a/src/gui/UBDocumentNavigator.cpp +++ /dev/null @@ -1,311 +0,0 @@ -/* - * Copyright (C) 2015-2016 Département de l'Instruction Publique (DIP-SEM) - * - * Copyright (C) 2013 Open Education Foundation - * - * Copyright (C) 2010-2013 Groupement d'Intérêt Public pour - * l'Education Numérique en Afrique (GIP ENA) - * - * This file is part of OpenBoard. - * - * OpenBoard 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, version 3 of the License, - * with a specific linking exception for the OpenSSL project's - * "OpenSSL" library (or with modified versions of it that use the - * same license as the "OpenSSL" library). - * - * OpenBoard 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 OpenBoard. If not, see . - */ - - - - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "core/UBApplication.h" -#include "UBDocumentNavigator.h" -#include "board/UBBoardController.h" -#include "adaptors/UBThumbnailAdaptor.h" -#include "adaptors/UBSvgSubsetAdaptor.h" -#include "document/UBDocumentController.h" -#include "domain/UBGraphicsScene.h" -#include "board/UBBoardPaletteManager.h" -#include "core/UBApplicationController.h" - -#include "core/memcheck.h" - -/** - * \brief Constructor - * @param parent as the parent widget - * @param name as the object name - */ -UBDocumentNavigator::UBDocumentNavigator(QWidget *parent, const char *name):QGraphicsView(parent) - , mScene(NULL) - , mNbColumns(1) - , mThumbnailWidth(0) - , mThumbnailMinWidth(100) - , mSelectedThumbnail(NULL) -{ - setObjectName(name); - mScene = new QGraphicsScene(this); - setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - setScene(mScene); - mThumbnailWidth = width() - 2*border(); - - setFrameShadow(QFrame::Plain); - - connect(UBApplication::boardController, SIGNAL(documentThumbnailsUpdated(UBDocumentContainer*)), this, SLOT(generateThumbnails(UBDocumentContainer*))); - connect(UBApplication::boardController, SIGNAL(documentPageUpdated(int)), this, SLOT(updateSpecificThumbnail(int))); - connect(UBApplication::boardController, SIGNAL(pageSelectionChanged(int)), this, SLOT(onScrollToSelectedPage(int))); -} - -/** - * \brief Destructor - */ -UBDocumentNavigator::~UBDocumentNavigator() -{ - if(NULL != mScene) - { - delete mScene; - mScene = NULL; - } -} - -/** - * \brief Generate the thumbnails - */ -void UBDocumentNavigator::generateThumbnails(UBDocumentContainer* source) -{ - mThumbsWithLabels.clear(); - int selectedIndex = -1; - QList graphicsItemList = mScene->items(); - for(int i = 0; i < graphicsItemList.size(); i+=1) - { - QGraphicsItem* item = graphicsItemList.at(i); - if(item->isSelected()) - selectedIndex = i; - mScene->removeItem(item); - delete item; - item = NULL; - } - - for(int i = 0; i < source->selectedDocument()->pageCount(); i++) - { - //claudio This is a very bad hack and shows a architectural problem - // source->selectedDocument()->pageCount() != source->pageCount() - if(i>=source->pageCount() || source->pageAt(i)->isNull()) - source->insertThumbPage(i); - - const QPixmap* pix = source->pageAt(i); - Q_ASSERT(!pix->isNull()); - int pageIndex = UBDocumentContainer::pageFromSceneIndex(i); - - UBSceneThumbnailNavigPixmap* pixmapItem = new UBSceneThumbnailNavigPixmap(*pix, source->selectedDocument(), i); - - QString label = tr("Page %0").arg(pageIndex); - UBThumbnailTextItem *labelItem = new UBThumbnailTextItem(label); - - UBImgTextThumbnailElement thumbWithText(pixmapItem, labelItem); - thumbWithText.setBorder(border()); - mThumbsWithLabels.append(thumbWithText); - - mScene->addItem(pixmapItem); - mScene->addItem(labelItem); - } - - if (selectedIndex >= 0 && selectedIndex < mThumbsWithLabels.count()) - mSelectedThumbnail = mThumbsWithLabels.at(selectedIndex).getThumbnail(); - else - mSelectedThumbnail = NULL; - - // Draw the items - refreshScene(); -} - -void UBDocumentNavigator::onScrollToSelectedPage(int index) -{ - int c = 0; - foreach(UBImgTextThumbnailElement el, mThumbsWithLabels) - { - if (c==index) - { - el.getThumbnail()->setSelected(true); - mSelectedThumbnail = el.getThumbnail(); - } - else - { - el.getThumbnail()->setSelected(false); - } - c++; - } - if(NULL != mSelectedThumbnail) - centerOn(mSelectedThumbnail); -} - -/** - * \brief Refresh the given thumbnail - * @param iPage as the given page related thumbnail - */ -void UBDocumentNavigator::updateSpecificThumbnail(int iPage) -{ - const QPixmap* pix = UBApplication::boardController->pageAt(iPage); - UBSceneThumbnailNavigPixmap* newItem = new UBSceneThumbnailNavigPixmap(*pix, UBApplication::boardController->selectedDocument(), iPage); - - // Get the old thumbnail - UBSceneThumbnailNavigPixmap* oldItem = mThumbsWithLabels.at(iPage).getThumbnail(); - if(NULL != oldItem) - { - mScene->removeItem(oldItem); - mScene->addItem(newItem); - mThumbsWithLabels[iPage].setThumbnail(newItem); - delete oldItem; - oldItem = NULL; - } - -} - -/** - * \brief Put the element in the right place in the scene. - */ -void UBDocumentNavigator::refreshScene() -{ - qreal thumbnailHeight = mThumbnailWidth / UBSettings::minScreenRatio; - - for(int i = 0; i < mThumbsWithLabels.size(); i++) - { - // Get the item - UBImgTextThumbnailElement& item = mThumbsWithLabels[i]; - int columnIndex = i % mNbColumns; - int rowIndex = i / mNbColumns; - item.Place(rowIndex, columnIndex, mThumbnailWidth, thumbnailHeight); - } - scene()->setSceneRect(scene()->itemsBoundingRect()); -} - -/** - * \brief Set the number of thumbnails columns - * @param nbColumns as the number of columns - */ -void UBDocumentNavigator::setNbColumns(int nbColumns) -{ - mNbColumns = nbColumns; -} - -/** - * \brief Get the number of columns - * @return the number of thumbnails columns - */ -int UBDocumentNavigator::nbColumns() -{ - return mNbColumns; -} - -/** - * \brief Set the thumbnails minimum width - * @param width as the minimum width - */ -void UBDocumentNavigator::setThumbnailMinWidth(int width) -{ - mThumbnailMinWidth = width; -} - -/** - * \brief Get the thumbnails minimum width - * @return the minimum thumbnails width - */ -int UBDocumentNavigator::thumbnailMinWidth() -{ - return mThumbnailMinWidth; -} - -/** - * \brief Get the border size - * @return the border size in pixels - */ -int UBDocumentNavigator::border() -{ - return 20; -} - -/** - * \brief Handle the resize event - * @param event as the resize event - */ -void UBDocumentNavigator::resizeEvent(QResizeEvent *event) -{ - Q_UNUSED(event); - - // Update the thumbnails width - mThumbnailWidth = (width() > mThumbnailMinWidth) ? width() - 2*border() : mThumbnailMinWidth; - - if(mSelectedThumbnail) - centerOn(mSelectedThumbnail); - - // Refresh the scene - refreshScene(); -} - -/** - * \brief Handle the mouse press event - * @param event as the mouse event - */ -void UBDocumentNavigator::mousePressEvent(QMouseEvent *event) -{ - QGraphicsItem* pClickedItem = itemAt(event->pos()); - if(NULL != pClickedItem) - { - - // First, select the clicked item - UBSceneThumbnailNavigPixmap* pCrntItem = dynamic_cast(pClickedItem); - - if(NULL == pCrntItem) - { - // If we fall here we may have clicked on the label instead of the thumbnail - UBThumbnailTextItem* pTextItem = dynamic_cast(pClickedItem); - if(NULL != pTextItem) - { - for(int i = 0; i < mThumbsWithLabels.size(); i++) - { - const UBImgTextThumbnailElement& el = mThumbsWithLabels.at(i); - if(el.getCaption() == pTextItem) - { - pCrntItem = el.getThumbnail(); - break; - } - } - } - } - - int index = 0; - for(int i = 0; i < mThumbsWithLabels.size(); i++) - { - if (mThumbsWithLabels.at(i).getThumbnail() == pCrntItem) - { - mSelectedThumbnail = pCrntItem; - index = i; - break; - } - } - UBApplication::boardController->setActiveDocumentScene(index); - } - QGraphicsView::mousePressEvent(event); -} - -void UBDocumentNavigator::mouseReleaseEvent(QMouseEvent *event) -{ - event->accept(); -} diff --git a/src/gui/UBDocumentThumbnailWidget.cpp b/src/gui/UBDocumentThumbnailWidget.cpp index 19ad39b1..b70f3926 100644 --- a/src/gui/UBDocumentThumbnailWidget.cpp +++ b/src/gui/UBDocumentThumbnailWidget.cpp @@ -75,17 +75,17 @@ void UBDocumentThumbnailWidget::mouseMoveEvent(QMouseEvent *event) QList graphicsItems = items(mMousePressPos); - UBSceneThumbnailPixmap* sceneItem = 0; + UBThumbnailPixmap* sceneItem = 0; while (!graphicsItems.isEmpty() && !sceneItem) - sceneItem = dynamic_cast(graphicsItems.takeFirst()); + sceneItem = dynamic_cast(graphicsItems.takeFirst()); if (sceneItem) { QDrag *drag = new QDrag(this); QList mimeDataItems; foreach (QGraphicsItem *item, selectedItems()) - mimeDataItems.append(UBMimeDataItem(sceneItem->proxy(), mGraphicItems.indexOf(item))); + mimeDataItems.append(UBMimeDataItem(sceneItem->documentProxy(), mGraphicItems.indexOf(item))); UBMimeData *mime = new UBMimeData(mimeDataItems); drag->setMimeData(mime); @@ -150,21 +150,21 @@ void UBDocumentThumbnailWidget::dragMoveEvent(QDragMoveEvent *event) mScrollTimer->stop(); } - QList pixmapItems; + QList pixmapItems; foreach (QGraphicsItem *item, scene()->items(mapToScene(boundingFrame))) { - UBSceneThumbnailPixmap* sceneItem = dynamic_cast(item); + UBThumbnailPixmap* sceneItem = dynamic_cast(item); if (sceneItem) pixmapItems.append(sceneItem); } int minDistance = 0; QGraphicsItem *underlyingItem = itemAt(event->pos()); - mClosestDropItem = dynamic_cast(underlyingItem); + mClosestDropItem = dynamic_cast(underlyingItem); if (!mClosestDropItem) { - foreach (UBSceneThumbnailPixmap *item, pixmapItems) + foreach (UBThumbnailPixmap *item, pixmapItems) { qreal scale = item->transform().m11(); QPointF itemCenter( @@ -305,7 +305,7 @@ void UBDocumentThumbnailWidget::hightlightItem(int index) } if (0 <= index && index < mGraphicItems.length()) { - UBSceneThumbnailPixmap *thumbnail = dynamic_cast(mGraphicItems.at(index)); + UBThumbnailPixmap *thumbnail = dynamic_cast(mGraphicItems.at(index)); if (thumbnail) thumbnail->highlight(); } diff --git a/src/gui/UBDocumentThumbnailWidget.h b/src/gui/UBDocumentThumbnailWidget.h index 617cee13..ba99acdf 100644 --- a/src/gui/UBDocumentThumbnailWidget.h +++ b/src/gui/UBDocumentThumbnailWidget.h @@ -71,7 +71,7 @@ class UBDocumentThumbnailWidget: public UBThumbnailWidget void deleteDropCaret(); QGraphicsRectItem *mDropCaretRectItem; - UBSceneThumbnailPixmap *mClosestDropItem; + UBThumbnailPixmap *mClosestDropItem; bool mDropIsRight; bool mDragEnabled; QTimer* mScrollTimer; diff --git a/src/gui/UBPageNavigationWidget.cpp b/src/gui/UBPageNavigationWidget.cpp index a6564573..eba9e401 100644 --- a/src/gui/UBPageNavigationWidget.cpp +++ b/src/gui/UBPageNavigationWidget.cpp @@ -60,7 +60,7 @@ UBPageNavigationWidget::UBPageNavigationWidget(QWidget *parent, const char *name mLayout = new QVBoxLayout(this); setLayout(mLayout); - mNavigator = new UBDocumentNavigator(this); + mNavigator = new UBBoardThumbnailsView(this); mLayout->addWidget(mNavigator, 1); mHLayout = new QHBoxLayout(); diff --git a/src/gui/UBPageNavigationWidget.h b/src/gui/UBPageNavigationWidget.h index 9fe7a388..bba9cc86 100644 --- a/src/gui/UBPageNavigationWidget.h +++ b/src/gui/UBPageNavigationWidget.h @@ -38,7 +38,7 @@ #include #include -#include "UBDocumentNavigator.h" +#include "UBBoardThumbnailsView.h" #include "UBDockPaletteWidget.h" #include "document/UBDocumentProxy.h" @@ -70,7 +70,7 @@ private: int border(); /** The thumbnails navigator widget */ - UBDocumentNavigator* mNavigator; + UBBoardThumbnailsView* mNavigator; /** The layout */ QVBoxLayout* mLayout; QHBoxLayout* mHLayout; diff --git a/src/gui/UBThumbnailView.cpp b/src/gui/UBThumbnailView.cpp index c6fc2713..f5f6f3ed 100644 --- a/src/gui/UBThumbnailView.cpp +++ b/src/gui/UBThumbnailView.cpp @@ -34,34 +34,29 @@ #include "core/memcheck.h" -UBThumbnailView::UBThumbnailView() +UBThumbnailView::UBThumbnailView(UBGraphicsScene *scene, QWidget* parent) + : QGraphicsView(scene, parent) + , mHBoxLayout(new QHBoxLayout(this)) { + setAcceptDrops(true); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::TextAntialiasing); -} -UBThumbnailView::~UBThumbnailView() -{ - // NOOP -} + int nominalWidth = scene->nominalSize().width(); + int nominalHeight = scene->nominalSize().height(); + QRectF nominalSceneRect(-nominalWidth/2, -nominalHeight/2, nominalWidth, nominalHeight); + fitInView(nominalSceneRect, Qt::KeepAspectRatio); + setSceneRect(nominalSceneRect); -void UBThumbnailView::drawBackground(QPainter *painter, const QRectF &rect) -{ - // Do not draw crossed background in thumbnails - if (qobject_cast(scene())->isDarkBackground()) - { - painter->fillRect(rect, QBrush(QColor(Qt::black))); - } - else - { - painter->fillRect(rect, QBrush(QColor(Qt::white))); - } -} + setStyleSheet( "QGraphicsView { border-style: none; }" ); -void UBThumbnailView::mouseDoubleClickEvent ( QMouseEvent * event ) -{ - Q_UNUSED(event); - emit doubleClicked(); -} + setFrameStyle(QFrame::Sunken | QFrame::StyledPanel); + //set stylesheet + setObjectName("DockPaletteWidgetBox"); + setStyleSheet("background:white"); + + mHBoxLayout->setAlignment(Qt::AlignHCenter); + setLayout(mHBoxLayout); +} diff --git a/src/gui/UBThumbnailView.h b/src/gui/UBThumbnailView.h index c2f00fb0..3a043c41 100644 --- a/src/gui/UBThumbnailView.h +++ b/src/gui/UBThumbnailView.h @@ -31,6 +31,9 @@ #define UBTHUMBNAILVIEW_H_ #include +#include +#include +#include class UBGraphicsScene; @@ -39,15 +42,15 @@ class UBThumbnailView : public QGraphicsView Q_OBJECT public: - UBThumbnailView(); - virtual ~UBThumbnailView(); - signals: - void doubleClicked(); + UBThumbnailView(UBGraphicsScene *scene, QWidget* parent =0); + virtual ~UBThumbnailView() + { - protected: - virtual void drawBackground(QPainter *painter, const QRectF &rect); - virtual void mouseDoubleClickEvent ( QMouseEvent * event ); + } + + private: + QHBoxLayout* mHBoxLayout; }; diff --git a/src/gui/UBThumbnailWidget.cpp b/src/gui/UBThumbnailWidget.cpp index 95d2b4cf..748c15c0 100644 --- a/src/gui/UBThumbnailWidget.cpp +++ b/src/gui/UBThumbnailWidget.cpp @@ -34,6 +34,8 @@ #include "UBRubberBand.h" #include "UBMainWindow.h" +#include + #include "board/UBBoardController.h" #include "core/UBSettings.h" @@ -42,6 +44,8 @@ #include "document/UBDocumentProxy.h" #include "document/UBDocumentController.h" +#include "board/UBBoardPaletteManager.h" + #include "core/memcheck.h" UBThumbnailWidget::UBThumbnailWidget(QWidget* parent) @@ -225,7 +229,7 @@ void UBThumbnailWidget::mousePressEvent(QMouseEvent *event) mClickTime = QTime::currentTime(); mMousePressPos = event->pos(); - UBSceneThumbnailPixmap* sceneItem = dynamic_cast(itemAt(mMousePressPos)); + UBThumbnailPixmap* sceneItem = dynamic_cast(itemAt(mMousePressPos)); if(sceneItem==NULL) { event->ignore(); @@ -359,7 +363,7 @@ void UBThumbnailWidget::mouseMoveEvent(QMouseEvent *event) { if (lassoSelectedItem) { - UBSceneThumbnailPixmap *thumbnailItem = dynamic_cast(lassoSelectedItem); + UBThumbnailPixmap *thumbnailItem = dynamic_cast(lassoSelectedItem); if (thumbnailItem) lassoSelectedThumbnailItems += lassoSelectedItem; } @@ -385,7 +389,7 @@ void UBThumbnailWidget::mouseMoveEvent(QMouseEvent *event) { if (lassoSelectedItem) { - UBSceneThumbnailPixmap *thumbnailItem = dynamic_cast(lassoSelectedItem); + UBThumbnailPixmap *thumbnailItem = dynamic_cast(lassoSelectedItem); if (thumbnailItem) lassoSelectedThumbnailItems += lassoSelectedItem; @@ -767,163 +771,226 @@ UBThumbnail::~UBThumbnail() delete mSelectionItem; } - -UBSceneThumbnailNavigPixmap::UBSceneThumbnailNavigPixmap(const QPixmap& pix, UBDocumentProxy* proxy, int pSceneIndex) - : UBSceneThumbnailPixmap(pix, proxy, pSceneIndex) - , bButtonsVisible(false) - , bCanDelete(false) - , bCanMoveUp(false) - , bCanMoveDown(false) +void UBWidgetTextThumbnailElement::Place(int row, int col, qreal width, qreal height) { - if(0 <= UBDocumentContainer::pageFromSceneIndex(pSceneIndex)){ - setAcceptHoverEvents(true); - setFlag(QGraphicsItem::ItemIsSelectable, true); + 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(); -UBSceneThumbnailNavigPixmap::~UBSceneThumbnailNavigPixmap() -{ + qreal scaleWidth = width / w; + qreal scaleHeight = height / h; + qreal scaleFactor = qMin(scaleWidth, scaleHeight); + UBThumbnail* pix = dynamic_cast(this->thumbnail); -} + QTransform transform; + transform.scale(scaleFactor, scaleFactor); -void UBSceneThumbnailNavigPixmap::hoverEnterEvent(QGraphicsSceneHoverEvent *event) -{ - event->accept(); - bButtonsVisible = true; - bCanDelete = true; - bCanMoveDown = false; - bCanMoveUp = false; - if(sceneIndex() < proxy()->pageCount() - 1) - bCanMoveDown = true; - if(sceneIndex() > 0) - bCanMoveUp = true; - if(proxy()->pageCount() == 1) - bCanDelete = false; - update(); -} + // Apply the scaling + this->thumbnail->setTransform(transform); + this->thumbnail->setFlag(QGraphicsItem::ItemIsSelectable, true); -void UBSceneThumbnailNavigPixmap::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) -{ - event->accept(); - bButtonsVisible = false; - update(); + 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); + } + } } -void UBSceneThumbnailNavigPixmap::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +void UBDraggableThumbnail::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { - Q_UNUSED(option); - Q_UNUSED(widget); + QGraphicsProxyWidget::paint(painter, option, widget); + using namespace UBThumbnailUI; - UBSceneThumbnailPixmap::paint(painter, option, widget); - if(bButtonsVisible) - { - if(bCanDelete) - painter->drawPixmap(0, 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/close.svg")); + if (editable()) + { + if(deletable()) + draw(painter, *getIcon("close")); else - painter->drawPixmap(0, 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/closeDisabled.svg")); + draw(painter, *getIcon("closeDisabled")); - painter->drawPixmap(BUTTONSIZE + BUTTONSPACING, 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/duplicate.svg")); + draw(painter, *getIcon("duplicate")); - if(bCanMoveUp) - painter->drawPixmap(2*(BUTTONSIZE + BUTTONSPACING), 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/moveUp.svg")); + if(movableUp()) + draw(painter, *getIcon("moveUp")); else - painter->drawPixmap(2*(BUTTONSIZE + BUTTONSPACING), 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/moveUpDisabled.svg")); - if(bCanMoveDown) - painter->drawPixmap(3*(BUTTONSIZE + BUTTONSPACING), 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/menu.svg")); + draw(painter, *getIcon("moveUpDisabled")); + + if(movableDown()) + draw(painter, *getIcon("moveDown")); else - painter->drawPixmap(3*(BUTTONSIZE + BUTTONSPACING), 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/menuDisabled.svg")); + draw(painter, *getIcon("moveDownDisabled")); + } } -void UBSceneThumbnailNavigPixmap::mousePressEvent(QGraphicsSceneMouseEvent *event) +void UBDraggableThumbnail::hoverEnterEvent(QGraphicsSceneHoverEvent *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(p.x() >= BUTTONSIZE + BUTTONSPACING && p.x() <= 2*BUTTONSIZE + BUTTONSPACING && p.y() >= 0 && p.y() <= BUTTONSIZE) - duplicatePage(); - - if(bCanMoveUp && p.x() >= 2*(BUTTONSIZE + BUTTONSPACING) && p.x() <= 3*BUTTONSIZE + 2*BUTTONSPACING && p.y() >= 0 && p.y() <= BUTTONSIZE) - moveUpPage(); - if(bCanMoveDown && p.x() >= 3*(BUTTONSIZE + BUTTONSPACING) && p.x() <= 4*BUTTONSIZE + 3*BUTTONSPACING && p.y() >= 0 && p.y() <= BUTTONSIZE) - moveDownPage(); + event->accept(); + showUI(); + update(); +} +void UBDraggableThumbnail::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) +{ event->accept(); + hideUI(); + update(); } -void UBSceneThumbnailNavigPixmap::deletePage() +void UBDraggableThumbnail::deletePage() { if(UBApplication::mainWindow->yesNoQuestion(QObject::tr("Remove Page"), QObject::tr("Are you sure you want to remove 1 page from the selected document '%0'?").arg(UBApplication::documentController->selectedDocument()->metaData(UBSettings::documentName).toString()))){ UBApplication::boardController->deleteScene(sceneIndex()); } } -void UBSceneThumbnailNavigPixmap::duplicatePage() +void UBDraggableThumbnail::duplicatePage() { UBApplication::boardController->duplicateScene(sceneIndex()); } -void UBSceneThumbnailNavigPixmap::moveUpPage() +void UBDraggableThumbnail::moveUpPage() { if (sceneIndex()!=0) UBApplication::boardController->moveSceneToIndex(sceneIndex(), sceneIndex() - 1); } -void UBSceneThumbnailNavigPixmap::moveDownPage() +void UBDraggableThumbnail::moveDownPage() { if (sceneIndex() < UBApplication::boardController->selectedDocument()->pageCount()-1) UBApplication::boardController->moveSceneToIndex(sceneIndex(), sceneIndex() + 1); } -void UBImgTextThumbnailElement::Place(int row, int col, qreal width, qreal height) +void UBDraggableThumbnail::mousePressEvent(QGraphicsSceneMouseEvent *event) { - int labelSpacing = 0; - if(this->caption) + event->accept(); +} + +void UBDraggableThumbnail::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + QPointF p = event->pos(); + + using namespace UBThumbnailUI; + + if (triggered(p.y())) { - QFontMetrics fm(this->caption->font()); - labelSpacing = UBSettings::thumbnailSpacing + fm.height(); + if(deletable() && getIcon("close")->triggered(p.x())) + deletePage(); + else if(getIcon("duplicate")->triggered(p.x())) + duplicatePage(); + else if(movableUp() && getIcon("moveUp")->triggered(p.x())) + moveUpPage(); + else if (movableDown() && getIcon("moveDown")->triggered(p.x())) + moveDownPage(); } - 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); + event->accept(); +} - QTransform transform; - transform.scale(scaleFactor, scaleFactor); - // Apply the scaling - this->thumbnail->setTransform(transform); - this->thumbnail->setFlag(QGraphicsItem::ItemIsSelectable, true); +void UBDraggableThumbnailView::updatePos(qreal width, qreal height) +{ + QFontMetrics fm(mPageNumber->font()); + int labelSpacing = UBSettings::thumbnailSpacing + fm.height(); - if(pix) - { - pix->setColumn(col); - pix->setRow(row); - } + int w = boundingRect().width(); + int h = boundingRect().height(); - QPointF pos(border + (width - w * scaleFactor) / 2 + col * (width + border), - border + row * (height + border + labelSpacing) + (height - h * scaleFactor) / 2); + qreal scaledWidth = width / w; + qreal scaledHeight = height / h; + qreal scaledFactor = qMin(scaledWidth, scaledHeight); - this->thumbnail->setPos(pos); + QTransform transform; + transform.scale(scaledFactor, scaledFactor); - if(this->caption) - { - QFontMetrics fm(this->caption->font()); - QString elidedText = fm.elidedText(this->caption->toPlainText(), Qt::ElideRight, width); + // Apply the scaling + setTransform(transform); + setFlag(QGraphicsItem::ItemIsSelectable, true); - 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); - } - } + QPointF position((width - w * scaledFactor) / 2, + sceneIndex() * (height + labelSpacing) + (height - h * scaledFactor) / 2); + + setPos(position); + + position.setY(position.y() + (height + h * scaledFactor) / 2); + position.setX(position.x() + (w * scaledFactor - fm.width(mPageNumber->toPlainText())) / 2); + + mPageNumber->setPos(position); +} + +UBThumbnailUI::UBThumbnailUIIcon* UBThumbnailUI::addIcon(const QString& thumbnailIcon, int pos) +{ + QString thumbnailIconPath = ":images/" + thumbnailIcon + ".svg"; + UBThumbnailUIIcon* newIcon = new UBThumbnailUIIcon(thumbnailIconPath, pos); + + using namespace UBThumbnailUI::_private; + if (!newIcon) + qDebug() << "cannot add Icon : check path : " + thumbnailIconPath; + else + catalog.insert(thumbnailIcon, newIcon); + + return newIcon; +} + +UBThumbnailUI::UBThumbnailUIIcon* UBThumbnailUI::getIcon(const QString& thumbnailIcon) +{ + using namespace UBThumbnailUI::_private; + if (!catalog.contains(thumbnailIcon)) + qDebug() << "cannot get Icon: check path ':images/" + thumbnailIcon + ".svg'"; + + return catalog.value(thumbnailIcon, NULL); +} + +void UBThumbnailUI::draw(QPainter *painter, const UBThumbnailUIIcon &thumbnailIcon) +{ + using namespace UBThumbnailUI; + painter->drawPixmap(thumbnailIcon.pos() * (ICONSIZE + ICONSPACING), 0, ICONSIZE, ICONSIZE, thumbnailIcon); +} + +void UBThumbnailUI::_private::initCatalog() +{ + using namespace UBThumbnailUI; + using namespace UBThumbnailUI::_private; + + addIcon("close", 0); + addIcon("closeDisabled", 0); + + addIcon("duplicate", 1); + + addIcon("moveUp", 2); + addIcon("moveUpDisabled", 2); + + addIcon("moveDown", 3); + addIcon("moveDownDisabled", 3); +} + +bool UBThumbnailUI::triggered(qreal y) +{ + return (y >= 0 && y <= UBThumbnailUI::ICONSIZE); } diff --git a/src/gui/UBThumbnailWidget.h b/src/gui/UBThumbnailWidget.h index 8d9770ab..81d05885 100644 --- a/src/gui/UBThumbnailWidget.h +++ b/src/gui/UBThumbnailWidget.h @@ -38,10 +38,14 @@ #include "frameworks/UBCoreGraphicsScene.h" #include "core/UBSettings.h" #include "domain/UBItem.h" +#include "gui/UBThumbnailView.h" +#include "document/UBDocumentProxy.h" + +#include +#include + #define STARTDRAGTIME 1000000 -#define BUTTONSIZE 48 -#define BUTTONSPACING 5 class UBDocumentProxy; class UBThumbnailTextItem; @@ -135,7 +139,6 @@ class UBThumbnailWidget : public QGraphicsView QTime mClickTime; }; - class UBThumbnail { public: @@ -190,6 +193,8 @@ class UBThumbnail void setColumn(int column) { mColumn = column; } int row() { return mRow; } void setRow(int row) { mRow = row; } + UBThumbnailTextItem *label(){return mLabel;} + void setLabel(UBThumbnailTextItem *label){mLabel = label;} protected: QGraphicsRectItem *mSelectionItem; @@ -198,41 +203,112 @@ class UBThumbnail int mColumn; int mRow; + UBThumbnailTextItem *mLabel; }; - -class UBThumbnailSvg : public QGraphicsSvgItem, public UBThumbnail +class UBThumbnailTextItem : public QGraphicsTextItem { public: - UBThumbnailSvg(const QString& path) - : QGraphicsSvgItem(path) + UBThumbnailTextItem(int index) + : QGraphicsTextItem(tr("Page %0").arg(index+1)) + , mWidth(0) + , mUnelidedText(toPlainText()) + , mIsHighlighted(false) + { + + } + + UBThumbnailTextItem(const QString& text) + : QGraphicsTextItem(text) + , mWidth(0) + , mUnelidedText(text) + , mIsHighlighted(false) { setFlag(QGraphicsItem::ItemSendsGeometryChanges, true); } - virtual ~UBThumbnailSvg() + QRectF boundingRect() const { return QRectF(QPointF(0.0, 0.0), QSize(mWidth, QFontMetricsF(font()).height() + 5));} + + void setWidth(qreal pWidth) { - // NOOP + if (mWidth != pWidth) + { + prepareGeometryChange(); + mWidth = pWidth; + computeText(); + } } - virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) + qreal width() {return mWidth;} + + void highlight() { - QStyleOptionGraphicsItem styleOption = UBThumbnail::muteStyleOption(option); - QGraphicsSvgItem::paint(painter, &styleOption, widget); + if (!mIsHighlighted) + { + mIsHighlighted = true; + computeText(); + } } - virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value) + void computeText() { - UBThumbnail::itemChange(this, change, value); - return QGraphicsSvgItem::itemChange(change, value); + 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 UBWidgetTextThumbnailElement +{ +protected: + QGraphicsItem* thumbnail; + UBThumbnailTextItem* caption; + int border; + +public: + UBWidgetTextThumbnailElement(QGraphicsProxyWidget* proxyWidget, UBThumbnailTextItem* text) + : thumbnail(proxyWidget) + , caption(text) + , border(0) + { + } + + 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; } +}; class UBThumbnailPixmap : public QGraphicsPixmapItem, public UBThumbnail { public: + UBThumbnailPixmap(const QPixmap& pix, UBDocumentProxy* proxy, int pSceneIndex) + : QGraphicsPixmapItem(pix) + , mDocumentProxy(proxy) + , mSceneIndex(pSceneIndex) + { + + } + UBThumbnailPixmap(const QPixmap& pix) : QGraphicsPixmapItem(pix) { @@ -241,11 +317,6 @@ class UBThumbnailPixmap : public QGraphicsPixmapItem, public UBThumbnail setFlag(QGraphicsItem::ItemSendsGeometryChanges, true); } - virtual ~UBThumbnailPixmap() - { - // NOOP - } - virtual QPainterPath shape () const { QPainterPath path; @@ -253,7 +324,6 @@ class UBThumbnailPixmap : public QGraphicsPixmapItem, public UBThumbnail return path; } - virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { QStyleOptionGraphicsItem styleOption = UBThumbnail::muteStyleOption(option); @@ -265,28 +335,44 @@ class UBThumbnailPixmap : public QGraphicsPixmapItem, public UBThumbnail UBThumbnail::itemChange(this, change, value); return QGraphicsPixmapItem::itemChange(change, value); } -}; + void highlight() + { -class UBSceneThumbnailPixmap : public UBThumbnailPixmap + } + + UBDocumentProxy* documentProxy() + { + return mDocumentProxy; + } + + int sceneIndex() + { + return mSceneIndex; + } + protected: + UBDocumentProxy* mDocumentProxy; + int mSceneIndex; +}; + +class UBThumbnailProxyWidget : public QGraphicsProxyWidget { public: - UBSceneThumbnailPixmap(const QPixmap& pix, UBDocumentProxy* proxy, int pSceneIndex) - : UBThumbnailPixmap(pix) - , mProxy(proxy) - , mSceneIndex(pSceneIndex) + UBThumbnailProxyWidget(UBDocumentProxy* proxy, int index) + : mDocumentProxy(proxy) + , mSceneIndex(index) { - // NOOP + } - virtual ~UBSceneThumbnailPixmap() + UBDocumentProxy* documentProxy() { - // NOOP + return mDocumentProxy; } - UBDocumentProxy* proxy() + void setSceneIndex(int i) { - return mProxy; + mSceneIndex = i; } int sceneIndex() @@ -294,27 +380,62 @@ class UBSceneThumbnailPixmap : public UBThumbnailPixmap return mSceneIndex; } - void highlight() - { - //NOOP - } - - private: - UBDocumentProxy* mProxy; +private: + UBDocumentProxy* mDocumentProxy; int mSceneIndex; }; -class UBSceneThumbnailNavigPixmap : public UBSceneThumbnailPixmap +class UBDraggableThumbnail : public UBThumbnailProxyWidget { public: - UBSceneThumbnailNavigPixmap(const QPixmap& pix, UBDocumentProxy* proxy, int pSceneIndex); - ~UBSceneThumbnailNavigPixmap(); + UBDraggableThumbnail(UBDocumentProxy* documentProxy, int index) + : UBThumbnailProxyWidget(documentProxy, index) + , mEditable(false) + { + + } + + bool editable() + { + return mEditable; + } + + bool deletable() + { + return documentProxy()->pageCount() > 1; + } + + bool movableUp() + { + return sceneIndex() > 0; + } + + bool movableDown() + { + return sceneIndex() < (documentProxy()->pageCount() -1); + } + + void showUI() + { + setEditable(true); + } + + void hideUI() + { + setEditable(false); + } + + void setEditable(bool editable) + { + mEditable = editable; + } protected: void hoverEnterEvent(QGraphicsSceneHoverEvent *event); void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); void mousePressEvent(QGraphicsSceneMouseEvent *event); + void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); private: void deletePage(); @@ -322,117 +443,104 @@ class UBSceneThumbnailNavigPixmap : public UBSceneThumbnailPixmap void moveUpPage(); void moveDownPage(); - bool bButtonsVisible; - bool bCanDelete; - bool bCanMoveUp; - bool bCanMoveDown; + bool mEditable; }; -class UBThumbnailVideo : public UBThumbnailPixmap +class UBDraggableThumbnailPixmap : public UBDraggableThumbnail { public: - UBThumbnailVideo(const QUrl &path) - : UBThumbnailPixmap(QPixmap(":/images/movie.svg")) - , mPath(path) - { - // NOOP - } - - virtual ~UBThumbnailVideo() - { - // NOOP - } - - QUrl path() - { - return mPath; - } - - private: - - QUrl mPath; + UBDraggableThumbnailPixmap(const QPixmap& pix, UBDocumentProxy* proxy, int pSceneIndex); + ~UBDraggableThumbnailPixmap(); }; -class UBThumbnailTextItem : public QGraphicsTextItem +class UBDraggableThumbnailView : public UBDraggableThumbnail { public: - UBThumbnailTextItem(const QString& text) - : QGraphicsTextItem(text) - , mUnelidedText(text) - , mIsHighlighted(false) + UBDraggableThumbnailView(UBThumbnailView* thumbnailView, UBDocumentProxy* documentProxy, int index) + : UBDraggableThumbnail(documentProxy, index) + , mThumbnailView(thumbnailView) + , mPageNumber(new UBThumbnailTextItem(index)) { - setFlag(QGraphicsItem::ItemSendsGeometryChanges, true); + setFlag(QGraphicsItem::ItemIsSelectable, true); + setWidget(mThumbnailView); + setAcceptDrops(true); } - QRectF boundingRect() const { return QRectF(QPointF(0.0, 0.0), QSize(mWidth, QFontMetricsF(font()).height() + 5));} - - void setWidth(qreal pWidth) + ~UBDraggableThumbnailView() { - if (mWidth != pWidth) - { - prepareGeometryChange(); - mWidth = pWidth; - computeText(); - } - }; + delete mPageNumber; // not a child of "this" QObject so it has to be deleted manually + } - qreal width() {return mWidth;} + void updatePos(qreal w, qreal h); - void highlight() + UBThumbnailView* thumbnailView() { - if (!mIsHighlighted) - { - mIsHighlighted = true; - computeText(); - } + return mThumbnailView; } - void computeText() + UBThumbnailTextItem* pageNumber() { - QFontMetricsF fm(font()); - QString elidedText = fm.elidedText(mUnelidedText, Qt::ElideRight, mWidth); + return mPageNumber; + } - if (mIsHighlighted) - { - setHtml("" + elidedText + ""); - } - else - { - setPlainText(elidedText); - } + void setPageNumber(int i) + { + mPageNumber->setPlainText(tr("Page %0").arg(i+1)); } - private: - qreal mWidth; - QString mUnelidedText; - bool mIsHighlighted; + private: + UBThumbnailView* mThumbnailView; + UBThumbnailTextItem* mPageNumber; + }; -class UBImgTextThumbnailElement +namespace UBThumbnailUI { -private: - UBSceneThumbnailNavigPixmap* thumbnail; - UBThumbnailTextItem* caption; - int border; + const int ICONSIZE = 96; + const int ICONSPACING = 10; -public: - UBImgTextThumbnailElement(UBSceneThumbnailNavigPixmap* thumb, UBThumbnailTextItem* text): border(0) + class UBThumbnailUIIcon : public QPixmap { - this->thumbnail = thumb; - this->caption = text; - } + public: - UBSceneThumbnailNavigPixmap* getThumbnail() const { return this->thumbnail; } - void setThumbnail(UBSceneThumbnailNavigPixmap* newGItem) { this->thumbnail = newGItem; } + UBThumbnailUIIcon(const QString& filename, int pos) + : QPixmap(QSize(ICONSIZE, ICONSIZE)) + , mPos(pos) + { + QSvgRenderer svgRenderer(filename); + QPainter painter; + fill(Qt::transparent); + painter.begin(this); + svgRenderer.render(&painter); + painter.end(); + } - UBThumbnailTextItem* getCaption() const { return this->caption; } - void setCaption(UBThumbnailTextItem* newcaption) { this->caption = newcaption; } + int pos() const + { + return mPos; + } - void Place(int row, int col, qreal width, qreal height); + bool triggered(qreal x) const + { + using namespace UBThumbnailUI; + return (x >= pos()*(ICONSIZE + ICONSPACING) && x <= (pos()+1)*ICONSIZE + pos()*ICONSPACING); + } - int getBorder() const { return this->border; } - void setBorder(int newBorder) { this->border = newBorder; } -}; + private: + int mPos; + }; + + namespace _private + { + //do not use this directly + static QMap catalog; + void initCatalog(); + } + UBThumbnailUIIcon* addIcon(const QString& thumbnailIcon, int pos); + UBThumbnailUIIcon* getIcon(const QString& thumbnailIcon); + void draw(QPainter* painter, const UBThumbnailUIIcon& thumbnailIcon); + bool triggered(qreal y); +} #endif /* UBTHUMBNAILWIDGET_H_ */ diff --git a/src/gui/gui.pri b/src/gui/gui.pri index a4921eff..8f9dea58 100644 --- a/src/gui/gui.pri +++ b/src/gui/gui.pri @@ -24,7 +24,6 @@ HEADERS += src/gui/UBThumbnailView.h \ src/gui/UBActionPalette.h \ src/gui/UBFavoriteToolPalette.h \ src/gui/UBKeyboardPalette.h \ - src/gui/UBDocumentNavigator.h \ src/gui/UBDockPalette.h \ src/gui/UBPropertyPalette.h \ src/gui/UBUpdateDlg.h \ @@ -41,7 +40,8 @@ HEADERS += src/gui/UBThumbnailView.h \ src/gui/UBMessagesDialog.h \ src/gui/UBOpenSankoreImporterWidget.h \ src/gui/UBStartupHintsPalette.h \ - src/gui/UBBackgroundPalette.h + src/gui/UBBackgroundPalette.h \ + src/gui/UBBoardThumbnailsView.h SOURCES += src/gui/UBThumbnailView.cpp \ src/gui/UBFloatingPalette.cpp \ src/gui/UBToolbarButtonGroup.cpp \ @@ -68,7 +68,6 @@ SOURCES += src/gui/UBThumbnailView.cpp \ src/gui/UBActionPalette.cpp \ src/gui/UBFavoriteToolPalette.cpp \ src/gui/UBKeyboardPalette.cpp \ - src/gui/UBDocumentNavigator.cpp \ src/gui/UBDockPalette.cpp \ src/gui/UBPropertyPalette.cpp \ src/gui/UBUpdateDlg.cpp \ @@ -85,7 +84,8 @@ SOURCES += src/gui/UBThumbnailView.cpp \ src/gui/UBMessagesDialog.cpp \ src/gui/UBOpenSankoreImporterWidget.cpp \ src/gui/UBStartupHintsPalette.cpp \ - src/gui/UBBackgroundPalette.cpp + src/gui/UBBackgroundPalette.cpp \ + src/gui/UBBoardThumbnailsView.cpp win32:SOURCES += src/gui/UBKeyboardPalette_win.cpp macx:OBJECTIVE_SOURCES += src/gui/UBKeyboardPalette_mac.mm linux-g++:SOURCES += src/gui/UBKeyboardPalette_linux.cpp diff --git a/src/tools/UBGraphicsCompass.cpp b/src/tools/UBGraphicsCompass.cpp index d1282b1f..1172ee36 100644 --- a/src/tools/UBGraphicsCompass.cpp +++ b/src/tools/UBGraphicsCompass.cpp @@ -304,6 +304,7 @@ void UBGraphicsCompass::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { updateResizeCursor(); updateDrawCursor(); + mDrewCenterCross = false; event->accept(); } else if (closeButtonRect().contains(event->pos()))