From bff3e8343d6357808392709ddfe6c8f884dfe4dd Mon Sep 17 00:00:00 2001 From: Anatoly Mihalchenko Date: Wed, 7 Mar 2012 18:38:08 +0300 Subject: [PATCH] http://188.165.53.52/jira/browse/SANKORE-284 --- src/board/UBBoardController.cpp | 4304 +++++++++++----------- src/board/UBBoardController.h | 574 +-- src/core/UBApplication.cpp | 15 + src/core/UBApplication.h | 324 +- src/core/UBDocumentManager.cpp | 588 +-- src/domain/UBGraphicsItemUndoCommand.cpp | 247 +- src/domain/UBGraphicsScene.cpp | 4018 ++++++++++---------- src/domain/UBGraphicsScene.h | 759 ++-- 8 files changed, 5463 insertions(+), 5366 deletions(-) diff --git a/src/board/UBBoardController.cpp b/src/board/UBBoardController.cpp index 9e787a8f..8af91ade 100644 --- a/src/board/UBBoardController.cpp +++ b/src/board/UBBoardController.cpp @@ -1,2129 +1,2175 @@ -/* - * 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 "UBBoardController.h" - -#include -#include - -#include "frameworks/UBFileSystemUtils.h" -#include "frameworks/UBPlatformUtils.h" - -#include "core/UBApplication.h" -#include "core/UBSettings.h" -#include "core/UBSetting.h" -#include "core/UBPersistenceManager.h" -#include "core/UBApplicationController.h" -#include "core/UBDocumentManager.h" -#include "core/UBMimeData.h" -#include "core/UBDownloadManager.h" - -#include "network/UBHttpGet.h" - -#include "gui/UBMessageWindow.h" -#include "gui/UBResources.h" -#include "gui/UBToolbarButtonGroup.h" -#include "gui/UBMainWindow.h" -#include "gui/UBToolWidget.h" -#include "gui/UBKeyboardPalette.h" -#include "gui/UBMagnifer.h" - -#include "domain/UBGraphicsPixmapItem.h" -#include "domain/UBGraphicsItemUndoCommand.h" -#include "domain/UBGraphicsProxyWidget.h" -#include "domain/UBGraphicsSvgItem.h" -#include "domain/UBGraphicsWidgetItem.h" -#include "domain/UBGraphicsVideoItem.h" -#include "domain/UBGraphicsAudioItem.h" -#include "domain/UBGraphicsPDFItem.h" -#include "domain/UBW3CWidget.h" -#include "domain/UBGraphicsTextItem.h" -#include "domain/UBPageSizeUndoCommand.h" - -#include "tools/UBToolsManager.h" - -#include "document/UBDocumentProxy.h" -#include "document/UBDocumentController.h" - -#include "board/UBDrawingController.h" -#include "board/UBBoardView.h" - -#include "podcast/UBPodcastController.h" - -#include "adaptors/UBMetadataDcSubsetAdaptor.h" - -#include "UBBoardPaletteManager.h" - -#include "core/memcheck.h" -//#include - -UBBoardController::UBBoardController(UBMainWindow* mainWindow) - : QObject(mainWindow->centralWidget()) - , mMainWindow(mainWindow) - , mActiveDocument(0) - , mActiveScene(0) - , mActiveSceneIndex(-1) - , mPaletteManager(0) - , mSoftwareUpdateDialog(0) - , mMessageWindow(0) - , mControlView(0) - , mDisplayView(0) - , mControlContainer(0) - , mControlLayout(0) - , mZoomFactor(1.0) - , mIsClosing(false) - , mSystemScaleFactor(1.0) - , mCleanupDone(false) -{ - mZoomFactor = UBSettings::settings()->boardZoomFactor->get().toDouble(); - - int penColorIndex = UBSettings::settings()->penColorIndex(); - int markerColorIndex = UBSettings::settings()->markerColorIndex(); - - mPenColorOnDarkBackground = UBSettings::settings()->penColors(true).at(penColorIndex); - mPenColorOnLightBackground = UBSettings::settings()->penColors(false).at(penColorIndex); - mMarkerColorOnDarkBackground = UBSettings::settings()->markerColors(true).at(markerColorIndex); - mMarkerColorOnLightBackground = UBSettings::settings()->markerColors(false).at(markerColorIndex); -} - - -void UBBoardController::init() -{ - setupViews(); - setupToolbar(); - - connect(UBPersistenceManager::persistenceManager(), SIGNAL(documentWillBeDeleted(UBDocumentProxy*)) - , this, SLOT(documentWillBeDeleted(UBDocumentProxy*))); - - connect(UBPersistenceManager::persistenceManager(), SIGNAL(documentSceneCreated(UBDocumentProxy*, int)) - , this, SLOT(documentSceneChanged(UBDocumentProxy*, int))); - - connect(UBPersistenceManager::persistenceManager(), SIGNAL(documentSceneDeleted(UBDocumentProxy*, int)) - , this, SLOT(documentSceneChanged(UBDocumentProxy*, int))); - - connect(UBPersistenceManager::persistenceManager(), SIGNAL(documentSceneMoved(UBDocumentProxy*, int)) - , this, SLOT(documentSceneChanged(UBDocumentProxy*, int))); - - connect(UBApplication::undoStack, SIGNAL(canUndoChanged(bool)) - , this, SLOT(undoRedoStateChange(bool))); - - connect(UBApplication::undoStack, SIGNAL(canRedoChanged (bool)) - , this, SLOT(undoRedoStateChange(bool))); - - connect(UBDrawingController::drawingController(), SIGNAL(stylusToolChanged(int)) - , this, SLOT(setToolCursor(int))); - - connect(UBDrawingController::drawingController(), SIGNAL(stylusToolChanged(int)) - , this, SLOT(stylusToolChanged(int))); - - connect(UBApplication::app(), SIGNAL(lastWindowClosed()) - , this, SLOT(lastWindowClosed())); - - connect(UBDownloadManager::downloadManager(), SIGNAL(downloadModalFinished()), this, SLOT(onDownloadModalFinished())); - connect(UBDownloadManager::downloadManager(), SIGNAL(addDownloadedFileToBoard(bool,QUrl,QString,QByteArray,QPointF,QSize,bool)), this, SLOT(downloadFinished(bool,QUrl,QString,QByteArray,QPointF,QSize,bool))); - - UBDocumentProxy* doc = UBPersistenceManager::persistenceManager()->createDocument(); - - setActiveDocumentScene(doc); - - undoRedoStateChange(true); -} - - -UBBoardController::~UBBoardController() -{ - delete mDisplayView; -} - - -void UBBoardController::setupViews() -{ - mControlContainer = new QWidget(mMainWindow->centralWidget()); - - mControlLayout = new QHBoxLayout(mControlContainer); - mControlLayout->setContentsMargins(0, 0, 0, 0); - - mControlView = new UBBoardView(this, mControlContainer); - mControlView->setInteractive(true); - mControlView->setMouseTracking(true); - - mControlView->grabGesture(Qt::SwipeGesture); - - mControlView->setTransformationAnchor(QGraphicsView::NoAnchor); - - mControlLayout->addWidget(mControlView); - mControlContainer->setObjectName("ubBoardControlContainer"); - mMainWindow->addBoardWidget(mControlContainer); - - connect(mControlView, SIGNAL(resized(QResizeEvent*)), this, SLOT(boardViewResized(QResizeEvent*))); - - // TODO UB 4.x Optimization do we have to create the display view even if their is - // only 1 screen - // - mDisplayView = new UBBoardView(this, UBItemLayerType::FixedBackground, UBItemLayerType::Tool, 0); - mDisplayView->setInteractive(false); - mDisplayView->setTransformationAnchor(QGraphicsView::NoAnchor); - - mMessageWindow = new UBMessageWindow(mControlView); - mMessageWindow->hide(); - - mPaletteManager = new UBBoardPaletteManager(mControlContainer, this); - connect(this, SIGNAL(activeSceneChanged()), mPaletteManager, SLOT(activeSceneChanged())); - -} - - -void UBBoardController::setupLayout() -{ - if(mPaletteManager) - mPaletteManager->setupLayout(); -} - - -void UBBoardController::setBoxing(QRect displayRect) -{ - if (displayRect.isNull()) - { - mControlLayout->setContentsMargins(0, 0, 0, 0); - return; - } - - qreal controlWidth = (qreal)mMainWindow->centralWidget()->width(); - qreal controlHeight = (qreal)mMainWindow->centralWidget()->height(); - qreal displayWidth = (qreal)displayRect.width(); - qreal displayHeight = (qreal)displayRect.height(); - - qreal displayRatio = displayWidth / displayHeight; - qreal controlRatio = controlWidth / controlHeight; - - if (displayRatio < controlRatio) - { - // Pillarboxing - int boxWidth = (controlWidth - (displayWidth * (controlHeight / displayHeight))) / 2; - mControlLayout->setContentsMargins(boxWidth, 0, boxWidth, 0); - } - else if (displayRatio > controlRatio) - { - // Letterboxing - int boxHeight = (controlHeight - (displayHeight * (controlWidth / displayWidth))) / 2; - mControlLayout->setContentsMargins(0, boxHeight, 0, boxHeight); - } - else - { - // No boxing - mControlLayout->setContentsMargins(0, 0, 0, 0); - } -} - - -QSize UBBoardController::displayViewport() -{ - return mDisplayView->geometry().size(); -} - - -QSize UBBoardController::controlViewport() -{ - return mControlView->geometry().size(); -} - - -QRectF UBBoardController::controlGeometry() -{ - return mControlView->geometry(); -} - - -void UBBoardController::setupToolbar() -{ - UBSettings *settings = UBSettings::settings(); - - // Setup color choice widget - QList colorActions; - colorActions.append(mMainWindow->actionColor0); - colorActions.append(mMainWindow->actionColor1); - colorActions.append(mMainWindow->actionColor2); - colorActions.append(mMainWindow->actionColor3); - - UBToolbarButtonGroup *colorChoice = - new UBToolbarButtonGroup(mMainWindow->boardToolBar, colorActions); - - mMainWindow->boardToolBar->insertWidget(mMainWindow->actionBackgrounds, colorChoice); - - connect(settings->appToolBarDisplayText, SIGNAL(changed(QVariant)), colorChoice, SLOT(displayText(QVariant))); - connect(colorChoice, SIGNAL(activated(int)), this, SLOT(setColorIndex(int))); - connect(UBDrawingController::drawingController(), SIGNAL(colorIndexChanged(int)), colorChoice, SLOT(setCurrentIndex(int))); - connect(UBDrawingController::drawingController(), SIGNAL(colorPaletteChanged()), colorChoice, SLOT(colorPaletteChanged())); - connect(UBDrawingController::drawingController(), SIGNAL(colorPaletteChanged()), this, SLOT(colorPaletteChanged())); - - colorChoice->displayText(QVariant(settings->appToolBarDisplayText->get().toBool())); - colorChoice->colorPaletteChanged(); - - // Setup line width choice widget - QList lineWidthActions; - lineWidthActions.append(mMainWindow->actionLineSmall); - lineWidthActions.append(mMainWindow->actionLineMedium); - lineWidthActions.append(mMainWindow->actionLineLarge); - - UBToolbarButtonGroup *lineWidthChoice = - new UBToolbarButtonGroup(mMainWindow->boardToolBar, lineWidthActions); - - connect(settings->appToolBarDisplayText, SIGNAL(changed(QVariant)), lineWidthChoice, SLOT(displayText(QVariant))); - - connect(lineWidthChoice, SIGNAL(activated(int)) - , UBDrawingController::drawingController(), SLOT(setLineWidthIndex(int))); - - connect(UBDrawingController::drawingController(), SIGNAL(lineWidthIndexChanged(int)) - , lineWidthChoice, SLOT(setCurrentIndex(int))); - - lineWidthChoice->displayText(QVariant(settings->appToolBarDisplayText->get().toBool())); - - mMainWindow->boardToolBar->insertWidget(mMainWindow->actionBackgrounds, lineWidthChoice); - - //-----------------------------------------------------------// - // Setup eraser width choice widget - - QList eraserWidthActions; - eraserWidthActions.append(mMainWindow->actionEraserSmall); - eraserWidthActions.append(mMainWindow->actionEraserMedium); - eraserWidthActions.append(mMainWindow->actionEraserLarge); - - UBToolbarButtonGroup *eraserWidthChoice = - new UBToolbarButtonGroup(mMainWindow->boardToolBar, eraserWidthActions); - - mMainWindow->boardToolBar->insertWidget(mMainWindow->actionBackgrounds, eraserWidthChoice); - - connect(settings->appToolBarDisplayText, SIGNAL(changed(QVariant)), eraserWidthChoice, SLOT(displayText(QVariant))); - connect(eraserWidthChoice, SIGNAL(activated(int)), UBDrawingController::drawingController(), SLOT(setEraserWidthIndex(int))); - - eraserWidthChoice->displayText(QVariant(settings->appToolBarDisplayText->get().toBool())); - eraserWidthChoice->setCurrentIndex(settings->eraserWidthIndex()); - - mMainWindow->boardToolBar->insertSeparator(mMainWindow->actionBackgrounds); - - //-----------------------------------------------------------// - - UBApplication::app()->insertSpaceToToolbarBeforeAction(mMainWindow->boardToolBar, mMainWindow->actionBoard); - UBApplication::app()->insertSpaceToToolbarBeforeAction(mMainWindow->tutorialToolBar, mMainWindow->actionBoard); - - UBApplication::app()->decorateActionMenu(mMainWindow->actionMenu); - - mMainWindow->actionBoard->setVisible(false); - - mMainWindow->webToolBar->hide(); - mMainWindow->documentToolBar->hide(); - mMainWindow->tutorialToolBar->hide(); - - connectToolbar(); - initToolbarTexts(); -} - - -void UBBoardController::setToolCursor(int tool) -{ - if (mActiveScene) - { - mActiveScene->setToolCursor(tool); - } - - mControlView->setToolCursor(tool); -} - - -void UBBoardController::connectToolbar() -{ - connect(mMainWindow->actionAdd, SIGNAL(triggered()), this, SLOT(addItem())); - connect(mMainWindow->actionNewPage, SIGNAL(triggered()), this, SLOT(addScene())); - connect(mMainWindow->actionDuplicatePage, SIGNAL(triggered()), this, SLOT(duplicateScene())); - - connect(mMainWindow->actionClearPage, SIGNAL(triggered()), this, SLOT(clearScene())); - connect(mMainWindow->actionEraseItems, SIGNAL(triggered()), this, SLOT(clearSceneItems())); - connect(mMainWindow->actionEraseAnnotations, SIGNAL(triggered()), this, SLOT(clearSceneAnnotation())); - - connect(mMainWindow->actionUndo, SIGNAL(triggered()), UBApplication::undoStack, SLOT(undo())); - connect(mMainWindow->actionRedo, SIGNAL(triggered()), UBApplication::undoStack, SLOT(redo())); - connect(mMainWindow->actionBack, SIGNAL( triggered()), this, SLOT(previousScene())); - connect(mMainWindow->actionForward, SIGNAL(triggered()), this, SLOT(nextScene())); - connect(mMainWindow->actionSleep, SIGNAL(triggered()), this, SLOT(blackout())); - connect(mMainWindow->actionVirtualKeyboard, SIGNAL(triggered(bool)), this, SLOT(showKeyboard(bool))); - connect(mMainWindow->actionImportPage, SIGNAL(triggered()), this, SLOT(importPage())); -} - - -void UBBoardController::initToolbarTexts() -{ - QList allToolbarActions; - - allToolbarActions << mMainWindow->boardToolBar->actions(); - allToolbarActions << mMainWindow->webToolBar->actions(); - allToolbarActions << mMainWindow->documentToolBar->actions(); - - foreach(QAction* action, allToolbarActions) - { - QString nominalText = action->text(); - QString shortText = truncate(nominalText, 48); - QPair texts(nominalText, shortText); - - mActionTexts.insert(action, texts); - } -} - - -void UBBoardController::setToolbarTexts() -{ - bool highResolution = mMainWindow->width() > 1024; - QSize iconSize; - - if (highResolution) - iconSize = QSize(48, 32); - else - iconSize = QSize(32, 32); - - mMainWindow->boardToolBar->setIconSize(iconSize); - mMainWindow->webToolBar->setIconSize(iconSize); - mMainWindow->documentToolBar->setIconSize(iconSize); - - foreach(QAction* action, mActionTexts.keys()) - { - QPair texts = mActionTexts.value(action); - - if (highResolution) - action->setText(texts.first); - else - { - action->setText(texts.second); - } - - action->setToolTip(texts.first); - } -} - - -QString UBBoardController::truncate(QString text, int maxWidth) -{ - QFontMetricsF fontMetrics(mMainWindow->font()); - return fontMetrics.elidedText(text, Qt::ElideRight, maxWidth); -} - - -void UBBoardController::stylusToolDoubleClicked(int tool) -{ - if (tool == UBStylusTool::ZoomIn || tool == UBStylusTool::ZoomOut) - { - zoomRestore(); - } - else if (tool == UBStylusTool::Hand) - { - centerRestore(); - } -} - - - -void UBBoardController::addScene() -{ - QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); - persistCurrentScene(); - - UBPersistenceManager::persistenceManager()->createDocumentSceneAt(mActiveDocument, mActiveSceneIndex + 1); - mActiveDocument->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); - - setActiveDocumentScene(mActiveDocument, mActiveSceneIndex + 1); - QApplication::restoreOverrideCursor(); -} - - -void UBBoardController::addScene(UBGraphicsScene* scene, bool replaceActiveIfEmpty) -{ - if (scene) - { - UBGraphicsScene* clone = scene->sceneDeepCopy(); - - if (scene->document() && (scene->document() != mActiveDocument)) - { - foreach(QUrl relativeFile, scene->relativeDependencies()) - { - QString source = scene->document()->persistencePath() + "/" + relativeFile.toString(); - QString target = mActiveDocument->persistencePath() + "/" + relativeFile.toString(); - - QFileInfo fi(target); - QDir d = fi.dir(); - - d.mkpath(d.absolutePath()); - QFile::copy(source, target); - } - } - - if (replaceActiveIfEmpty && mActiveScene->isEmpty()) - { - UBPersistenceManager::persistenceManager()->persistDocumentScene(mActiveDocument, clone, mActiveSceneIndex); - setActiveDocumentScene(mActiveDocument, mActiveSceneIndex); - } - else - { - persistCurrentScene(); - UBPersistenceManager::persistenceManager()->insertDocumentSceneAt(mActiveDocument, clone, mActiveSceneIndex + 1); - setActiveDocumentScene(mActiveDocument, mActiveSceneIndex + 1); - } - - mActiveDocument->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); - } -} - - -void UBBoardController::addScene(UBDocumentProxy* proxy, int sceneIndex, bool replaceActiveIfEmpty) -{ - UBGraphicsScene* scene = UBPersistenceManager::persistenceManager()->loadDocumentScene(proxy, sceneIndex); - - if (scene) - { - addScene(scene, replaceActiveIfEmpty); - } -} - - -void UBBoardController::duplicateScene() -{ - if (UBApplication::applicationController->displayMode() != UBApplicationController::Board) - return; - - QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); - persistCurrentScene(); - - UBPersistenceManager::persistenceManager()->duplicateDocumentScene(mActiveDocument, mActiveSceneIndex); - mActiveDocument->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); - - setActiveDocumentScene(mActiveDocument, mActiveSceneIndex + 1); - QApplication::restoreOverrideCursor(); - - emit pageChanged(); -} - - -void UBBoardController::clearScene() -{ - if (mActiveScene) - { - mActiveScene->clearItemsAndAnnotations(); - updateActionStates(); - } -} - - -void UBBoardController::clearSceneItems() -{ - if (mActiveScene) - { - mActiveScene->clearItems(); - updateActionStates(); - } -} - - -void UBBoardController::clearSceneAnnotation() -{ - if (mActiveScene) - { - mActiveScene->clearAnnotations(); - updateActionStates(); - } -} - - -void UBBoardController::showDocumentsDialog() -{ - if (mActiveDocument) - persistCurrentScene(); - - UBApplication::mainWindow->actionLibrary->setChecked(false); - -} - -void UBBoardController::libraryDialogClosed(int ret) -{ - Q_UNUSED(ret); - - mMainWindow->actionLibrary->setChecked(false); -} - - -void UBBoardController::blackout() -{ - UBApplication::applicationController->blackout(); -} - - -void UBBoardController::showKeyboard(bool show) -{ - if(show) - UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); - mPaletteManager->showVirtualKeyboard(show); -} - - -void UBBoardController::zoomIn(QPointF scenePoint) -{ - if (mControlView->transform().m11() > UB_MAX_ZOOM) - { - qApp->beep(); - return; - } - zoom(mZoomFactor, scenePoint); -} - - -void UBBoardController::zoomOut(QPointF scenePoint) -{ - if ((mControlView->horizontalScrollBar()->maximum() == 0) && (mControlView->verticalScrollBar()->maximum() == 0)) - { - // Do not zoom out if we reached the maximum - qApp->beep(); - return; - } - - qreal newZoomFactor = 1 / mZoomFactor; - - zoom(newZoomFactor, scenePoint); -} - - -void UBBoardController::zoomRestore() -{ - QTransform tr; - - tr.scale(mSystemScaleFactor, mSystemScaleFactor); - mControlView->setTransform(tr); - - centerRestore(); - - foreach(QGraphicsItem *gi, mActiveScene->selectedItems ()) - { - //force item to redraw the frame (for the anti scale calculation) - gi->setSelected(false); - gi->setSelected(true); - } - - emit zoomChanged(1.0); -} - - -void UBBoardController::centerRestore() -{ - centerOn(QPointF(0,0)); -} - - -void UBBoardController::centerOn(QPointF scenePoint) -{ - mControlView->centerOn(scenePoint); - UBApplication::applicationController->adjustDisplayView(); -} - - -void UBBoardController::zoom(const qreal ratio, QPointF scenePoint) -{ - - QPointF viewCenter = mControlView->mapToScene(QRect(0, 0, mControlView->width(), mControlView->height()).center()); - QPointF offset = scenePoint - viewCenter; - QPointF scalledOffset = offset / ratio; - - mControlView->scale(ratio, ratio); - - qreal currentZoom = mControlView->viewportTransform().m11() / mSystemScaleFactor; - - QPointF newCenter = scenePoint - scalledOffset; - - mControlView->centerOn(newCenter); - - emit zoomChanged(currentZoom); - UBApplication::applicationController->adjustDisplayView(); - - emit controlViewportChanged(); -} - - -void UBBoardController::handScroll(qreal dx, qreal dy) -{ -// mControlView->horizontalScrollBar()->setValue(mControlView->horizontalScrollBar()->value() - dx); -// mControlView->verticalScrollBar()->setValue(mControlView->verticalScrollBar()->value() - dy); - mControlView->translate(dx, dy); - - UBApplication::applicationController->adjustDisplayView(); - - emit controlViewportChanged(); -} - - -void UBBoardController::previousScene() -{ - if (mActiveSceneIndex > 0) - { - QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); - persistCurrentScene(); - setActiveDocumentScene(mActiveDocument, mActiveSceneIndex - 1); - QApplication::restoreOverrideCursor(); - } - - updateActionStates(); - emit pageChanged(); -} - - -void UBBoardController::nextScene() -{ - if (mActiveSceneIndex < mActiveDocument->pageCount() - 1) - { - QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); - persistCurrentScene(); - setActiveDocumentScene(mActiveDocument, mActiveSceneIndex + 1); - QApplication::restoreOverrideCursor(); - } - - updateActionStates(); - emit pageChanged(); -} - - -void UBBoardController::firstScene() -{ - if (mActiveSceneIndex > 0) - { - QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); - persistCurrentScene(); - setActiveDocumentScene(mActiveDocument, 0); - QApplication::restoreOverrideCursor(); - } - - updateActionStates(); - emit pageChanged(); -} - - -void UBBoardController::lastScene() -{ - if (mActiveSceneIndex < mActiveDocument->pageCount() - 1) - { - QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); - persistCurrentScene(); - setActiveDocumentScene(mActiveDocument, mActiveDocument->pageCount() - 1); - QApplication::restoreOverrideCursor(); - } - - updateActionStates(); - emit pageChanged(); -} - - -void UBBoardController::downloadURL(const QUrl& url, const QPointF& pPos, const QSize& pSize, bool isBackground) -{ - qDebug() << "something has been dropped on the board! Url is: " << url.toString(); - QString sUrl = url.toString(); - - if(sUrl.startsWith("uniboardTool://")) - { - downloadFinished(true, url, "application/vnd.mnemis-uniboard-tool", QByteArray(), pPos, pSize, isBackground); - } - else if (sUrl.startsWith("file://") || sUrl.startsWith("/")) - { - QString fileName = url.toLocalFile(); - - QString contentType = UBFileSystemUtils::mimeTypeFromFileName(fileName); - - bool shouldLoadFileData = - contentType.startsWith("image") - || contentType.startsWith("application/widget") - || contentType.startsWith("application/vnd.apple-widget"); - - QFile file(fileName); - - if (shouldLoadFileData) - file.open(QIODevice::ReadOnly); - - downloadFinished(true, url, contentType, file.readAll(), pPos, pSize, isBackground); - - if (shouldLoadFileData) - file.close(); - } - else - { - // When we fall there, it means that we are dropping something from the web to the board - sDownloadFileDesc desc; - desc.modal = true; - desc.url = url.toString(); - desc.currentSize = 0; - desc.name = QFileInfo(url.toString()).fileName(); - desc.totalSize = 0; // The total size will be retrieved during the download - desc.pos = pPos; - desc.size = pSize; - desc.isBackground = isBackground; - - UBDownloadManager::downloadManager()->addFileToDownload(desc); - } -} - - -void UBBoardController::downloadFinished(bool pSuccess, QUrl sourceUrl, QString pContentTypeHeader, QByteArray pData, QPointF pPos, QSize pSize, bool isBackground) -{ - QString mimeType = pContentTypeHeader; - - // In some cases "image/jpeg;charset=" is retourned by the drag-n-drop. That is - // why we will check if an ; exists and take the first part (the standard allows this kind of mimetype) - int position=mimeType.indexOf(";"); - if(position != -1) - mimeType=mimeType.left(position); - - if (!pSuccess) - { - UBApplication::showMessage(tr("Downloading content %1 failed").arg(sourceUrl.toString())); - return; - } - - if (!sourceUrl.toString().startsWith("file://") && !sourceUrl.toString().startsWith("uniboardTool://")) - UBApplication::showMessage(tr("Download finished")); - - if (mimeType == "image/jpeg" - || mimeType == "image/png" - || mimeType == "image/gif" - || mimeType == "image/tiff" - || mimeType == "image/bmp") - { - - qDebug() << "accepting mime type" << mimeType << "as raster image"; - - QImage img; - img.loadFromData(pData); - QPixmap pix = QPixmap::fromImage(img); - - UBGraphicsPixmapItem* pixItem = mActiveScene->addPixmap(pix, pPos, 1.); - pixItem->setSourceUrl(sourceUrl); - - if (isBackground) - { - mActiveScene->setAsBackgroundObject(pixItem, true); - } - else - { - mActiveScene->scaleToFitDocumentSize(pixItem, true, UBSettings::objectInControlViewMargin); - pixItem->setSelected(true); - UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); - } - } - else if (mimeType == "image/svg+xml") - { - qDebug() << "accepting mime type" << mimeType << "as vecto image"; - - UBGraphicsSvgItem* svgItem = mActiveScene->addSvg(sourceUrl, pPos); - svgItem->setSourceUrl(sourceUrl); - - if (isBackground) - { - mActiveScene->setAsBackgroundObject(svgItem); - } - else - { - mActiveScene->scaleToFitDocumentSize(svgItem, true, UBSettings::objectInControlViewMargin); - svgItem->setSelected(true); - UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); - } - } - else if (mimeType == "application/vnd.apple-widget") //mime type invented by us :-( - { - qDebug() << "accepting mime type" << mimeType << "as Apple widget"; - - QUrl widgetUrl = sourceUrl; - - if (pData.length() > 0) - { - widgetUrl = expandWidgetToTempDir(pData, "wdgt"); - } - - UBGraphicsWidgetItem* appleWidgetItem = mActiveScene->addAppleWidget(widgetUrl, pPos); - - appleWidgetItem->setSourceUrl(sourceUrl); - - if (isBackground) - { - mActiveScene->setAsBackgroundObject(appleWidgetItem); - } - else - { - UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); - } - } - else if (mimeType == "application/widget") - { - qDebug() << "accepting mime type" << mimeType << "as W3C widget"; - QUrl widgetUrl = sourceUrl; - - if (pData.length() > 0) - { - widgetUrl = expandWidgetToTempDir(pData); - } - - UBGraphicsWidgetItem *w3cWidgetItem = addW3cWidget(widgetUrl, pPos); - - if (isBackground) - { - mActiveScene->setAsBackgroundObject(w3cWidgetItem); - } - else - { - UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); - } - } - else if (mimeType.startsWith("video/")) - { - qDebug() << "accepting mime type" << mimeType << "as video"; - - UBGraphicsVideoItem *videoItem = 0; - - if (pData.length() > 0) - { - QUuid uuid = QUuid::createUuid(); - - QUrl url = QUrl::fromLocalFile(UBPersistenceManager::persistenceManager() - ->addVideoFileToDocument(mActiveDocument, sourceUrl, pData, uuid)); - - videoItem = mActiveScene->addVideo(url, false, pPos); - - videoItem->setSourceUrl(sourceUrl); - videoItem->setUuid(uuid); - } - else - { - videoItem = addVideo(sourceUrl, false, pPos); - } - - if(videoItem){ - connect(this, SIGNAL(activeSceneChanged()), videoItem, SLOT(activeSceneChanged())); - } - - UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); - } - else if (mimeType.startsWith("audio/")) - { - qDebug() << "accepting mime type" << mimeType << "as audio"; - - UBGraphicsAudioItem *audioItem = 0; - - if (pData.length() > 0) - { - QUuid uuid = QUuid::createUuid(); - - QUrl url = QUrl::fromLocalFile(UBPersistenceManager::persistenceManager() - ->addAudioFileToDocument(mActiveDocument, sourceUrl, pData, uuid)); - - audioItem = mActiveScene->addAudio(url, false, pPos); - - audioItem->setSourceUrl(sourceUrl); - audioItem->setUuid(uuid); - } - else - { - audioItem = addAudio(sourceUrl, false, pPos); - } - - if(audioItem){ - connect(this, SIGNAL(activeSceneChanged()), audioItem, SLOT(activeSceneChanged())); - } - - UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); - } - - else if (mimeType.startsWith("application/x-shockwave-flash")) - { - - qDebug() << "accepting mime type" << mimeType << "as flash"; - - QString sUrl = sourceUrl.toString(); - - if (sUrl.startsWith("file://") || sUrl.startsWith("/")) - { - sUrl = sourceUrl.toLocalFile(); - } - - QTemporaryFile* eduMediaFile = 0; - - if (sUrl.toLower().contains("edumedia-sciences.com")) - { - eduMediaFile = new QTemporaryFile("XXXXXX.swf"); - if (eduMediaFile->open()) - { - eduMediaFile->write(pData); - QFileInfo fi(*eduMediaFile); - sUrl = fi.absoluteFilePath(); - } - } - - QSize size; - - if (pSize.height() > 0 && pSize.width() > 0) - size = pSize; - else - size = mActiveScene->nominalSize() * .8; - - QString widgetUrl = UBW3CWidget::createNPAPIWrapper(sUrl, mimeType, size); - - if (widgetUrl.length() > 0) - { - UBGraphicsWidgetItem *widgetItem = mActiveScene->addW3CWidget(QUrl::fromLocalFile(widgetUrl), pPos); - - widgetItem->setSourceUrl(sourceUrl); - - UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); - } - - if (eduMediaFile) - delete eduMediaFile; - - } - else if (mimeType.startsWith("application/pdf")) - { - qDebug() << "accepting mime type" << mimeType << "as PDF"; - qDebug() << "pdf data length: " << pData.size(); - qDebug() << "sourceurl : " + sourceUrl.toString(); - int result = 0; - if(!sourceUrl.isEmpty()){ - QFile sourceFile(sourceUrl.toLocalFile()); - result = UBDocumentManager::documentManager()->addFileToDocument(mActiveDocument, sourceFile); - } - else if(pData.size()){ - QTemporaryFile pdfFile("XXXXXX.pdf"); - if (pdfFile.open()) - { - pdfFile.write(pData); - result = UBDocumentManager::documentManager()->addFileToDocument(mActiveDocument, pdfFile); - pdfFile.close(); - } - } - - if (result){ - mActiveDocument->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); - } - } - else if (mimeType.startsWith("application/vnd.mnemis-uniboard-tool")) - { - qDebug() << "accepting mime type" << mimeType << "as Uniboard Tool"; - - if (sourceUrl.toString() == UBToolsManager::manager()->compass.id) - { - mActiveScene->addCompass(pPos); - UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); - } - else if (sourceUrl.toString() == UBToolsManager::manager()->ruler.id) - { - mActiveScene->addRuler(pPos); - UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); - } - else if (sourceUrl.toString() == UBToolsManager::manager()->protractor.id) - { - mActiveScene->addProtractor(pPos); - UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); - } - else if (sourceUrl.toString() == UBToolsManager::manager()->triangle.id) - { - mActiveScene->addTriangle(pPos); - UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); - } - else if (sourceUrl.toString() == UBToolsManager::manager()->cache.id) - { - mActiveScene->addCache(); - UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); - } - else if (sourceUrl.toString() == UBToolsManager::manager()->magnifier.id) - { - UBMagnifierParams params; - params.x = controlContainer()->geometry().width() / 2; - params.y = controlContainer()->geometry().height() / 2; - params.zoom = 2; - params.sizePercentFromScene = 20; - mActiveScene->addMagnifier(params); - UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); - } - else if (sourceUrl.toString() == UBToolsManager::manager()->mask.id) - { - mActiveScene->addMask(pPos); - UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); - } - else - { - UBApplication::showMessage(tr("Unknown tool type %1").arg(sourceUrl.toString())); - } - } - else if (sourceUrl.toString().contains("edumedia-sciences.com")) - { - qDebug() << "accepting url " << sourceUrl.toString() << "as eduMedia content"; - - QTemporaryFile eduMediaZipFile("XXXXXX.edumedia"); - if (eduMediaZipFile.open()) - { - eduMediaZipFile.write(pData); - eduMediaZipFile.close(); - - QString tempDir = UBFileSystemUtils::createTempDir("uniboard-edumedia"); - - UBFileSystemUtils::expandZipToDir(eduMediaZipFile, tempDir); - - QDir appDir(tempDir); - - foreach(QString subDirName, appDir.entryList(QDir::AllDirs)) - { - QDir subDir(tempDir + "/" + subDirName + "/contents"); - - foreach(QString fileName, subDir.entryList(QDir::Files)) - { - if (fileName.toLower().endsWith(".swf")) - { - QString swfFile = tempDir + "/" + subDirName + "/contents/" + fileName; - - QSize size; - - if (pSize.height() > 0 && pSize.width() > 0) - size = pSize; - else - size = mActiveScene->nominalSize() * .8; - - QString widgetUrl = UBW3CWidget::createNPAPIWrapper(swfFile, "application/x-shockwave-flash", size); - - if (widgetUrl.length() > 0) - { - UBGraphicsWidgetItem *widgetItem = mActiveScene->addW3CWidget(QUrl::fromLocalFile(widgetUrl), pPos); - - widgetItem->setSourceUrl(sourceUrl); - - UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); - } - } - } - } - } - } - else - { - UBApplication::showMessage(tr("Unknown content type %1").arg(pContentTypeHeader)); - qWarning() << "ignoring mime type" << pContentTypeHeader ; - } -} - - -void UBBoardController::setActiveDocumentScene(UBDocumentProxy* pDocumentProxy, const int pSceneIndex) -{ - saveViewState(); - - bool documentChange = mActiveDocument != pDocumentProxy; - - int index = pSceneIndex; - int sceneCount = pDocumentProxy->pageCount(); - if (index >= sceneCount && sceneCount > 0) - index = sceneCount - 1; - - UBGraphicsScene* targetScene = UBPersistenceManager::persistenceManager()->loadDocumentScene(pDocumentProxy, index); - - bool sceneChange = targetScene != mActiveScene; - - if (targetScene) - { - if(sceneChange) - emit activeSceneWillChange(); - - ClearUndoStack(); - - mActiveScene = targetScene; - mActiveDocument = pDocumentProxy; - mActiveSceneIndex = index; - - updateSystemScaleFactor(); - - mControlView->setScene(mActiveScene); - mDisplayView->setScene(mActiveScene); - - pDocumentProxy->setDefaultDocumentSize(mActiveScene->nominalSize()); - updatePageSizeState(); - - adjustDisplayViews(); - - UBSettings::settings()->setDarkBackground(mActiveScene->isDarkBackground()); - UBSettings::settings()->setCrossedBackground(mActiveScene->isCrossedBackground()); - } - - selectionChanged(); - - updateBackgroundActionsState(mActiveScene->isDarkBackground(), mActiveScene->isCrossedBackground()); - updateBackgroundState(); - - if(documentChange) - { - emit activeDocumentChanged(); - UBGraphicsTextItem::lastUsedTextColor = QColor(); - } - - // Notify the navigator palette that the document has changed - emit setDocOnPageNavigator(pDocumentProxy); - - if (sceneChange) - { - emit activeSceneChanged(); - emit pageChanged(); - } -} - -void UBBoardController::ClearUndoStack() -{ - QSet uniqueItems; - // go through all stack command - for(int i = 0; i < UBApplication::undoStack->count(); i++) - { - - UBAbstractUndoCommand *abstractCmd = (UBAbstractUndoCommand*)UBApplication::undoStack->command(i); - if(abstractCmd->getType() != UBAbstractUndoCommand::undotype_GRAPHICITEM) - continue; - - UBGraphicsItemUndoCommand *cmd = (UBGraphicsItemUndoCommand*)UBApplication::undoStack->command(i); - - // go through all added and removed objects, for create list of unique objects - QSetIterator itAdded(cmd->GetAddedList()); - while (itAdded.hasNext()) - { - QGraphicsItem* item = itAdded.next(); - if( !uniqueItems.contains(item) ) - uniqueItems.insert(item); - } - - QSetIterator itRemoved(cmd->GetRemovedList()); - while (itRemoved.hasNext()) - { - QGraphicsItem* item = itRemoved.next(); - if( !uniqueItems.contains(item) ) - uniqueItems.insert(item); - } - } - - // clear stack, and command list - UBApplication::undoStack->clear(); - - // go through all unique items, and check, ot on scene, or not. - // if not on scene, than item can be deleted - - QSetIterator itUniq(uniqueItems); - while (itUniq.hasNext()) - { - QGraphicsItem* item = itUniq.next(); - UBGraphicsScene *scene = dynamic_cast(item->scene()); - if(!scene) - { - mActiveScene->deleteItem(item); - } - } - -} - -void UBBoardController::adjustDisplayViews() -{ - if (UBApplication::applicationController) - { - UBApplication::applicationController->adjustDisplayView(); - UBApplication::applicationController->adjustPreviousViews(mActiveSceneIndex, mActiveDocument); - } -} - - -void UBBoardController::changeBackground(bool isDark, bool isCrossed) -{ - bool currentIsDark = mActiveScene->isDarkBackground(); - bool currentIsCrossed = mActiveScene->isCrossedBackground(); - - if ((isDark != currentIsDark) || (currentIsCrossed != isCrossed)) - { - UBSettings::settings()->setDarkBackground(isDark); - UBSettings::settings()->setCrossedBackground(isCrossed); - - mActiveScene->setBackground(isDark, isCrossed); - - updateBackgroundState(); - - emit backgroundChanged(); - } -} - - -void UBBoardController::boardViewResized(QResizeEvent* event) -{ - Q_UNUSED(event); - - int innerMargin = UBSettings::boardMargin; - int userHeight = mControlContainer->height() - (2 * innerMargin); - - mMessageWindow->move(innerMargin, innerMargin + userHeight - mMessageWindow->height()); - mMessageWindow->adjustSizeAndPosition(); - - UBApplication::applicationController->initViewState( - mControlView->horizontalScrollBar()->value(), - mControlView->verticalScrollBar()->value()); - - updateSystemScaleFactor(); - - mControlView->centerOn(0,0); - - mPaletteManager->containerResized(); - - -} - - -void UBBoardController::documentWillBeDeleted(UBDocumentProxy* pProxy) -{ - if (mActiveDocument == pProxy) - { - if (!mIsClosing) - setActiveDocumentScene(UBPersistenceManager::persistenceManager()->createDocument()); - } -} - - -void UBBoardController::showMessage(const QString& message, bool showSpinningWheel) -{ - mMessageWindow->showMessage(message, showSpinningWheel); -} - - -void UBBoardController::hideMessage() -{ - mMessageWindow->hideMessage(); -} - - -void UBBoardController::setDisabled(bool disable) -{ - mMainWindow->boardToolBar->setDisabled(disable); - mControlView->setDisabled(disable); -} - - -void UBBoardController::selectionChanged() -{ - updateActionStates(); -} - - -void UBBoardController::undoRedoStateChange(bool canUndo) -{ - Q_UNUSED(canUndo); - - mMainWindow->actionUndo->setEnabled(UBApplication::undoStack->canUndo()); - mMainWindow->actionRedo->setEnabled(UBApplication::undoStack->canRedo()); - - updateActionStates(); -} - - -void UBBoardController::updateActionStates() -{ - mMainWindow->actionBack->setEnabled(mActiveDocument && (mActiveSceneIndex > 0)); - mMainWindow->actionForward->setEnabled(mActiveDocument && (mActiveSceneIndex < mActiveDocument->pageCount() - 1)); - mMainWindow->actionErase->setEnabled(mActiveScene && !mActiveScene->isEmpty()); -} - - -UBDocumentProxy* UBBoardController::activeDocument() const -{ - return mActiveDocument; -} - - -UBGraphicsScene* UBBoardController::activeScene() const -{ - return mActiveScene; -} - - -int UBBoardController::activeSceneIndex() const -{ - return mActiveSceneIndex; -} - - -void UBBoardController::documentSceneChanged(UBDocumentProxy* pDocumentProxy, int pIndex) -{ - Q_UNUSED(pIndex); - - if(mActiveDocument == pDocumentProxy) - { - setActiveDocumentScene(mActiveDocument, mActiveSceneIndex); - } -} - -void UBBoardController::closing() -{ - mIsClosing = true; - ClearUndoStack(); - lastWindowClosed(); -} - -void UBBoardController::lastWindowClosed() -{ - if (!mCleanupDone) - { - if (mActiveDocument->pageCount() == 1 && (!mActiveScene || mActiveScene->isEmpty())) - { - UBPersistenceManager::persistenceManager()->deleteDocument(mActiveDocument); - } - else - { - persistCurrentScene(); - } - - UBPersistenceManager::persistenceManager()->purgeEmptyDocuments(); - - mCleanupDone = true; - } -} - - - -void UBBoardController::setColorIndex(int pColorIndex) -{ - UBDrawingController::drawingController()->setColorIndex(pColorIndex); - - if (UBDrawingController::drawingController()->stylusTool() != UBStylusTool::Marker && - UBDrawingController::drawingController()->stylusTool() != UBStylusTool::Line && - UBDrawingController::drawingController()->stylusTool() != UBStylusTool::Text && - UBDrawingController::drawingController()->stylusTool() != UBStylusTool::Selector) - { - UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Pen); - } - - if (UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Pen || - UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Line || - UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Text || - UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Selector) - { - mPenColorOnDarkBackground = UBSettings::settings()->penColors(true).at(pColorIndex); - mPenColorOnLightBackground = UBSettings::settings()->penColors(false).at(pColorIndex); - - if (UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Selector) - { - // If we are in mode board, then do that - if(UBApplication::applicationController->displayMode() == UBApplicationController::Board) - { - UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Pen); - mMainWindow->actionPen->setChecked(true); - } - } - - emit penColorChanged(); - } - else if (UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Marker) - { - mMarkerColorOnDarkBackground = UBSettings::settings()->markerColors(true).at(pColorIndex); - mMarkerColorOnLightBackground = UBSettings::settings()->markerColors(false).at(pColorIndex); - } -} - -void UBBoardController::colorPaletteChanged() -{ - mPenColorOnDarkBackground = UBSettings::settings()->penColor(true); - mPenColorOnLightBackground = UBSettings::settings()->penColor(false); - mMarkerColorOnDarkBackground = UBSettings::settings()->markerColor(true); - mMarkerColorOnLightBackground = UBSettings::settings()->markerColor(false); -} - - -qreal UBBoardController::currentZoom() -{ - if (mControlView) - return mControlView->viewportTransform().m11() / mSystemScaleFactor; - else - return 1.0; -} - - -UBToolWidget* UBBoardController::addTool(const QUrl& toolUrl) -{ - return addTool(toolUrl, mControlView->mapToScene(mControlView->rect().center())); -} - - -UBToolWidget* UBBoardController::addTool(const QUrl& toolUrl, QPointF scenePos) -{ - UBToolWidget *toolWidget = new UBToolWidget(toolUrl, mMainWindow); // Deleted in UBBoardController::removeTool - QPoint pos = mControlView->mapToGlobal(mControlView->mapFromScene(scenePos)); - pos -= QPoint(toolWidget->width() / 2, toolWidget->height() / 2); - - toolWidget->move(pos); - - mTools.append(toolWidget); - - toolWidget->show(); - - return toolWidget; -} - - -void UBBoardController::removeTool(UBToolWidget* toolWidget) -{ - toolWidget->hide(); - - mTools.removeAll(toolWidget); - - delete toolWidget; -} - - -void UBBoardController::hide() -{ - UBApplication::mainWindow->actionLibrary->setChecked(false); - - controlViewHidden(); -} - - -void UBBoardController::show() -{ - UBApplication::mainWindow->actionLibrary->setChecked(false); - - controlViewShown(); -} - - -void UBBoardController::persistCurrentScene() -{ - if(UBPersistenceManager::persistenceManager() - && mActiveDocument && mActiveScene - && (mActiveSceneIndex >= 0)) - { - emit activeSceneWillBePersisted(); - - UBPersistenceManager::persistenceManager()->persistDocumentScene(mActiveDocument, mActiveScene, mActiveSceneIndex); - UBMetadataDcSubsetAdaptor::persist(mActiveDocument); - } -} - - -void UBBoardController::updateSystemScaleFactor() -{ - qreal newScaleFactor = 1.0; - - if (mActiveScene) - { - QSize pageNominalSize = mActiveScene->nominalSize(); - //we're going to keep scale factor untouched if the size is custom - QMap sizesMap = UBSettings::settings()->documentSizes; - if(pageNominalSize == sizesMap.value(DocumentSizeRatio::Ratio16_9) || pageNominalSize == sizesMap.value(DocumentSizeRatio::Ratio4_3)) - { - QSize controlSize = controlViewport(); - - qreal hFactor = ((qreal)controlSize.width()) / ((qreal)pageNominalSize.width()); - qreal vFactor = ((qreal)controlSize.height()) / ((qreal)pageNominalSize.height()); - - newScaleFactor = qMin(hFactor, vFactor); - } - } - - if (mSystemScaleFactor != newScaleFactor) - { - mSystemScaleFactor = newScaleFactor; - emit systemScaleFactorChanged(newScaleFactor); - } - - UBGraphicsScene::SceneViewState viewState = mActiveScene->viewState(); - - QTransform scalingTransform; - - qreal scaleFactor = viewState.zoomFactor * mSystemScaleFactor; - scalingTransform.scale(scaleFactor, scaleFactor); - - mControlView->setTransform(scalingTransform); - mControlView->horizontalScrollBar()->setValue(viewState.horizontalPosition); - mControlView->verticalScrollBar()->setValue(viewState.verticalPostition); -} - - -void UBBoardController::setWidePageSize(bool checked) -{ - Q_UNUSED(checked); - QSize newSize = UBSettings::settings()->documentSizes.value(DocumentSizeRatio::Ratio16_9); - - if (mActiveScene->nominalSize() != newSize) - { - UBPageSizeUndoCommand* uc = new UBPageSizeUndoCommand(mActiveScene, mActiveScene->nominalSize(), newSize); - UBApplication::undoStack->push(uc); - - setPageSize(newSize); - } -} - - -void UBBoardController::setRegularPageSize(bool checked) -{ - Q_UNUSED(checked); - QSize newSize = UBSettings::settings()->documentSizes.value(DocumentSizeRatio::Ratio4_3); - - if (mActiveScene->nominalSize() != newSize) - { - UBPageSizeUndoCommand* uc = new UBPageSizeUndoCommand(mActiveScene, mActiveScene->nominalSize(), newSize); - UBApplication::undoStack->push(uc); - - setPageSize(newSize); - } -} - - -void UBBoardController::setPageSize(QSize newSize) -{ - if (mActiveScene->nominalSize() != newSize) - { - mActiveScene->setNominalSize(newSize); - - saveViewState(); - - updateSystemScaleFactor(); - updatePageSizeState(); - adjustDisplayViews(); - mActiveDocument->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); - - UBSettings::settings()->pageSize->set(newSize); - } -} - -void UBBoardController::notifyCache(bool visible) -{ - if(visible) - { - emit cacheEnabled(); - } - else - { - emit cacheDisabled(); - } -} - -void UBBoardController::updatePageSizeState() -{ - if (mActiveScene->nominalSize() == UBSettings::settings()->documentSizes.value(DocumentSizeRatio::Ratio16_9)) - { - mMainWindow->actionWidePageSize->setChecked(true); - } - else if(mActiveScene->nominalSize() == UBSettings::settings()->documentSizes.value(DocumentSizeRatio::Ratio4_3)) - { - mMainWindow->actionRegularPageSize->setChecked(true); - } - else - { - mMainWindow->actionCustomPageSize->setChecked(true); - } -} - - -void UBBoardController::saveViewState() -{ - if (mActiveScene) - { - mActiveScene->setViewState(UBGraphicsScene::SceneViewState(currentZoom(), - mControlView->horizontalScrollBar()->value(), - mControlView->verticalScrollBar()->value())); - } -} - - -void UBBoardController::updateBackgroundState() -{ - //adjust background style - QString newBackgroundStyle; - - if (mActiveScene && mActiveScene->isDarkBackground()) - { - newBackgroundStyle ="QWidget {background-color: #0E0E0E}"; - } - else - { - newBackgroundStyle ="QWidget {background-color: #F1F1F1}"; - } -} - -void UBBoardController::stylusToolChanged(int tool) -{ - if (UBPlatformUtils::hasVirtualKeyboard() && mPaletteManager->mKeyboardPalette) - { - UBStylusTool::Enum eTool = (UBStylusTool::Enum)tool; - if(eTool != UBStylusTool::Selector && eTool != UBStylusTool::Text) - { - if(mPaletteManager->mKeyboardPalette->m_isVisible) - UBApplication::mainWindow->actionVirtualKeyboard->activate(QAction::Trigger); - } - } - - updateBackgroundState(); -} - - -QUrl UBBoardController::expandWidgetToTempDir(const QByteArray& pZipedData, const QString& ext) -{ - QUrl widgetUrl; - QTemporaryFile tmp; - - if (tmp.open()) - { - tmp.write(pZipedData); - tmp.flush(); - tmp.close(); - - QString tmpDir = UBFileSystemUtils::createTempDir() + "." + ext; - - if (UBFileSystemUtils::expandZipToDir(tmp, tmpDir)) - { - widgetUrl = QUrl::fromLocalFile(tmpDir); - } - } - - return widgetUrl; -} - - -void UBBoardController::grabScene(const QRectF& pSceneRect) -{ - if (mActiveScene) - { - QImage image(pSceneRect.width(), pSceneRect.height(), QImage::Format_ARGB32); - image.fill(Qt::transparent); - - QRectF targetRect(0, 0, pSceneRect.width(), pSceneRect.height()); - QPainter painter(&image); - painter.setRenderHint(QPainter::SmoothPixmapTransform); - painter.setRenderHint(QPainter::Antialiasing); - - mActiveScene->setRenderingContext(UBGraphicsScene::NonScreen); - mActiveScene->setRenderingQuality(UBItem::RenderingQualityHigh); - - mActiveScene->render(&painter, targetRect, pSceneRect); - - mActiveScene->setRenderingContext(UBGraphicsScene::Screen); - mActiveScene->setRenderingQuality(UBItem::RenderingQualityNormal); - - mPaletteManager->addItem(QPixmap::fromImage(image)); - mActiveDocument->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); - } -} - - -void UBBoardController::controlViewHidden() -{ - foreach(UBToolWidget* tool, mTools) - { - tool->hide(); - } -} - - -void UBBoardController::controlViewShown() -{ - foreach(UBToolWidget* tool, mTools) - { - tool->show(); - } -} - - -UBGraphicsVideoItem* UBBoardController::addVideo(const QUrl& pSourceUrl, bool startPlay, const QPointF& pos) -{ - QUuid uuid = QUuid::createUuid(); - QUrl concreteUrl = pSourceUrl; - -#ifdef Q_WS_X11 - concreteUrl = QUrl::fromLocalFile(mActiveDocument->persistencePath() + "/" + UBPersistenceManager::persistenceManager() - ->addVideoFileToDocument(mActiveDocument, pSourceUrl.toLocalFile(), uuid)); -#else - concreteUrl = QUrl::fromLocalFile(UBPersistenceManager::persistenceManager() - ->addVideoFileToDocument(mActiveDocument, pSourceUrl.toLocalFile(), uuid)); -#endif - - UBGraphicsVideoItem* vi = mActiveScene->addVideo(concreteUrl, startPlay, pos); - mActiveDocument->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); - - if (vi) { - vi->setUuid(uuid); - vi->setSourceUrl(pSourceUrl); - } - - return vi; - -} - -UBGraphicsAudioItem* UBBoardController::addAudio(const QUrl& pSourceUrl, bool startPlay, const QPointF& pos) -{ - QUuid uuid = QUuid::createUuid(); - QUrl concreteUrl = pSourceUrl; - -#ifdef Q_WS_X11 - concreteUrl = QUrl::fromLocalFile(mActiveDocument->persistencePath() + "/" + UBPersistenceManager::persistenceManager() - ->addAudioFileToDocument(mActiveDocument, pSourceUrl.toLocalFile(), uuid)); -#else - concreteUrl = QUrl::fromLocalFile(UBPersistenceManager::persistenceManager() - ->addAudioFileToDocument(mActiveDocument, pSourceUrl.toLocalFile(), uuid)); -#endif - - UBGraphicsAudioItem* vi = mActiveScene->addAudio(concreteUrl, startPlay, pos); - mActiveDocument->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); - - if (vi){ - vi->setUuid(uuid); - vi->setSourceUrl(pSourceUrl); - } - - return vi; - -} - -UBGraphicsWidgetItem *UBBoardController::addW3cWidget(const QUrl &pUrl, const QPointF &pos) -{ - UBGraphicsWidgetItem* w3cWidgetItem = 0; - - QUuid uuid = QUuid::createUuid(); - QUrl newUrl = pUrl; - - newUrl = QUrl::fromLocalFile(UBPersistenceManager::persistenceManager()->addGraphicsWidgteToDocument(mActiveDocument, pUrl.toLocalFile(), uuid)); - - w3cWidgetItem = mActiveScene->addW3CWidget(newUrl, pos); - - if (w3cWidgetItem) { - w3cWidgetItem->setUuid(uuid); - w3cWidgetItem->setOwnFolder(newUrl); - w3cWidgetItem->setSourceUrl(pUrl); - - QString struuid = UBStringUtils::toCanonicalUuid(uuid); - QString snapshotPath = mActiveDocument->persistencePath() + "/" + UBPersistenceManager::widgetDirectory + "/" + struuid + ".png"; - w3cWidgetItem->setSnapshotPath(QUrl::fromLocalFile(snapshotPath)); - UBGraphicsWidgetItem *tmpItem = dynamic_cast(w3cWidgetItem); - if (tmpItem) - tmpItem->widgetWebView()->takeSnapshot().save(snapshotPath, "PNG"); - - } - - return 0; -} - -void UBBoardController::cut() -{ - //---------------------------------------------------------// - - QList selectedItems; - foreach(QGraphicsItem* gi, mActiveScene->selectedItems()) - selectedItems << gi; - - //---------------------------------------------------------// - - QList selected; - foreach(QGraphicsItem* gi, selectedItems) - { - gi->setSelected(false); - - UBItem* ubItem = dynamic_cast(gi); - UBGraphicsItem *ubGi = dynamic_cast(gi); - - if (ubItem && ubGi && !mActiveScene->tools().contains(gi)) - { - selected << ubItem->deepCopy(); - ubGi->remove(); - } - } - - //---------------------------------------------------------// - - if (selected.size() > 0) - { - QClipboard *clipboard = QApplication::clipboard(); - - UBMimeDataGraphicsItem* mimeGi = new UBMimeDataGraphicsItem(selected); - - mimeGi->setData(UBApplication::mimeTypeUniboardPageItem, QByteArray()); - clipboard->setMimeData(mimeGi); - - mActiveDocument->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); - } - - //---------------------------------------------------------// -} - - -void UBBoardController::copy() -{ - QList selected; - - foreach(QGraphicsItem* gi, mActiveScene->selectedItems()) - { - UBItem* ubItem = dynamic_cast(gi); - - if (ubItem && !mActiveScene->tools().contains(gi)) - selected << ubItem->deepCopy(); - } - - if (selected.size() > 0) - { - QClipboard *clipboard = QApplication::clipboard(); - - UBMimeDataGraphicsItem* mimeGi = new UBMimeDataGraphicsItem(selected); - - mimeGi->setData(UBApplication::mimeTypeUniboardPageItem, QByteArray()); - clipboard->setMimeData(mimeGi); - - } -} - - -void UBBoardController::paste() -{ - QClipboard *clipboard = QApplication::clipboard(); - QPointF pos(0, 0); - processMimeData(clipboard->mimeData(), pos); - - mActiveDocument->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); -} - - -void UBBoardController::processMimeData(const QMimeData* pMimeData, const QPointF& pPos) -{ - if (pMimeData->hasFormat(UBApplication::mimeTypeUniboardPage)) - { - const UBMimeData* mimeData = qobject_cast (pMimeData); - - if (mimeData) - { - int previousActiveSceneIndex = activeSceneIndex(); - int previousPageCount = activeDocument()->pageCount(); - - foreach (UBMimeDataItem sourceItem, mimeData->items()) - addScene(sourceItem.documentProxy(), sourceItem.sceneIndex(), true); - - if (activeDocument()->pageCount() < previousPageCount + mimeData->items().count()) - setActiveDocumentScene(activeDocument(), previousActiveSceneIndex); - else - setActiveDocumentScene(activeDocument(), previousActiveSceneIndex + 1); - - return; - } - } - - if (pMimeData->hasFormat(UBApplication::mimeTypeUniboardPageItem)) - { - const UBMimeDataGraphicsItem* mimeData = qobject_cast (pMimeData); - - if (mimeData) - { - foreach(UBItem* item, mimeData->items()) - { - QGraphicsItem* gi = dynamic_cast(item->deepCopy()); - - if (gi) - { -// gi->setZValue(mActiveScene->getNextObjectZIndex()); - UBGraphicsItem::assignZValue(gi, mActiveScene->getNextObjectZIndex()); - mActiveScene->addItem(gi); - gi->setPos(gi->pos() + QPointF(50, 50)); - } - } - - return; - } - } - - if(pMimeData->hasHtml()) - { - QString qsHtml = pMimeData->html(); - QString url = UBApplication::urlFromHtml(qsHtml); - - if("" != url) - { - downloadURL(url, pPos); - return; - } - } - - if (pMimeData->hasUrls()) - { - QList urls = pMimeData->urls(); - - int index = 0; - - foreach(const QUrl url, urls){ - QPointF pos(pPos + QPointF(index * 15, index * 15)); - downloadURL(url, pos); - index++; - } - - return; - } - - if (pMimeData->hasImage()) - { - QImage img = qvariant_cast (pMimeData->imageData()); - QPixmap pix = QPixmap::fromImage(img); - - // validate that the image is really an image, webkit does not fill properly the image mime data - if (pix.width() != 0 && pix.height() != 0) - { - mActiveScene->addPixmap(pix, pPos, 1.); - return; - } - } - - if (pMimeData->hasText()) - { - if("" != pMimeData->text()){ - // Sometimes, it is possible to have an URL as text. we check here if it is the case - QString qsTmp = pMimeData->text().remove(QRegExp("[\\0]")); - if(qsTmp.startsWith("http")){ - downloadURL(QUrl(qsTmp), pPos); - } - else{ - mActiveScene->addTextHtml(pMimeData->html(), pPos); - } - } - else{ -#ifdef Q_WS_MACX - // With Safari, in 95% of the drops, the mime datas are hidden in Apple Web Archive pasteboard type. - // This is due to the way Safari is working so we have to dig into the pasteboard in order to retrieve - // the data. - QString qsUrl = UBPlatformUtils::urlFromClipboard(); - if("" != qsUrl){ - // We finally got the url of the dropped ressource! Let's import it! - downloadURL(qsUrl, pPos); - return; - } -#endif - } - } -} - - -void UBBoardController::togglePodcast(bool checked) -{ - if (UBPodcastController::instance()) - UBPodcastController::instance()->toggleRecordingPalette(checked); -} - - -void UBBoardController::moveGraphicsWidgetToControlView(UBGraphicsWidgetItem* graphicsWidget) -{ - QPoint controlViewPos = mControlView->mapFromScene(graphicsWidget->sceneBoundingRect().center()); - - graphicsWidget->setSelected(false); - - UBAbstractWidget *aw = graphicsWidget->widgetWebView(); - graphicsWidget->setWidget(0); - - UBToolWidget *toolWidget = new UBToolWidget(aw, mControlContainer); - - graphicsWidget->scene()->removeItem(graphicsWidget); // TODO UB 4.6 probably leaking the frame - - toolWidget->centerOn(mControlView->mapTo(mControlContainer, controlViewPos)); - - toolWidget->show(); -} - - -void UBBoardController::moveToolWidgetToScene(UBToolWidget* toolWidget) -{ - int xIsOdd = toolWidget->width() % 2; - int yIsOdd = toolWidget->height() % 2; - - QPoint mainWindowCenter = toolWidget->mapTo(mMainWindow, QPoint(toolWidget->width(), toolWidget->height()) / 2); - - UBAbstractWidget* webWidget = toolWidget->webWidget(); - webWidget->setParent(0); - - UBGraphicsWidgetItem* graphicsWidget = 0; - - UBW3CWidget* w3cWidget = qobject_cast(webWidget); - if (w3cWidget) - { - graphicsWidget = new UBGraphicsW3CWidgetItem(w3cWidget); - } - else - { - UBAppleWidget* appleWidget = qobject_cast(webWidget); - if (appleWidget) - { - graphicsWidget = new UBGraphicsAppleWidgetItem(appleWidget); - } - } - - QPoint controlViewCenter = mControlView->mapFrom(mMainWindow, mainWindowCenter); - QPointF scenePos = mControlView->mapToScene(controlViewCenter) + QPointF(xIsOdd * 0.5, yIsOdd * 0.5); - - mActiveScene->addGraphicsWidget(graphicsWidget, scenePos); - - toolWidget->hide(); - toolWidget->deleteLater(); -} - - -void UBBoardController::updateBackgroundActionsState(bool isDark, bool isCrossed) -{ - if (isDark && !isCrossed) - mMainWindow->actionPlainDarkBackground->setChecked(true); - else if (isDark && isCrossed) - mMainWindow->actionCrossedDarkBackground->setChecked(true); - else if (!isDark && isCrossed) - mMainWindow->actionCrossedLightBackground->setChecked(true); - else - mMainWindow->actionPlainLightBackground->setChecked(true); -} - - -void UBBoardController::addItem() -{ - QString defaultPath = UBSettings::settings()->lastImportToLibraryPath->get().toString(); - - QString extensions; - foreach(QString ext, UBSettings::imageFileExtensions) - { - extensions += " *."; - extensions += ext; - } - - QString filename = QFileDialog::getOpenFileName(mControlContainer, tr("Add Item"), - defaultPath, - tr("All Supported (%1)").arg(extensions)); - - if (filename.length() > 0) - { - mPaletteManager->addItem(QUrl::fromLocalFile(filename)); - QFileInfo source(filename); - UBSettings::settings()->lastImportToLibraryPath->set(QVariant(source.absolutePath())); - } -} - -void UBBoardController::importPage() -{ - int pageCount = mActiveDocument->pageCount(); - - if (UBApplication::documentController->addFileToDocument(mActiveDocument)) - { - setActiveDocumentScene(mActiveDocument, pageCount); - } -} - -void UBBoardController::notifyPageChanged() -{ - emit pageChanged(); -} - -void UBBoardController::onDownloadModalFinished() -{ - -} - -void UBBoardController::displayMetaData(QMap metadatas) -{ - emit displayMetadata(metadatas); -} +/* + * 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 "UBBoardController.h" + +#include +#include + +#include "frameworks/UBFileSystemUtils.h" +#include "frameworks/UBPlatformUtils.h" + +#include "core/UBApplication.h" +#include "core/UBSettings.h" +#include "core/UBSetting.h" +#include "core/UBPersistenceManager.h" +#include "core/UBApplicationController.h" +#include "core/UBDocumentManager.h" +#include "core/UBMimeData.h" +#include "core/UBDownloadManager.h" + +#include "network/UBHttpGet.h" + +#include "gui/UBMessageWindow.h" +#include "gui/UBResources.h" +#include "gui/UBToolbarButtonGroup.h" +#include "gui/UBMainWindow.h" +#include "gui/UBToolWidget.h" +#include "gui/UBKeyboardPalette.h" +#include "gui/UBMagnifer.h" + +#include "domain/UBGraphicsPixmapItem.h" +#include "domain/UBGraphicsItemUndoCommand.h" +#include "domain/UBGraphicsProxyWidget.h" +#include "domain/UBGraphicsSvgItem.h" +#include "domain/UBGraphicsWidgetItem.h" +#include "domain/UBGraphicsVideoItem.h" +#include "domain/UBGraphicsAudioItem.h" +#include "domain/UBGraphicsPDFItem.h" +#include "domain/UBW3CWidget.h" +#include "domain/UBGraphicsTextItem.h" +#include "domain/UBPageSizeUndoCommand.h" + +#include "tools/UBToolsManager.h" + +#include "document/UBDocumentProxy.h" +#include "document/UBDocumentController.h" + +#include "board/UBDrawingController.h" +#include "board/UBBoardView.h" + +#include "podcast/UBPodcastController.h" + +#include "adaptors/UBMetadataDcSubsetAdaptor.h" + +#include "UBBoardPaletteManager.h" + +#include "core/memcheck.h" +//#include + +UBBoardController::UBBoardController(UBMainWindow* mainWindow) + : QObject(mainWindow->centralWidget()) + , mMainWindow(mainWindow) + , mActiveDocument(0) + , mActiveScene(0) + , mActiveSceneIndex(-1) + , mPaletteManager(0) + , mSoftwareUpdateDialog(0) + , mMessageWindow(0) + , mControlView(0) + , mDisplayView(0) + , mControlContainer(0) + , mControlLayout(0) + , mZoomFactor(1.0) + , mIsClosing(false) + , mSystemScaleFactor(1.0) + , mCleanupDone(false) +{ + mZoomFactor = UBSettings::settings()->boardZoomFactor->get().toDouble(); + + int penColorIndex = UBSettings::settings()->penColorIndex(); + int markerColorIndex = UBSettings::settings()->markerColorIndex(); + + mPenColorOnDarkBackground = UBSettings::settings()->penColors(true).at(penColorIndex); + mPenColorOnLightBackground = UBSettings::settings()->penColors(false).at(penColorIndex); + mMarkerColorOnDarkBackground = UBSettings::settings()->markerColors(true).at(markerColorIndex); + mMarkerColorOnLightBackground = UBSettings::settings()->markerColors(false).at(markerColorIndex); +} + + +void UBBoardController::init() +{ + setupViews(); + setupToolbar(); + + connect(UBPersistenceManager::persistenceManager(), SIGNAL(documentWillBeDeleted(UBDocumentProxy*)) + , this, SLOT(documentWillBeDeleted(UBDocumentProxy*))); + + connect(UBPersistenceManager::persistenceManager(), SIGNAL(documentSceneCreated(UBDocumentProxy*, int)) + , this, SLOT(documentSceneChanged(UBDocumentProxy*, int))); + + connect(UBPersistenceManager::persistenceManager(), SIGNAL(documentSceneDeleted(UBDocumentProxy*, int)) + , this, SLOT(documentSceneChanged(UBDocumentProxy*, int))); + + connect(UBPersistenceManager::persistenceManager(), SIGNAL(documentSceneMoved(UBDocumentProxy*, int)) + , this, SLOT(documentSceneChanged(UBDocumentProxy*, int))); + + connect(UBApplication::undoStack, SIGNAL(canUndoChanged(bool)) + , this, SLOT(undoRedoStateChange(bool))); + + connect(UBApplication::undoStack, SIGNAL(canRedoChanged (bool)) + , this, SLOT(undoRedoStateChange(bool))); + + connect(UBDrawingController::drawingController(), SIGNAL(stylusToolChanged(int)) + , this, SLOT(setToolCursor(int))); + + connect(UBDrawingController::drawingController(), SIGNAL(stylusToolChanged(int)) + , this, SLOT(stylusToolChanged(int))); + + connect(UBApplication::app(), SIGNAL(lastWindowClosed()) + , this, SLOT(lastWindowClosed())); + + connect(UBDownloadManager::downloadManager(), SIGNAL(downloadModalFinished()), this, SLOT(onDownloadModalFinished())); + connect(UBDownloadManager::downloadManager(), SIGNAL(addDownloadedFileToBoard(bool,QUrl,QString,QByteArray,QPointF,QSize,bool)), this, SLOT(downloadFinished(bool,QUrl,QString,QByteArray,QPointF,QSize,bool))); + + UBDocumentProxy* doc = UBPersistenceManager::persistenceManager()->createDocument(); + + setActiveDocumentScene(doc); + + undoRedoStateChange(true); +} + + +UBBoardController::~UBBoardController() +{ + delete mDisplayView; +} + + +void UBBoardController::setupViews() +{ + mControlContainer = new QWidget(mMainWindow->centralWidget()); + + mControlLayout = new QHBoxLayout(mControlContainer); + mControlLayout->setContentsMargins(0, 0, 0, 0); + + mControlView = new UBBoardView(this, mControlContainer); + mControlView->setInteractive(true); + mControlView->setMouseTracking(true); + + mControlView->grabGesture(Qt::SwipeGesture); + + mControlView->setTransformationAnchor(QGraphicsView::NoAnchor); + + mControlLayout->addWidget(mControlView); + mControlContainer->setObjectName("ubBoardControlContainer"); + mMainWindow->addBoardWidget(mControlContainer); + + connect(mControlView, SIGNAL(resized(QResizeEvent*)), this, SLOT(boardViewResized(QResizeEvent*))); + + // TODO UB 4.x Optimization do we have to create the display view even if their is + // only 1 screen + // + mDisplayView = new UBBoardView(this, UBItemLayerType::FixedBackground, UBItemLayerType::Tool, 0); + mDisplayView->setInteractive(false); + mDisplayView->setTransformationAnchor(QGraphicsView::NoAnchor); + + mMessageWindow = new UBMessageWindow(mControlView); + mMessageWindow->hide(); + + mPaletteManager = new UBBoardPaletteManager(mControlContainer, this); + connect(this, SIGNAL(activeSceneChanged()), mPaletteManager, SLOT(activeSceneChanged())); + +} + + +void UBBoardController::setupLayout() +{ + if(mPaletteManager) + mPaletteManager->setupLayout(); +} + + +void UBBoardController::setBoxing(QRect displayRect) +{ + if (displayRect.isNull()) + { + mControlLayout->setContentsMargins(0, 0, 0, 0); + return; + } + + qreal controlWidth = (qreal)mMainWindow->centralWidget()->width(); + qreal controlHeight = (qreal)mMainWindow->centralWidget()->height(); + qreal displayWidth = (qreal)displayRect.width(); + qreal displayHeight = (qreal)displayRect.height(); + + qreal displayRatio = displayWidth / displayHeight; + qreal controlRatio = controlWidth / controlHeight; + + if (displayRatio < controlRatio) + { + // Pillarboxing + int boxWidth = (controlWidth - (displayWidth * (controlHeight / displayHeight))) / 2; + mControlLayout->setContentsMargins(boxWidth, 0, boxWidth, 0); + } + else if (displayRatio > controlRatio) + { + // Letterboxing + int boxHeight = (controlHeight - (displayHeight * (controlWidth / displayWidth))) / 2; + mControlLayout->setContentsMargins(0, boxHeight, 0, boxHeight); + } + else + { + // No boxing + mControlLayout->setContentsMargins(0, 0, 0, 0); + } +} + + +QSize UBBoardController::displayViewport() +{ + return mDisplayView->geometry().size(); +} + + +QSize UBBoardController::controlViewport() +{ + return mControlView->geometry().size(); +} + + +QRectF UBBoardController::controlGeometry() +{ + return mControlView->geometry(); +} + + +void UBBoardController::setupToolbar() +{ + UBSettings *settings = UBSettings::settings(); + + // Setup color choice widget + QList colorActions; + colorActions.append(mMainWindow->actionColor0); + colorActions.append(mMainWindow->actionColor1); + colorActions.append(mMainWindow->actionColor2); + colorActions.append(mMainWindow->actionColor3); + + UBToolbarButtonGroup *colorChoice = + new UBToolbarButtonGroup(mMainWindow->boardToolBar, colorActions); + + mMainWindow->boardToolBar->insertWidget(mMainWindow->actionBackgrounds, colorChoice); + + connect(settings->appToolBarDisplayText, SIGNAL(changed(QVariant)), colorChoice, SLOT(displayText(QVariant))); + connect(colorChoice, SIGNAL(activated(int)), this, SLOT(setColorIndex(int))); + connect(UBDrawingController::drawingController(), SIGNAL(colorIndexChanged(int)), colorChoice, SLOT(setCurrentIndex(int))); + connect(UBDrawingController::drawingController(), SIGNAL(colorPaletteChanged()), colorChoice, SLOT(colorPaletteChanged())); + connect(UBDrawingController::drawingController(), SIGNAL(colorPaletteChanged()), this, SLOT(colorPaletteChanged())); + + colorChoice->displayText(QVariant(settings->appToolBarDisplayText->get().toBool())); + colorChoice->colorPaletteChanged(); + + // Setup line width choice widget + QList lineWidthActions; + lineWidthActions.append(mMainWindow->actionLineSmall); + lineWidthActions.append(mMainWindow->actionLineMedium); + lineWidthActions.append(mMainWindow->actionLineLarge); + + UBToolbarButtonGroup *lineWidthChoice = + new UBToolbarButtonGroup(mMainWindow->boardToolBar, lineWidthActions); + + connect(settings->appToolBarDisplayText, SIGNAL(changed(QVariant)), lineWidthChoice, SLOT(displayText(QVariant))); + + connect(lineWidthChoice, SIGNAL(activated(int)) + , UBDrawingController::drawingController(), SLOT(setLineWidthIndex(int))); + + connect(UBDrawingController::drawingController(), SIGNAL(lineWidthIndexChanged(int)) + , lineWidthChoice, SLOT(setCurrentIndex(int))); + + lineWidthChoice->displayText(QVariant(settings->appToolBarDisplayText->get().toBool())); + + mMainWindow->boardToolBar->insertWidget(mMainWindow->actionBackgrounds, lineWidthChoice); + + //-----------------------------------------------------------// + // Setup eraser width choice widget + + QList eraserWidthActions; + eraserWidthActions.append(mMainWindow->actionEraserSmall); + eraserWidthActions.append(mMainWindow->actionEraserMedium); + eraserWidthActions.append(mMainWindow->actionEraserLarge); + + UBToolbarButtonGroup *eraserWidthChoice = + new UBToolbarButtonGroup(mMainWindow->boardToolBar, eraserWidthActions); + + mMainWindow->boardToolBar->insertWidget(mMainWindow->actionBackgrounds, eraserWidthChoice); + + connect(settings->appToolBarDisplayText, SIGNAL(changed(QVariant)), eraserWidthChoice, SLOT(displayText(QVariant))); + connect(eraserWidthChoice, SIGNAL(activated(int)), UBDrawingController::drawingController(), SLOT(setEraserWidthIndex(int))); + + eraserWidthChoice->displayText(QVariant(settings->appToolBarDisplayText->get().toBool())); + eraserWidthChoice->setCurrentIndex(settings->eraserWidthIndex()); + + mMainWindow->boardToolBar->insertSeparator(mMainWindow->actionBackgrounds); + + //-----------------------------------------------------------// + + UBApplication::app()->insertSpaceToToolbarBeforeAction(mMainWindow->boardToolBar, mMainWindow->actionBoard); + UBApplication::app()->insertSpaceToToolbarBeforeAction(mMainWindow->tutorialToolBar, mMainWindow->actionBoard); + + UBApplication::app()->decorateActionMenu(mMainWindow->actionMenu); + + mMainWindow->actionBoard->setVisible(false); + + mMainWindow->webToolBar->hide(); + mMainWindow->documentToolBar->hide(); + mMainWindow->tutorialToolBar->hide(); + + connectToolbar(); + initToolbarTexts(); +} + + +void UBBoardController::setToolCursor(int tool) +{ + if (mActiveScene) + { + mActiveScene->setToolCursor(tool); + } + + mControlView->setToolCursor(tool); +} + + +void UBBoardController::connectToolbar() +{ + connect(mMainWindow->actionAdd, SIGNAL(triggered()), this, SLOT(addItem())); + connect(mMainWindow->actionNewPage, SIGNAL(triggered()), this, SLOT(addScene())); + connect(mMainWindow->actionDuplicatePage, SIGNAL(triggered()), this, SLOT(duplicateScene())); + + connect(mMainWindow->actionClearPage, SIGNAL(triggered()), this, SLOT(clearScene())); + connect(mMainWindow->actionEraseItems, SIGNAL(triggered()), this, SLOT(clearSceneItems())); + connect(mMainWindow->actionEraseAnnotations, SIGNAL(triggered()), this, SLOT(clearSceneAnnotation())); + + //connect(mMainWindow->actionUndo, SIGNAL(triggered()), this, SLOT(stopScript())); + connect(mMainWindow->actionUndo, SIGNAL(triggered()), UBApplication::undoStack, SLOT(undo())); + connect(mMainWindow->actionRedo, SIGNAL(triggered()), UBApplication::undoStack, SLOT(redo())); + connect(mMainWindow->actionRedo, SIGNAL(triggered()), this, SLOT(startScript())); + connect(mMainWindow->actionBack, SIGNAL( triggered()), this, SLOT(previousScene())); + connect(mMainWindow->actionForward, SIGNAL(triggered()), this, SLOT(nextScene())); + connect(mMainWindow->actionSleep, SIGNAL(triggered()), this, SLOT(stopScript())); + connect(mMainWindow->actionSleep, SIGNAL(triggered()), this, SLOT(blackout())); + connect(mMainWindow->actionVirtualKeyboard, SIGNAL(triggered(bool)), this, SLOT(showKeyboard(bool))); + connect(mMainWindow->actionImportPage, SIGNAL(triggered()), this, SLOT(importPage())); +} + +void UBBoardController::startScript() +{ + freezeW3CWidgets(false); +} + +void UBBoardController::stopScript() +{ + freezeW3CWidgets(true); +} + +void UBBoardController::initToolbarTexts() +{ + QList allToolbarActions; + + allToolbarActions << mMainWindow->boardToolBar->actions(); + allToolbarActions << mMainWindow->webToolBar->actions(); + allToolbarActions << mMainWindow->documentToolBar->actions(); + + foreach(QAction* action, allToolbarActions) + { + QString nominalText = action->text(); + QString shortText = truncate(nominalText, 48); + QPair texts(nominalText, shortText); + + mActionTexts.insert(action, texts); + } +} + + +void UBBoardController::setToolbarTexts() +{ + bool highResolution = mMainWindow->width() > 1024; + QSize iconSize; + + if (highResolution) + iconSize = QSize(48, 32); + else + iconSize = QSize(32, 32); + + mMainWindow->boardToolBar->setIconSize(iconSize); + mMainWindow->webToolBar->setIconSize(iconSize); + mMainWindow->documentToolBar->setIconSize(iconSize); + + foreach(QAction* action, mActionTexts.keys()) + { + QPair texts = mActionTexts.value(action); + + if (highResolution) + action->setText(texts.first); + else + { + action->setText(texts.second); + } + + action->setToolTip(texts.first); + } +} + + +QString UBBoardController::truncate(QString text, int maxWidth) +{ + QFontMetricsF fontMetrics(mMainWindow->font()); + return fontMetrics.elidedText(text, Qt::ElideRight, maxWidth); +} + + +void UBBoardController::stylusToolDoubleClicked(int tool) +{ + if (tool == UBStylusTool::ZoomIn || tool == UBStylusTool::ZoomOut) + { + zoomRestore(); + } + else if (tool == UBStylusTool::Hand) + { + centerRestore(); + } +} + + + +void UBBoardController::addScene() +{ + QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + persistCurrentScene(); + + UBPersistenceManager::persistenceManager()->createDocumentSceneAt(mActiveDocument, mActiveSceneIndex + 1); + mActiveDocument->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); + + setActiveDocumentScene(mActiveDocument, mActiveSceneIndex + 1); + QApplication::restoreOverrideCursor(); +} + + +void UBBoardController::addScene(UBGraphicsScene* scene, bool replaceActiveIfEmpty) +{ + if (scene) + { + UBGraphicsScene* clone = scene->sceneDeepCopy(); + + if (scene->document() && (scene->document() != mActiveDocument)) + { + foreach(QUrl relativeFile, scene->relativeDependencies()) + { + QString source = scene->document()->persistencePath() + "/" + relativeFile.toString(); + QString target = mActiveDocument->persistencePath() + "/" + relativeFile.toString(); + + QFileInfo fi(target); + QDir d = fi.dir(); + + d.mkpath(d.absolutePath()); + QFile::copy(source, target); + } + } + + if (replaceActiveIfEmpty && mActiveScene->isEmpty()) + { + UBPersistenceManager::persistenceManager()->persistDocumentScene(mActiveDocument, clone, mActiveSceneIndex); + setActiveDocumentScene(mActiveDocument, mActiveSceneIndex); + } + else + { + persistCurrentScene(); + UBPersistenceManager::persistenceManager()->insertDocumentSceneAt(mActiveDocument, clone, mActiveSceneIndex + 1); + setActiveDocumentScene(mActiveDocument, mActiveSceneIndex + 1); + } + + mActiveDocument->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); + } +} + + +void UBBoardController::addScene(UBDocumentProxy* proxy, int sceneIndex, bool replaceActiveIfEmpty) +{ + UBGraphicsScene* scene = UBPersistenceManager::persistenceManager()->loadDocumentScene(proxy, sceneIndex); + + if (scene) + { + addScene(scene, replaceActiveIfEmpty); + } +} + + +void UBBoardController::duplicateScene() +{ + if (UBApplication::applicationController->displayMode() != UBApplicationController::Board) + return; + + QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + persistCurrentScene(); + + UBPersistenceManager::persistenceManager()->duplicateDocumentScene(mActiveDocument, mActiveSceneIndex); + mActiveDocument->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); + + setActiveDocumentScene(mActiveDocument, mActiveSceneIndex + 1); + QApplication::restoreOverrideCursor(); + + emit pageChanged(); +} + + +void UBBoardController::clearScene() +{ + if (mActiveScene) + { + freezeW3CWidgets(true); + mActiveScene->clearItemsAndAnnotations(); + updateActionStates(); + } +} + + +void UBBoardController::clearSceneItems() +{ + if (mActiveScene) + { + freezeW3CWidgets(true); + mActiveScene->clearItems(); + updateActionStates(); + } +} + + +void UBBoardController::clearSceneAnnotation() +{ + if (mActiveScene) + { + mActiveScene->clearAnnotations(); + updateActionStates(); + } +} + + +void UBBoardController::showDocumentsDialog() +{ + if (mActiveDocument) + persistCurrentScene(); + + UBApplication::mainWindow->actionLibrary->setChecked(false); + +} + +void UBBoardController::libraryDialogClosed(int ret) +{ + Q_UNUSED(ret); + + mMainWindow->actionLibrary->setChecked(false); +} + + +void UBBoardController::blackout() +{ + UBApplication::applicationController->blackout(); +} + + +void UBBoardController::showKeyboard(bool show) +{ + if(show) + UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); + mPaletteManager->showVirtualKeyboard(show); +} + + +void UBBoardController::zoomIn(QPointF scenePoint) +{ + if (mControlView->transform().m11() > UB_MAX_ZOOM) + { + qApp->beep(); + return; + } + zoom(mZoomFactor, scenePoint); +} + + +void UBBoardController::zoomOut(QPointF scenePoint) +{ + if ((mControlView->horizontalScrollBar()->maximum() == 0) && (mControlView->verticalScrollBar()->maximum() == 0)) + { + // Do not zoom out if we reached the maximum + qApp->beep(); + return; + } + + qreal newZoomFactor = 1 / mZoomFactor; + + zoom(newZoomFactor, scenePoint); +} + + +void UBBoardController::zoomRestore() +{ + QTransform tr; + + tr.scale(mSystemScaleFactor, mSystemScaleFactor); + mControlView->setTransform(tr); + + centerRestore(); + + foreach(QGraphicsItem *gi, mActiveScene->selectedItems ()) + { + //force item to redraw the frame (for the anti scale calculation) + gi->setSelected(false); + gi->setSelected(true); + } + + emit zoomChanged(1.0); +} + + +void UBBoardController::centerRestore() +{ + centerOn(QPointF(0,0)); +} + + +void UBBoardController::centerOn(QPointF scenePoint) +{ + mControlView->centerOn(scenePoint); + UBApplication::applicationController->adjustDisplayView(); +} + + +void UBBoardController::zoom(const qreal ratio, QPointF scenePoint) +{ + + QPointF viewCenter = mControlView->mapToScene(QRect(0, 0, mControlView->width(), mControlView->height()).center()); + QPointF offset = scenePoint - viewCenter; + QPointF scalledOffset = offset / ratio; + + mControlView->scale(ratio, ratio); + + qreal currentZoom = mControlView->viewportTransform().m11() / mSystemScaleFactor; + + QPointF newCenter = scenePoint - scalledOffset; + + mControlView->centerOn(newCenter); + + emit zoomChanged(currentZoom); + UBApplication::applicationController->adjustDisplayView(); + + emit controlViewportChanged(); +} + + +void UBBoardController::handScroll(qreal dx, qreal dy) +{ +// mControlView->horizontalScrollBar()->setValue(mControlView->horizontalScrollBar()->value() - dx); +// mControlView->verticalScrollBar()->setValue(mControlView->verticalScrollBar()->value() - dy); + mControlView->translate(dx, dy); + + UBApplication::applicationController->adjustDisplayView(); + + emit controlViewportChanged(); +} + + +void UBBoardController::previousScene() +{ + if (mActiveSceneIndex > 0) + { + QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + persistCurrentScene(); + setActiveDocumentScene(mActiveDocument, mActiveSceneIndex - 1); + QApplication::restoreOverrideCursor(); + } + + updateActionStates(); + emit pageChanged(); +} + + +void UBBoardController::nextScene() +{ + if (mActiveSceneIndex < mActiveDocument->pageCount() - 1) + { + QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + persistCurrentScene(); + setActiveDocumentScene(mActiveDocument, mActiveSceneIndex + 1); + QApplication::restoreOverrideCursor(); + } + + updateActionStates(); + emit pageChanged(); +} + + +void UBBoardController::firstScene() +{ + if (mActiveSceneIndex > 0) + { + QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + persistCurrentScene(); + setActiveDocumentScene(mActiveDocument, 0); + QApplication::restoreOverrideCursor(); + } + + updateActionStates(); + emit pageChanged(); +} + + +void UBBoardController::lastScene() +{ + if (mActiveSceneIndex < mActiveDocument->pageCount() - 1) + { + QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + persistCurrentScene(); + setActiveDocumentScene(mActiveDocument, mActiveDocument->pageCount() - 1); + QApplication::restoreOverrideCursor(); + } + + updateActionStates(); + emit pageChanged(); +} + + +void UBBoardController::downloadURL(const QUrl& url, const QPointF& pPos, const QSize& pSize, bool isBackground) +{ + qDebug() << "something has been dropped on the board! Url is: " << url.toString(); + QString sUrl = url.toString(); + + if(sUrl.startsWith("uniboardTool://")) + { + downloadFinished(true, url, "application/vnd.mnemis-uniboard-tool", QByteArray(), pPos, pSize, isBackground); + } + else if (sUrl.startsWith("file://") || sUrl.startsWith("/")) + { + QString fileName = url.toLocalFile(); + + QString contentType = UBFileSystemUtils::mimeTypeFromFileName(fileName); + + bool shouldLoadFileData = + contentType.startsWith("image") + || contentType.startsWith("application/widget") + || contentType.startsWith("application/vnd.apple-widget"); + + QFile file(fileName); + + if (shouldLoadFileData) + file.open(QIODevice::ReadOnly); + + downloadFinished(true, url, contentType, file.readAll(), pPos, pSize, isBackground); + + if (shouldLoadFileData) + file.close(); + } + else + { + // When we fall there, it means that we are dropping something from the web to the board + sDownloadFileDesc desc; + desc.modal = true; + desc.url = url.toString(); + desc.currentSize = 0; + desc.name = QFileInfo(url.toString()).fileName(); + desc.totalSize = 0; // The total size will be retrieved during the download + desc.pos = pPos; + desc.size = pSize; + desc.isBackground = isBackground; + + UBDownloadManager::downloadManager()->addFileToDownload(desc); + } +} + + +void UBBoardController::downloadFinished(bool pSuccess, QUrl sourceUrl, QString pContentTypeHeader, QByteArray pData, QPointF pPos, QSize pSize, bool isBackground) +{ + QString mimeType = pContentTypeHeader; + + // In some cases "image/jpeg;charset=" is retourned by the drag-n-drop. That is + // why we will check if an ; exists and take the first part (the standard allows this kind of mimetype) + int position=mimeType.indexOf(";"); + if(position != -1) + mimeType=mimeType.left(position); + + if (!pSuccess) + { + UBApplication::showMessage(tr("Downloading content %1 failed").arg(sourceUrl.toString())); + return; + } + + if (!sourceUrl.toString().startsWith("file://") && !sourceUrl.toString().startsWith("uniboardTool://")) + UBApplication::showMessage(tr("Download finished")); + + if (mimeType == "image/jpeg" + || mimeType == "image/png" + || mimeType == "image/gif" + || mimeType == "image/tiff" + || mimeType == "image/bmp") + { + + qDebug() << "accepting mime type" << mimeType << "as raster image"; + + QImage img; + img.loadFromData(pData); + QPixmap pix = QPixmap::fromImage(img); + + UBGraphicsPixmapItem* pixItem = mActiveScene->addPixmap(pix, pPos, 1.); + pixItem->setSourceUrl(sourceUrl); + + if (isBackground) + { + mActiveScene->setAsBackgroundObject(pixItem, true); + } + else + { + mActiveScene->scaleToFitDocumentSize(pixItem, true, UBSettings::objectInControlViewMargin); + pixItem->setSelected(true); + UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); + } + } + else if (mimeType == "image/svg+xml") + { + qDebug() << "accepting mime type" << mimeType << "as vecto image"; + + UBGraphicsSvgItem* svgItem = mActiveScene->addSvg(sourceUrl, pPos); + svgItem->setSourceUrl(sourceUrl); + + if (isBackground) + { + mActiveScene->setAsBackgroundObject(svgItem); + } + else + { + mActiveScene->scaleToFitDocumentSize(svgItem, true, UBSettings::objectInControlViewMargin); + svgItem->setSelected(true); + UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); + } + } + else if (mimeType == "application/vnd.apple-widget") //mime type invented by us :-( + { + qDebug() << "accepting mime type" << mimeType << "as Apple widget"; + + QUrl widgetUrl = sourceUrl; + + if (pData.length() > 0) + { + widgetUrl = expandWidgetToTempDir(pData, "wdgt"); + } + + UBGraphicsWidgetItem* appleWidgetItem = mActiveScene->addAppleWidget(widgetUrl, pPos); + + appleWidgetItem->setSourceUrl(sourceUrl); + + if (isBackground) + { + mActiveScene->setAsBackgroundObject(appleWidgetItem); + } + else + { + UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); + } + } + else if (mimeType == "application/widget") + { + qDebug() << "accepting mime type" << mimeType << "as W3C widget"; + QUrl widgetUrl = sourceUrl; + + if (pData.length() > 0) + { + widgetUrl = expandWidgetToTempDir(pData); + } + + UBGraphicsWidgetItem *w3cWidgetItem = addW3cWidget(widgetUrl, pPos); + + if (isBackground) + { + mActiveScene->setAsBackgroundObject(w3cWidgetItem); + } + else + { + UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); + } + } + else if (mimeType.startsWith("video/")) + { + qDebug() << "accepting mime type" << mimeType << "as video"; + + UBGraphicsVideoItem *videoItem = 0; + + if (pData.length() > 0) + { + QUuid uuid = QUuid::createUuid(); + + QUrl url = QUrl::fromLocalFile(UBPersistenceManager::persistenceManager() + ->addVideoFileToDocument(mActiveDocument, sourceUrl, pData, uuid)); + + videoItem = mActiveScene->addVideo(url, false, pPos); + + videoItem->setSourceUrl(sourceUrl); + videoItem->setUuid(uuid); + } + else + { + videoItem = addVideo(sourceUrl, false, pPos); + } + + if(videoItem){ + connect(this, SIGNAL(activeSceneChanged()), videoItem, SLOT(activeSceneChanged())); + } + + UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); + } + else if (mimeType.startsWith("audio/")) + { + qDebug() << "accepting mime type" << mimeType << "as audio"; + + UBGraphicsAudioItem *audioItem = 0; + + if (pData.length() > 0) + { + QUuid uuid = QUuid::createUuid(); + + QUrl url = QUrl::fromLocalFile(UBPersistenceManager::persistenceManager() + ->addAudioFileToDocument(mActiveDocument, sourceUrl, pData, uuid)); + + audioItem = mActiveScene->addAudio(url, false, pPos); + + audioItem->setSourceUrl(sourceUrl); + audioItem->setUuid(uuid); + } + else + { + audioItem = addAudio(sourceUrl, false, pPos); + } + + if(audioItem){ + connect(this, SIGNAL(activeSceneChanged()), audioItem, SLOT(activeSceneChanged())); + } + + UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); + } + + else if (mimeType.startsWith("application/x-shockwave-flash")) + { + + qDebug() << "accepting mime type" << mimeType << "as flash"; + + QString sUrl = sourceUrl.toString(); + + if (sUrl.startsWith("file://") || sUrl.startsWith("/")) + { + sUrl = sourceUrl.toLocalFile(); + } + + QTemporaryFile* eduMediaFile = 0; + + if (sUrl.toLower().contains("edumedia-sciences.com")) + { + eduMediaFile = new QTemporaryFile("XXXXXX.swf"); + if (eduMediaFile->open()) + { + eduMediaFile->write(pData); + QFileInfo fi(*eduMediaFile); + sUrl = fi.absoluteFilePath(); + } + } + + QSize size; + + if (pSize.height() > 0 && pSize.width() > 0) + size = pSize; + else + size = mActiveScene->nominalSize() * .8; + + QString widgetUrl = UBW3CWidget::createNPAPIWrapper(sUrl, mimeType, size); + + if (widgetUrl.length() > 0) + { + UBGraphicsWidgetItem *widgetItem = mActiveScene->addW3CWidget(QUrl::fromLocalFile(widgetUrl), pPos); + + widgetItem->setSourceUrl(sourceUrl); + + UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); + } + + if (eduMediaFile) + delete eduMediaFile; + + } + else if (mimeType.startsWith("application/pdf")) + { + qDebug() << "accepting mime type" << mimeType << "as PDF"; + qDebug() << "pdf data length: " << pData.size(); + qDebug() << "sourceurl : " + sourceUrl.toString(); + int result = 0; + if(!sourceUrl.isEmpty()){ + QFile sourceFile(sourceUrl.toLocalFile()); + result = UBDocumentManager::documentManager()->addFileToDocument(mActiveDocument, sourceFile); + } + else if(pData.size()){ + QTemporaryFile pdfFile("XXXXXX.pdf"); + if (pdfFile.open()) + { + pdfFile.write(pData); + result = UBDocumentManager::documentManager()->addFileToDocument(mActiveDocument, pdfFile); + pdfFile.close(); + } + } + + if (result){ + mActiveDocument->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); + } + } + else if (mimeType.startsWith("application/vnd.mnemis-uniboard-tool")) + { + qDebug() << "accepting mime type" << mimeType << "as Uniboard Tool"; + + if (sourceUrl.toString() == UBToolsManager::manager()->compass.id) + { + mActiveScene->addCompass(pPos); + UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); + } + else if (sourceUrl.toString() == UBToolsManager::manager()->ruler.id) + { + mActiveScene->addRuler(pPos); + UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); + } + else if (sourceUrl.toString() == UBToolsManager::manager()->protractor.id) + { + mActiveScene->addProtractor(pPos); + UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); + } + else if (sourceUrl.toString() == UBToolsManager::manager()->triangle.id) + { + mActiveScene->addTriangle(pPos); + UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); + } + else if (sourceUrl.toString() == UBToolsManager::manager()->cache.id) + { + mActiveScene->addCache(); + UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); + } + else if (sourceUrl.toString() == UBToolsManager::manager()->magnifier.id) + { + UBMagnifierParams params; + params.x = controlContainer()->geometry().width() / 2; + params.y = controlContainer()->geometry().height() / 2; + params.zoom = 2; + params.sizePercentFromScene = 20; + mActiveScene->addMagnifier(params); + UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); + } + else if (sourceUrl.toString() == UBToolsManager::manager()->mask.id) + { + mActiveScene->addMask(pPos); + UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); + } + else + { + UBApplication::showMessage(tr("Unknown tool type %1").arg(sourceUrl.toString())); + } + } + else if (sourceUrl.toString().contains("edumedia-sciences.com")) + { + qDebug() << "accepting url " << sourceUrl.toString() << "as eduMedia content"; + + QTemporaryFile eduMediaZipFile("XXXXXX.edumedia"); + if (eduMediaZipFile.open()) + { + eduMediaZipFile.write(pData); + eduMediaZipFile.close(); + + QString tempDir = UBFileSystemUtils::createTempDir("uniboard-edumedia"); + + UBFileSystemUtils::expandZipToDir(eduMediaZipFile, tempDir); + + QDir appDir(tempDir); + + foreach(QString subDirName, appDir.entryList(QDir::AllDirs)) + { + QDir subDir(tempDir + "/" + subDirName + "/contents"); + + foreach(QString fileName, subDir.entryList(QDir::Files)) + { + if (fileName.toLower().endsWith(".swf")) + { + QString swfFile = tempDir + "/" + subDirName + "/contents/" + fileName; + + QSize size; + + if (pSize.height() > 0 && pSize.width() > 0) + size = pSize; + else + size = mActiveScene->nominalSize() * .8; + + QString widgetUrl = UBW3CWidget::createNPAPIWrapper(swfFile, "application/x-shockwave-flash", size); + + if (widgetUrl.length() > 0) + { + UBGraphicsWidgetItem *widgetItem = mActiveScene->addW3CWidget(QUrl::fromLocalFile(widgetUrl), pPos); + + widgetItem->setSourceUrl(sourceUrl); + + UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); + } + } + } + } + } + } + else + { + UBApplication::showMessage(tr("Unknown content type %1").arg(pContentTypeHeader)); + qWarning() << "ignoring mime type" << pContentTypeHeader ; + } +} + + +void UBBoardController::setActiveDocumentScene(UBDocumentProxy* pDocumentProxy, const int pSceneIndex) +{ + saveViewState(); + + bool documentChange = mActiveDocument != pDocumentProxy; + + int index = pSceneIndex; + int sceneCount = pDocumentProxy->pageCount(); + if (index >= sceneCount && sceneCount > 0) + index = sceneCount - 1; + + UBGraphicsScene* targetScene = UBPersistenceManager::persistenceManager()->loadDocumentScene(pDocumentProxy, index); + + bool sceneChange = targetScene != mActiveScene; + + if (targetScene) + { + freezeW3CWidgets(true); + + if(sceneChange) + emit activeSceneWillChange(); + + ClearUndoStack(); + + mActiveScene = targetScene; + mActiveDocument = pDocumentProxy; + mActiveSceneIndex = index; + + updateSystemScaleFactor(); + + mControlView->setScene(mActiveScene); + mDisplayView->setScene(mActiveScene); + + pDocumentProxy->setDefaultDocumentSize(mActiveScene->nominalSize()); + updatePageSizeState(); + + adjustDisplayViews(); + + UBSettings::settings()->setDarkBackground(mActiveScene->isDarkBackground()); + UBSettings::settings()->setCrossedBackground(mActiveScene->isCrossedBackground()); + + freezeW3CWidgets(false); + } + + selectionChanged(); + + updateBackgroundActionsState(mActiveScene->isDarkBackground(), mActiveScene->isCrossedBackground()); + updateBackgroundState(); + + if(documentChange) + { + emit activeDocumentChanged(); + UBGraphicsTextItem::lastUsedTextColor = QColor(); + } + + // Notify the navigator palette that the document has changed + emit setDocOnPageNavigator(pDocumentProxy); + + if (sceneChange) + { + emit activeSceneChanged(); + emit pageChanged(); + } +} + +void UBBoardController::ClearUndoStack() +{ + QSet uniqueItems; + // go through all stack command + for(int i = 0; i < UBApplication::undoStack->count(); i++) + { + + UBAbstractUndoCommand *abstractCmd = (UBAbstractUndoCommand*)UBApplication::undoStack->command(i); + if(abstractCmd->getType() != UBAbstractUndoCommand::undotype_GRAPHICITEM) + continue; + + UBGraphicsItemUndoCommand *cmd = (UBGraphicsItemUndoCommand*)UBApplication::undoStack->command(i); + + // go through all added and removed objects, for create list of unique objects + QSetIterator itAdded(cmd->GetAddedList()); + while (itAdded.hasNext()) + { + QGraphicsItem* item = itAdded.next(); + if( !uniqueItems.contains(item) ) + uniqueItems.insert(item); + } + + QSetIterator itRemoved(cmd->GetRemovedList()); + while (itRemoved.hasNext()) + { + QGraphicsItem* item = itRemoved.next(); + if( !uniqueItems.contains(item) ) + uniqueItems.insert(item); + } + } + + // clear stack, and command list + UBApplication::undoStack->clear(); + + // go through all unique items, and check, ot on scene, or not. + // if not on scene, than item can be deleted + + QSetIterator itUniq(uniqueItems); + while (itUniq.hasNext()) + { + QGraphicsItem* item = itUniq.next(); + UBGraphicsScene *scene = dynamic_cast(item->scene()); + if(!scene) + { + mActiveScene->deleteItem(item); + } + } + +} + +void UBBoardController::adjustDisplayViews() +{ + if (UBApplication::applicationController) + { + UBApplication::applicationController->adjustDisplayView(); + UBApplication::applicationController->adjustPreviousViews(mActiveSceneIndex, mActiveDocument); + } +} + + +void UBBoardController::changeBackground(bool isDark, bool isCrossed) +{ + bool currentIsDark = mActiveScene->isDarkBackground(); + bool currentIsCrossed = mActiveScene->isCrossedBackground(); + + if ((isDark != currentIsDark) || (currentIsCrossed != isCrossed)) + { + UBSettings::settings()->setDarkBackground(isDark); + UBSettings::settings()->setCrossedBackground(isCrossed); + + mActiveScene->setBackground(isDark, isCrossed); + + updateBackgroundState(); + + emit backgroundChanged(); + } +} + + +void UBBoardController::boardViewResized(QResizeEvent* event) +{ + Q_UNUSED(event); + + int innerMargin = UBSettings::boardMargin; + int userHeight = mControlContainer->height() - (2 * innerMargin); + + mMessageWindow->move(innerMargin, innerMargin + userHeight - mMessageWindow->height()); + mMessageWindow->adjustSizeAndPosition(); + + UBApplication::applicationController->initViewState( + mControlView->horizontalScrollBar()->value(), + mControlView->verticalScrollBar()->value()); + + updateSystemScaleFactor(); + + mControlView->centerOn(0,0); + + mPaletteManager->containerResized(); + + +} + + +void UBBoardController::documentWillBeDeleted(UBDocumentProxy* pProxy) +{ + if (mActiveDocument == pProxy) + { + if (!mIsClosing) + setActiveDocumentScene(UBPersistenceManager::persistenceManager()->createDocument()); + } +} + + +void UBBoardController::showMessage(const QString& message, bool showSpinningWheel) +{ + mMessageWindow->showMessage(message, showSpinningWheel); +} + + +void UBBoardController::hideMessage() +{ + mMessageWindow->hideMessage(); +} + + +void UBBoardController::setDisabled(bool disable) +{ + mMainWindow->boardToolBar->setDisabled(disable); + mControlView->setDisabled(disable); +} + + +void UBBoardController::selectionChanged() +{ + updateActionStates(); +} + + +void UBBoardController::undoRedoStateChange(bool canUndo) +{ + Q_UNUSED(canUndo); + + mMainWindow->actionUndo->setEnabled(UBApplication::undoStack->canUndo()); + mMainWindow->actionRedo->setEnabled(UBApplication::undoStack->canRedo()); + + updateActionStates(); +} + + +void UBBoardController::updateActionStates() +{ + mMainWindow->actionBack->setEnabled(mActiveDocument && (mActiveSceneIndex > 0)); + mMainWindow->actionForward->setEnabled(mActiveDocument && (mActiveSceneIndex < mActiveDocument->pageCount() - 1)); + mMainWindow->actionErase->setEnabled(mActiveScene && !mActiveScene->isEmpty()); +} + + +UBDocumentProxy* UBBoardController::activeDocument() const +{ + return mActiveDocument; +} + + +UBGraphicsScene* UBBoardController::activeScene() const +{ + return mActiveScene; +} + + +int UBBoardController::activeSceneIndex() const +{ + return mActiveSceneIndex; +} + + +void UBBoardController::documentSceneChanged(UBDocumentProxy* pDocumentProxy, int pIndex) +{ + Q_UNUSED(pIndex); + + if(mActiveDocument == pDocumentProxy) + { + setActiveDocumentScene(mActiveDocument, mActiveSceneIndex); + } +} + +void UBBoardController::closing() +{ + mIsClosing = true; + ClearUndoStack(); + lastWindowClosed(); +} + +void UBBoardController::lastWindowClosed() +{ + if (!mCleanupDone) + { + if (mActiveDocument->pageCount() == 1 && (!mActiveScene || mActiveScene->isEmpty())) + { + UBPersistenceManager::persistenceManager()->deleteDocument(mActiveDocument); + } + else + { + persistCurrentScene(); + } + + UBPersistenceManager::persistenceManager()->purgeEmptyDocuments(); + + mCleanupDone = true; + } +} + + + +void UBBoardController::setColorIndex(int pColorIndex) +{ + UBDrawingController::drawingController()->setColorIndex(pColorIndex); + + if (UBDrawingController::drawingController()->stylusTool() != UBStylusTool::Marker && + UBDrawingController::drawingController()->stylusTool() != UBStylusTool::Line && + UBDrawingController::drawingController()->stylusTool() != UBStylusTool::Text && + UBDrawingController::drawingController()->stylusTool() != UBStylusTool::Selector) + { + UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Pen); + } + + if (UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Pen || + UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Line || + UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Text || + UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Selector) + { + mPenColorOnDarkBackground = UBSettings::settings()->penColors(true).at(pColorIndex); + mPenColorOnLightBackground = UBSettings::settings()->penColors(false).at(pColorIndex); + + if (UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Selector) + { + // If we are in mode board, then do that + if(UBApplication::applicationController->displayMode() == UBApplicationController::Board) + { + UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Pen); + mMainWindow->actionPen->setChecked(true); + } + } + + emit penColorChanged(); + } + else if (UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Marker) + { + mMarkerColorOnDarkBackground = UBSettings::settings()->markerColors(true).at(pColorIndex); + mMarkerColorOnLightBackground = UBSettings::settings()->markerColors(false).at(pColorIndex); + } +} + +void UBBoardController::colorPaletteChanged() +{ + mPenColorOnDarkBackground = UBSettings::settings()->penColor(true); + mPenColorOnLightBackground = UBSettings::settings()->penColor(false); + mMarkerColorOnDarkBackground = UBSettings::settings()->markerColor(true); + mMarkerColorOnLightBackground = UBSettings::settings()->markerColor(false); +} + + +qreal UBBoardController::currentZoom() +{ + if (mControlView) + return mControlView->viewportTransform().m11() / mSystemScaleFactor; + else + return 1.0; +} + + +UBToolWidget* UBBoardController::addTool(const QUrl& toolUrl) +{ + return addTool(toolUrl, mControlView->mapToScene(mControlView->rect().center())); +} + + +UBToolWidget* UBBoardController::addTool(const QUrl& toolUrl, QPointF scenePos) +{ + UBToolWidget *toolWidget = new UBToolWidget(toolUrl, mMainWindow); // Deleted in UBBoardController::removeTool + QPoint pos = mControlView->mapToGlobal(mControlView->mapFromScene(scenePos)); + pos -= QPoint(toolWidget->width() / 2, toolWidget->height() / 2); + + toolWidget->move(pos); + + mTools.append(toolWidget); + + toolWidget->show(); + + return toolWidget; +} + + +void UBBoardController::removeTool(UBToolWidget* toolWidget) +{ + toolWidget->hide(); + + mTools.removeAll(toolWidget); + + delete toolWidget; +} + + +void UBBoardController::hide() +{ + UBApplication::mainWindow->actionLibrary->setChecked(false); + + controlViewHidden(); +} + + +void UBBoardController::show() +{ + UBApplication::mainWindow->actionLibrary->setChecked(false); + + controlViewShown(); +} + + +void UBBoardController::persistCurrentScene() +{ + if(UBPersistenceManager::persistenceManager() + && mActiveDocument && mActiveScene + && (mActiveSceneIndex >= 0)) + { + emit activeSceneWillBePersisted(); + + UBPersistenceManager::persistenceManager()->persistDocumentScene(mActiveDocument, mActiveScene, mActiveSceneIndex); + UBMetadataDcSubsetAdaptor::persist(mActiveDocument); + } +} + + +void UBBoardController::updateSystemScaleFactor() +{ + qreal newScaleFactor = 1.0; + + if (mActiveScene) + { + QSize pageNominalSize = mActiveScene->nominalSize(); + //we're going to keep scale factor untouched if the size is custom + QMap sizesMap = UBSettings::settings()->documentSizes; + if(pageNominalSize == sizesMap.value(DocumentSizeRatio::Ratio16_9) || pageNominalSize == sizesMap.value(DocumentSizeRatio::Ratio4_3)) + { + QSize controlSize = controlViewport(); + + qreal hFactor = ((qreal)controlSize.width()) / ((qreal)pageNominalSize.width()); + qreal vFactor = ((qreal)controlSize.height()) / ((qreal)pageNominalSize.height()); + + newScaleFactor = qMin(hFactor, vFactor); + } + } + + if (mSystemScaleFactor != newScaleFactor) + { + mSystemScaleFactor = newScaleFactor; + emit systemScaleFactorChanged(newScaleFactor); + } + + UBGraphicsScene::SceneViewState viewState = mActiveScene->viewState(); + + QTransform scalingTransform; + + qreal scaleFactor = viewState.zoomFactor * mSystemScaleFactor; + scalingTransform.scale(scaleFactor, scaleFactor); + + mControlView->setTransform(scalingTransform); + mControlView->horizontalScrollBar()->setValue(viewState.horizontalPosition); + mControlView->verticalScrollBar()->setValue(viewState.verticalPostition); +} + + +void UBBoardController::setWidePageSize(bool checked) +{ + Q_UNUSED(checked); + QSize newSize = UBSettings::settings()->documentSizes.value(DocumentSizeRatio::Ratio16_9); + + if (mActiveScene->nominalSize() != newSize) + { + UBPageSizeUndoCommand* uc = new UBPageSizeUndoCommand(mActiveScene, mActiveScene->nominalSize(), newSize); + UBApplication::undoStack->push(uc); + + setPageSize(newSize); + } +} + + +void UBBoardController::setRegularPageSize(bool checked) +{ + Q_UNUSED(checked); + QSize newSize = UBSettings::settings()->documentSizes.value(DocumentSizeRatio::Ratio4_3); + + if (mActiveScene->nominalSize() != newSize) + { + UBPageSizeUndoCommand* uc = new UBPageSizeUndoCommand(mActiveScene, mActiveScene->nominalSize(), newSize); + UBApplication::undoStack->push(uc); + + setPageSize(newSize); + } +} + + +void UBBoardController::setPageSize(QSize newSize) +{ + if (mActiveScene->nominalSize() != newSize) + { + mActiveScene->setNominalSize(newSize); + + saveViewState(); + + updateSystemScaleFactor(); + updatePageSizeState(); + adjustDisplayViews(); + mActiveDocument->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); + + UBSettings::settings()->pageSize->set(newSize); + } +} + +void UBBoardController::notifyCache(bool visible) +{ + if(visible) + { + emit cacheEnabled(); + } + else + { + emit cacheDisabled(); + } +} + +void UBBoardController::updatePageSizeState() +{ + if (mActiveScene->nominalSize() == UBSettings::settings()->documentSizes.value(DocumentSizeRatio::Ratio16_9)) + { + mMainWindow->actionWidePageSize->setChecked(true); + } + else if(mActiveScene->nominalSize() == UBSettings::settings()->documentSizes.value(DocumentSizeRatio::Ratio4_3)) + { + mMainWindow->actionRegularPageSize->setChecked(true); + } + else + { + mMainWindow->actionCustomPageSize->setChecked(true); + } +} + + +void UBBoardController::saveViewState() +{ + if (mActiveScene) + { + mActiveScene->setViewState(UBGraphicsScene::SceneViewState(currentZoom(), + mControlView->horizontalScrollBar()->value(), + mControlView->verticalScrollBar()->value())); + } +} + + +void UBBoardController::updateBackgroundState() +{ + //adjust background style + QString newBackgroundStyle; + + if (mActiveScene && mActiveScene->isDarkBackground()) + { + newBackgroundStyle ="QWidget {background-color: #0E0E0E}"; + } + else + { + newBackgroundStyle ="QWidget {background-color: #F1F1F1}"; + } +} + +void UBBoardController::stylusToolChanged(int tool) +{ + if (UBPlatformUtils::hasVirtualKeyboard() && mPaletteManager->mKeyboardPalette) + { + UBStylusTool::Enum eTool = (UBStylusTool::Enum)tool; + if(eTool != UBStylusTool::Selector && eTool != UBStylusTool::Text) + { + if(mPaletteManager->mKeyboardPalette->m_isVisible) + UBApplication::mainWindow->actionVirtualKeyboard->activate(QAction::Trigger); + } + } + + updateBackgroundState(); +} + + +QUrl UBBoardController::expandWidgetToTempDir(const QByteArray& pZipedData, const QString& ext) +{ + QUrl widgetUrl; + QTemporaryFile tmp; + + if (tmp.open()) + { + tmp.write(pZipedData); + tmp.flush(); + tmp.close(); + + QString tmpDir = UBFileSystemUtils::createTempDir() + "." + ext; + + if (UBFileSystemUtils::expandZipToDir(tmp, tmpDir)) + { + widgetUrl = QUrl::fromLocalFile(tmpDir); + } + } + + return widgetUrl; +} + + +void UBBoardController::grabScene(const QRectF& pSceneRect) +{ + if (mActiveScene) + { + QImage image(pSceneRect.width(), pSceneRect.height(), QImage::Format_ARGB32); + image.fill(Qt::transparent); + + QRectF targetRect(0, 0, pSceneRect.width(), pSceneRect.height()); + QPainter painter(&image); + painter.setRenderHint(QPainter::SmoothPixmapTransform); + painter.setRenderHint(QPainter::Antialiasing); + + mActiveScene->setRenderingContext(UBGraphicsScene::NonScreen); + mActiveScene->setRenderingQuality(UBItem::RenderingQualityHigh); + + mActiveScene->render(&painter, targetRect, pSceneRect); + + mActiveScene->setRenderingContext(UBGraphicsScene::Screen); + mActiveScene->setRenderingQuality(UBItem::RenderingQualityNormal); + + mPaletteManager->addItem(QPixmap::fromImage(image)); + mActiveDocument->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); + } +} + + +void UBBoardController::controlViewHidden() +{ + foreach(UBToolWidget* tool, mTools) + { + tool->hide(); + } +} + + +void UBBoardController::controlViewShown() +{ + foreach(UBToolWidget* tool, mTools) + { + tool->show(); + } +} + + +UBGraphicsVideoItem* UBBoardController::addVideo(const QUrl& pSourceUrl, bool startPlay, const QPointF& pos) +{ + QUuid uuid = QUuid::createUuid(); + QUrl concreteUrl = pSourceUrl; + +#ifdef Q_WS_X11 + concreteUrl = QUrl::fromLocalFile(mActiveDocument->persistencePath() + "/" + UBPersistenceManager::persistenceManager() + ->addVideoFileToDocument(mActiveDocument, pSourceUrl.toLocalFile(), uuid)); +#else + concreteUrl = QUrl::fromLocalFile(UBPersistenceManager::persistenceManager() + ->addVideoFileToDocument(mActiveDocument, pSourceUrl.toLocalFile(), uuid)); +#endif + + UBGraphicsVideoItem* vi = mActiveScene->addVideo(concreteUrl, startPlay, pos); + mActiveDocument->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); + + if (vi) { + vi->setUuid(uuid); + vi->setSourceUrl(pSourceUrl); + } + + return vi; + +} + +UBGraphicsAudioItem* UBBoardController::addAudio(const QUrl& pSourceUrl, bool startPlay, const QPointF& pos) +{ + QUuid uuid = QUuid::createUuid(); + QUrl concreteUrl = pSourceUrl; + +#ifdef Q_WS_X11 + concreteUrl = QUrl::fromLocalFile(mActiveDocument->persistencePath() + "/" + UBPersistenceManager::persistenceManager() + ->addAudioFileToDocument(mActiveDocument, pSourceUrl.toLocalFile(), uuid)); +#else + concreteUrl = QUrl::fromLocalFile(UBPersistenceManager::persistenceManager() + ->addAudioFileToDocument(mActiveDocument, pSourceUrl.toLocalFile(), uuid)); +#endif + + UBGraphicsAudioItem* vi = mActiveScene->addAudio(concreteUrl, startPlay, pos); + mActiveDocument->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); + + if (vi){ + vi->setUuid(uuid); + vi->setSourceUrl(pSourceUrl); + } + + return vi; + +} + +UBGraphicsWidgetItem *UBBoardController::addW3cWidget(const QUrl &pUrl, const QPointF &pos) +{ + UBGraphicsWidgetItem* w3cWidgetItem = 0; + + QUuid uuid = QUuid::createUuid(); + QUrl newUrl = pUrl; + + newUrl = QUrl::fromLocalFile(UBPersistenceManager::persistenceManager()->addGraphicsWidgteToDocument(mActiveDocument, pUrl.toLocalFile(), uuid)); + + w3cWidgetItem = mActiveScene->addW3CWidget(pUrl, pos); + + if (w3cWidgetItem) { + w3cWidgetItem->setUuid(uuid); + w3cWidgetItem->setOwnFolder(newUrl); + w3cWidgetItem->setSourceUrl(pUrl); + + QString struuid = UBStringUtils::toCanonicalUuid(uuid); + QString snapshotPath = mActiveDocument->persistencePath() + "/" + UBPersistenceManager::widgetDirectory + "/" + struuid + ".png"; + w3cWidgetItem->setSnapshotPath(QUrl::fromLocalFile(snapshotPath)); + UBGraphicsWidgetItem *tmpItem = dynamic_cast(w3cWidgetItem); + if (tmpItem) + tmpItem->widgetWebView()->takeSnapshot().save(snapshotPath, "PNG"); + + } + + return 0; +} + +void UBBoardController::cut() +{ + //---------------------------------------------------------// + + QList selectedItems; + foreach(QGraphicsItem* gi, mActiveScene->selectedItems()) + selectedItems << gi; + + //---------------------------------------------------------// + + QList selected; + foreach(QGraphicsItem* gi, selectedItems) + { + gi->setSelected(false); + + UBItem* ubItem = dynamic_cast(gi); + UBGraphicsItem *ubGi = dynamic_cast(gi); + + if (ubItem && ubGi && !mActiveScene->tools().contains(gi)) + { + selected << ubItem->deepCopy(); + ubGi->remove(); + } + } + + //---------------------------------------------------------// + + if (selected.size() > 0) + { + QClipboard *clipboard = QApplication::clipboard(); + + UBMimeDataGraphicsItem* mimeGi = new UBMimeDataGraphicsItem(selected); + + mimeGi->setData(UBApplication::mimeTypeUniboardPageItem, QByteArray()); + clipboard->setMimeData(mimeGi); + + mActiveDocument->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); + } + + //---------------------------------------------------------// +} + + +void UBBoardController::copy() +{ + QList selected; + + foreach(QGraphicsItem* gi, mActiveScene->selectedItems()) + { + UBItem* ubItem = dynamic_cast(gi); + + if (ubItem && !mActiveScene->tools().contains(gi)) + selected << ubItem->deepCopy(); + } + + if (selected.size() > 0) + { + QClipboard *clipboard = QApplication::clipboard(); + + UBMimeDataGraphicsItem* mimeGi = new UBMimeDataGraphicsItem(selected); + + mimeGi->setData(UBApplication::mimeTypeUniboardPageItem, QByteArray()); + clipboard->setMimeData(mimeGi); + + } +} + + +void UBBoardController::paste() +{ + QClipboard *clipboard = QApplication::clipboard(); + QPointF pos(0, 0); + processMimeData(clipboard->mimeData(), pos); + + mActiveDocument->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); +} + + +void UBBoardController::processMimeData(const QMimeData* pMimeData, const QPointF& pPos) +{ + if (pMimeData->hasFormat(UBApplication::mimeTypeUniboardPage)) + { + const UBMimeData* mimeData = qobject_cast (pMimeData); + + if (mimeData) + { + int previousActiveSceneIndex = activeSceneIndex(); + int previousPageCount = activeDocument()->pageCount(); + + foreach (UBMimeDataItem sourceItem, mimeData->items()) + addScene(sourceItem.documentProxy(), sourceItem.sceneIndex(), true); + + if (activeDocument()->pageCount() < previousPageCount + mimeData->items().count()) + setActiveDocumentScene(activeDocument(), previousActiveSceneIndex); + else + setActiveDocumentScene(activeDocument(), previousActiveSceneIndex + 1); + + return; + } + } + + if (pMimeData->hasFormat(UBApplication::mimeTypeUniboardPageItem)) + { + const UBMimeDataGraphicsItem* mimeData = qobject_cast (pMimeData); + + if (mimeData) + { + foreach(UBItem* item, mimeData->items()) + { + QGraphicsItem* gi = dynamic_cast(item->deepCopy()); + + if (gi) + { +// gi->setZValue(mActiveScene->getNextObjectZIndex()); + UBGraphicsItem::assignZValue(gi, mActiveScene->getNextObjectZIndex()); + mActiveScene->addItem(gi); + gi->setPos(gi->pos() + QPointF(50, 50)); + } + } + + return; + } + } + + if(pMimeData->hasHtml()) + { + QString qsHtml = pMimeData->html(); + QString url = UBApplication::urlFromHtml(qsHtml); + + if("" != url) + { + downloadURL(url, pPos); + return; + } + } + + if (pMimeData->hasUrls()) + { + QList urls = pMimeData->urls(); + + int index = 0; + + foreach(const QUrl url, urls){ + QPointF pos(pPos + QPointF(index * 15, index * 15)); + downloadURL(url, pos); + index++; + } + + return; + } + + if (pMimeData->hasImage()) + { + QImage img = qvariant_cast (pMimeData->imageData()); + QPixmap pix = QPixmap::fromImage(img); + + // validate that the image is really an image, webkit does not fill properly the image mime data + if (pix.width() != 0 && pix.height() != 0) + { + mActiveScene->addPixmap(pix, pPos, 1.); + return; + } + } + + if (pMimeData->hasText()) + { + if("" != pMimeData->text()){ + // Sometimes, it is possible to have an URL as text. we check here if it is the case + QString qsTmp = pMimeData->text().remove(QRegExp("[\\0]")); + if(qsTmp.startsWith("http")){ + downloadURL(QUrl(qsTmp), pPos); + } + else{ + mActiveScene->addTextHtml(pMimeData->html(), pPos); + } + } + else{ +#ifdef Q_WS_MACX + // With Safari, in 95% of the drops, the mime datas are hidden in Apple Web Archive pasteboard type. + // This is due to the way Safari is working so we have to dig into the pasteboard in order to retrieve + // the data. + QString qsUrl = UBPlatformUtils::urlFromClipboard(); + if("" != qsUrl){ + // We finally got the url of the dropped ressource! Let's import it! + downloadURL(qsUrl, pPos); + return; + } +#endif + } + } +} + + +void UBBoardController::togglePodcast(bool checked) +{ + if (UBPodcastController::instance()) + UBPodcastController::instance()->toggleRecordingPalette(checked); +} + + +void UBBoardController::moveGraphicsWidgetToControlView(UBGraphicsWidgetItem* graphicsWidget) +{ + QPoint controlViewPos = mControlView->mapFromScene(graphicsWidget->sceneBoundingRect().center()); + + graphicsWidget->setSelected(false); + + UBAbstractWidget *aw = graphicsWidget->widgetWebView(); + graphicsWidget->setWidget(0); + + UBToolWidget *toolWidget = new UBToolWidget(aw, mControlContainer); + + graphicsWidget->scene()->removeItem(graphicsWidget); // TODO UB 4.6 probably leaking the frame + + toolWidget->centerOn(mControlView->mapTo(mControlContainer, controlViewPos)); + + toolWidget->show(); +} + + +void UBBoardController::moveToolWidgetToScene(UBToolWidget* toolWidget) +{ + int xIsOdd = toolWidget->width() % 2; + int yIsOdd = toolWidget->height() % 2; + + QPoint mainWindowCenter = toolWidget->mapTo(mMainWindow, QPoint(toolWidget->width(), toolWidget->height()) / 2); + + UBAbstractWidget* webWidget = toolWidget->webWidget(); + webWidget->setParent(0); + + UBGraphicsWidgetItem* graphicsWidget = 0; + + UBW3CWidget* w3cWidget = qobject_cast(webWidget); + if (w3cWidget) + { + graphicsWidget = new UBGraphicsW3CWidgetItem(w3cWidget); + } + else + { + UBAppleWidget* appleWidget = qobject_cast(webWidget); + if (appleWidget) + { + graphicsWidget = new UBGraphicsAppleWidgetItem(appleWidget); + } + } + + QPoint controlViewCenter = mControlView->mapFrom(mMainWindow, mainWindowCenter); + QPointF scenePos = mControlView->mapToScene(controlViewCenter) + QPointF(xIsOdd * 0.5, yIsOdd * 0.5); + + mActiveScene->addGraphicsWidget(graphicsWidget, scenePos); + + toolWidget->hide(); + toolWidget->deleteLater(); +} + + +void UBBoardController::updateBackgroundActionsState(bool isDark, bool isCrossed) +{ + if (isDark && !isCrossed) + mMainWindow->actionPlainDarkBackground->setChecked(true); + else if (isDark && isCrossed) + mMainWindow->actionCrossedDarkBackground->setChecked(true); + else if (!isDark && isCrossed) + mMainWindow->actionCrossedLightBackground->setChecked(true); + else + mMainWindow->actionPlainLightBackground->setChecked(true); +} + + +void UBBoardController::addItem() +{ + QString defaultPath = UBSettings::settings()->lastImportToLibraryPath->get().toString(); + + QString extensions; + foreach(QString ext, UBSettings::imageFileExtensions) + { + extensions += " *."; + extensions += ext; + } + + QString filename = QFileDialog::getOpenFileName(mControlContainer, tr("Add Item"), + defaultPath, + tr("All Supported (%1)").arg(extensions), NULL, QFileDialog::DontUseNativeDialog); + + if (filename.length() > 0) + { + mPaletteManager->addItem(QUrl::fromLocalFile(filename)); + QFileInfo source(filename); + UBSettings::settings()->lastImportToLibraryPath->set(QVariant(source.absolutePath())); + } +} + +void UBBoardController::importPage() +{ + int pageCount = mActiveDocument->pageCount(); + + if (UBApplication::documentController->addFileToDocument(mActiveDocument)) + { + setActiveDocumentScene(mActiveDocument, pageCount); + } +} + +void UBBoardController::notifyPageChanged() +{ + emit pageChanged(); +} + +void UBBoardController::onDownloadModalFinished() +{ + +} + +void UBBoardController::displayMetaData(QMap metadatas) +{ + emit displayMetadata(metadatas); +} + +void UBBoardController::freezeW3CWidgets(bool freeze) +{ + if (mActiveSceneIndex >= 0) + { + QList list = UBApplication::boardController->activeScene()->getFastAccessItems(); + foreach(QGraphicsItem *item, list) + { + freezeW3CWidget(item, freeze); + } + } +} + +void UBBoardController::freezeW3CWidget(QGraphicsItem *item, bool freeze) +{ + if(item->type() == UBGraphicsW3CWidgetItem::Type) + { + QString scriptString; + if (freeze) + scriptString = "setfreezed(true);"; + else + scriptString = "setfreezed(false);"; + UBGraphicsW3CWidgetItem* item_casted = dynamic_cast(item); + if (0 == item_casted) + return; + item_casted->widgetWebView()->page()->mainFrame()->evaluateJavaScript(scriptString); + } +} \ No newline at end of file diff --git a/src/board/UBBoardController.h b/src/board/UBBoardController.h index a15e8add..4ea56d7a 100644 --- a/src/board/UBBoardController.h +++ b/src/board/UBBoardController.h @@ -1,285 +1,289 @@ -/* - * 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 UBBOARDCONTROLLER_H_ -#define UBBOARDCONTROLLER_H_ - -#include - -#include - -class UBMainWindow; -class UBApplication; -class UBBoardView; - -class UBDocumentController; -class UBMessageWindow; -class UBGraphicsScene; -class UBDocumentProxy; -class UBBlackoutWidget; -class UBToolWidget; -class UBVersion; -class UBSoftwareUpdate; -class UBSoftwareUpdateDialog; -class UBGraphicsVideoItem; -class UBGraphicsAudioItem; -class UBGraphicsWidgetItem; -class UBBoardPaletteManager; - - -class UBBoardController : public QObject -{ - Q_OBJECT - - public: - UBBoardController(UBMainWindow *mainWindow); - virtual ~UBBoardController(); - - void init(); - void setupLayout(); - UBDocumentProxy* activeDocument() const; - UBGraphicsScene* activeScene() const; - int activeSceneIndex() const; - QSize displayViewport(); - QSize controlViewport(); - QRectF controlGeometry(); - void closing(); - - UBDocumentProxy* activeDocument() - { - return mActiveDocument; - } - - QWidget* controlContainer() - { - return mControlContainer; - } - - UBBoardView* controlView() - { - return mControlView; - } - - UBBoardView* displayView() - { - return mDisplayView; - } - - UBGraphicsScene* activeScene() - { - return mActiveScene; - } - - void setPenColorOnDarkBackground(const QColor& pColor) - { - if (mPenColorOnDarkBackground == pColor) - return; - - mPenColorOnDarkBackground = pColor; - emit penColorChanged(); - } - - void setPenColorOnLightBackground(const QColor& pColor) - { - if (mPenColorOnLightBackground == pColor) - return; - - mPenColorOnLightBackground = pColor; - emit penColorChanged(); - } - - void setMarkerColorOnDarkBackground(const QColor& pColor) - { - mMarkerColorOnDarkBackground = pColor; - } - - void setMarkerColorOnLightBackground(const QColor& pColor) - { - mMarkerColorOnLightBackground = pColor; - } - - QColor penColorOnDarkBackground() - { - return mPenColorOnDarkBackground; - } - - QColor penColorOnLightBackground() - { - return mPenColorOnLightBackground; - } - - QColor markerColorOnDarkBackground() - { - return mMarkerColorOnDarkBackground; - } - - QColor markerColorOnLightBackground() - { - return mMarkerColorOnLightBackground; - } - - qreal systemScaleFactor() - { - return mSystemScaleFactor; - } - qreal currentZoom(); - void persistCurrentScene(); - void showNewVersionAvailable(bool automatic, const UBVersion &installedVersion, const UBSoftwareUpdate &softwareUpdate); - void setBoxing(QRect displayRect); - void setToolbarTexts(); - static QUrl expandWidgetToTempDir(const QByteArray& pZipedData, const QString& pExtension = QString("wgt")); -// static QRect freeRectInGlobalPos() const {return ;} - void setPageSize(QSize newSize); - UBBoardPaletteManager *paletteManager() - { - return mPaletteManager; - } - - void notifyCache(bool visible); - void notifyPageChanged(); - void displayMetaData(QMap metadatas); - - void ClearUndoStack(); - - - public slots: - void setActiveDocumentScene(UBDocumentProxy* pDocumentProxy, int pSceneIndex = 0); - void showDocumentsDialog(); - void showKeyboard(bool show); - void togglePodcast(bool checked); - void blackout(); - void addScene(); - void addScene(UBDocumentProxy* proxy, int sceneIndex, bool replaceActiveIfEmpty = false); - void addScene(UBGraphicsScene* scene, bool replaceActiveIfEmpty = false); - void duplicateScene(); - void importPage(); - void clearScene(); - void clearSceneItems(); - void clearSceneAnnotation(); - void zoomIn(QPointF scenePoint = QPointF(0,0)); - void zoomOut(QPointF scenePoint = QPointF(0,0)); - void zoomRestore(); - void centerRestore(); - void centerOn(QPointF scenePoint = QPointF(0,0)); - void zoom(const qreal ratio, QPointF scenePoint); - void handScroll(qreal dx, qreal dy); - void previousScene(); - void nextScene(); - void firstScene(); - void lastScene(); - void downloadURL(const QUrl& url, const QPointF& pPos = QPointF(0.0, 0.0), const QSize& pSize = QSize(), bool isBackground = false); - void downloadFinished(bool pSuccess, QUrl sourceUrl, QString pHeader, QByteArray pData, QPointF pPos, QSize pSize, bool isBackground = false); - void changeBackground(bool isDark, bool isCrossed); - void setToolCursor(int tool); - void showMessage(const QString& message, bool showSpinningWheel); - void hideMessage(); - void setDisabled(bool disable); - void setColorIndex(int pColorIndex); - UBToolWidget* addTool(const QUrl& toolUrl, QPointF scenePos); - UBToolWidget* addTool(const QUrl& toolUrl); - void removeTool(UBToolWidget* toolWidget); - void hide(); - void show(); - void setWidePageSize(bool checked); - void setRegularPageSize(bool checked); - void stylusToolChanged(int tool); - void grabScene(const QRectF& pSceneRect); - void controlViewHidden(); - void controlViewShown(); - UBGraphicsVideoItem* addVideo(const QUrl& pUrl, bool startPlay, const QPointF& pos); - UBGraphicsAudioItem* addAudio(const QUrl& pUrl, bool startPlay, const QPointF& pos); - UBGraphicsWidgetItem *addW3cWidget(const QUrl& pUrl, const QPointF& pos); - - void cut(); - void copy(); - void paste(); - void processMimeData(const QMimeData* pMimeData, const QPointF& pPos); - void moveGraphicsWidgetToControlView(UBGraphicsWidgetItem* graphicWidget); - void moveToolWidgetToScene(UBToolWidget* toolWidget); - void addItem(); - - signals: - void activeSceneWillBePersisted(); - void activeSceneWillChange(); - void activeSceneChanged(); - void activeDocumentChanged(); - void zoomChanged(qreal pZoomFactor); - void systemScaleFactorChanged(qreal pSystemScaleFactor); - void penColorChanged(); - void controlViewportChanged(); - void backgroundChanged(); - void cacheEnabled(); - void cacheDisabled(); - void pageChanged(); - void setDocOnPageNavigator(UBDocumentProxy* doc); - void documentReorganized(int index); - void displayMetadata(QMap metadata); - - protected: - void setupViews(); - void setupToolbar(); - void connectToolbar(); - void initToolbarTexts(); - void updateActionStates(); - void updateSystemScaleFactor(); - QString truncate(QString text, int maxWidth); - - protected slots: - void selectionChanged(); - void undoRedoStateChange(bool canUndo); - void documentSceneChanged(UBDocumentProxy* proxy, int pIndex); - - private: - void updatePageSizeState(); - void saveViewState(); - void adjustDisplayViews(); - - UBMainWindow *mMainWindow; - UBDocumentProxy* mActiveDocument; - UBGraphicsScene* mActiveScene; - int mActiveSceneIndex; - UBBoardPaletteManager *mPaletteManager; - UBSoftwareUpdateDialog *mSoftwareUpdateDialog; - UBMessageWindow *mMessageWindow; - UBBoardView *mControlView; - UBBoardView *mDisplayView; - QWidget *mControlContainer; - QHBoxLayout *mControlLayout; - qreal mZoomFactor; - bool mIsClosing; - QColor mPenColorOnDarkBackground; - QColor mPenColorOnLightBackground; - QColor mMarkerColorOnDarkBackground; - QColor mMarkerColorOnLightBackground; - QList mTools; - qreal mSystemScaleFactor; - bool mCleanupDone; - QMap > mActionTexts; - - private slots: - void stylusToolDoubleClicked(int tool); - void boardViewResized(QResizeEvent* event); - void documentWillBeDeleted(UBDocumentProxy* pProxy); - void updateBackgroundActionsState(bool isDark, bool isCrossed); - void updateBackgroundState(); - void colorPaletteChanged(); - void libraryDialogClosed(int ret); - void lastWindowClosed(); - void onDownloadModalFinished(); - -}; - - -#endif /* UBBOARDCONTROLLER_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 UBBOARDCONTROLLER_H_ +#define UBBOARDCONTROLLER_H_ + +#include + +#include + +class UBMainWindow; +class UBApplication; +class UBBoardView; + +class UBDocumentController; +class UBMessageWindow; +class UBGraphicsScene; +class UBDocumentProxy; +class UBBlackoutWidget; +class UBToolWidget; +class UBVersion; +class UBSoftwareUpdate; +class UBSoftwareUpdateDialog; +class UBGraphicsVideoItem; +class UBGraphicsAudioItem; +class UBGraphicsWidgetItem; +class UBBoardPaletteManager; + + +class UBBoardController : public QObject +{ + Q_OBJECT + + public: + UBBoardController(UBMainWindow *mainWindow); + virtual ~UBBoardController(); + + void init(); + void setupLayout(); + UBDocumentProxy* activeDocument() const; + UBGraphicsScene* activeScene() const; + int activeSceneIndex() const; + QSize displayViewport(); + QSize controlViewport(); + QRectF controlGeometry(); + void closing(); + + UBDocumentProxy* activeDocument() + { + return mActiveDocument; + } + + QWidget* controlContainer() + { + return mControlContainer; + } + + UBBoardView* controlView() + { + return mControlView; + } + + UBBoardView* displayView() + { + return mDisplayView; + } + + UBGraphicsScene* activeScene() + { + return mActiveScene; + } + + void setPenColorOnDarkBackground(const QColor& pColor) + { + if (mPenColorOnDarkBackground == pColor) + return; + + mPenColorOnDarkBackground = pColor; + emit penColorChanged(); + } + + void setPenColorOnLightBackground(const QColor& pColor) + { + if (mPenColorOnLightBackground == pColor) + return; + + mPenColorOnLightBackground = pColor; + emit penColorChanged(); + } + + void setMarkerColorOnDarkBackground(const QColor& pColor) + { + mMarkerColorOnDarkBackground = pColor; + } + + void setMarkerColorOnLightBackground(const QColor& pColor) + { + mMarkerColorOnLightBackground = pColor; + } + + QColor penColorOnDarkBackground() + { + return mPenColorOnDarkBackground; + } + + QColor penColorOnLightBackground() + { + return mPenColorOnLightBackground; + } + + QColor markerColorOnDarkBackground() + { + return mMarkerColorOnDarkBackground; + } + + QColor markerColorOnLightBackground() + { + return mMarkerColorOnLightBackground; + } + + qreal systemScaleFactor() + { + return mSystemScaleFactor; + } + qreal currentZoom(); + void persistCurrentScene(); + void showNewVersionAvailable(bool automatic, const UBVersion &installedVersion, const UBSoftwareUpdate &softwareUpdate); + void setBoxing(QRect displayRect); + void setToolbarTexts(); + static QUrl expandWidgetToTempDir(const QByteArray& pZipedData, const QString& pExtension = QString("wgt")); +// static QRect freeRectInGlobalPos() const {return ;} + void setPageSize(QSize newSize); + UBBoardPaletteManager *paletteManager() + { + return mPaletteManager; + } + + void notifyCache(bool visible); + void notifyPageChanged(); + void displayMetaData(QMap metadatas); + + void ClearUndoStack(); + + public slots: + void setActiveDocumentScene(UBDocumentProxy* pDocumentProxy, int pSceneIndex = 0); + void showDocumentsDialog(); + void showKeyboard(bool show); + void togglePodcast(bool checked); + void blackout(); + void addScene(); + void addScene(UBDocumentProxy* proxy, int sceneIndex, bool replaceActiveIfEmpty = false); + void addScene(UBGraphicsScene* scene, bool replaceActiveIfEmpty = false); + void duplicateScene(); + void importPage(); + void clearScene(); + void clearSceneItems(); + void clearSceneAnnotation(); + void zoomIn(QPointF scenePoint = QPointF(0,0)); + void zoomOut(QPointF scenePoint = QPointF(0,0)); + void zoomRestore(); + void centerRestore(); + void centerOn(QPointF scenePoint = QPointF(0,0)); + void zoom(const qreal ratio, QPointF scenePoint); + void handScroll(qreal dx, qreal dy); + void previousScene(); + void nextScene(); + void firstScene(); + void lastScene(); + void downloadURL(const QUrl& url, const QPointF& pPos = QPointF(0.0, 0.0), const QSize& pSize = QSize(), bool isBackground = false); + void downloadFinished(bool pSuccess, QUrl sourceUrl, QString pHeader, QByteArray pData, QPointF pPos, QSize pSize, bool isBackground = false); + void changeBackground(bool isDark, bool isCrossed); + void setToolCursor(int tool); + void showMessage(const QString& message, bool showSpinningWheel); + void hideMessage(); + void setDisabled(bool disable); + void setColorIndex(int pColorIndex); + UBToolWidget* addTool(const QUrl& toolUrl, QPointF scenePos); + UBToolWidget* addTool(const QUrl& toolUrl); + void removeTool(UBToolWidget* toolWidget); + void hide(); + void show(); + void setWidePageSize(bool checked); + void setRegularPageSize(bool checked); + void stylusToolChanged(int tool); + void grabScene(const QRectF& pSceneRect); + void controlViewHidden(); + void controlViewShown(); + UBGraphicsVideoItem* addVideo(const QUrl& pUrl, bool startPlay, const QPointF& pos); + UBGraphicsAudioItem* addAudio(const QUrl& pUrl, bool startPlay, const QPointF& pos); + UBGraphicsWidgetItem *addW3cWidget(const QUrl& pUrl, const QPointF& pos); + + void cut(); + void copy(); + void paste(); + void processMimeData(const QMimeData* pMimeData, const QPointF& pPos); + void moveGraphicsWidgetToControlView(UBGraphicsWidgetItem* graphicWidget); + void moveToolWidgetToScene(UBToolWidget* toolWidget); + void addItem(); + + void freezeW3CWidgets(bool freeze); + void freezeW3CWidget(QGraphicsItem* item, bool freeze); + void startScript(); + void stopScript(); + + signals: + void activeSceneWillBePersisted(); + void activeSceneWillChange(); + void activeSceneChanged(); + void activeDocumentChanged(); + void zoomChanged(qreal pZoomFactor); + void systemScaleFactorChanged(qreal pSystemScaleFactor); + void penColorChanged(); + void controlViewportChanged(); + void backgroundChanged(); + void cacheEnabled(); + void cacheDisabled(); + void pageChanged(); + void setDocOnPageNavigator(UBDocumentProxy* doc); + void documentReorganized(int index); + void displayMetadata(QMap metadata); + + protected: + void setupViews(); + void setupToolbar(); + void connectToolbar(); + void initToolbarTexts(); + void updateActionStates(); + void updateSystemScaleFactor(); + QString truncate(QString text, int maxWidth); + + protected slots: + void selectionChanged(); + void undoRedoStateChange(bool canUndo); + void documentSceneChanged(UBDocumentProxy* proxy, int pIndex); + + private: + void updatePageSizeState(); + void saveViewState(); + void adjustDisplayViews(); + + UBMainWindow *mMainWindow; + UBDocumentProxy* mActiveDocument; + UBGraphicsScene* mActiveScene; + int mActiveSceneIndex; + UBBoardPaletteManager *mPaletteManager; + UBSoftwareUpdateDialog *mSoftwareUpdateDialog; + UBMessageWindow *mMessageWindow; + UBBoardView *mControlView; + UBBoardView *mDisplayView; + QWidget *mControlContainer; + QHBoxLayout *mControlLayout; + qreal mZoomFactor; + bool mIsClosing; + QColor mPenColorOnDarkBackground; + QColor mPenColorOnLightBackground; + QColor mMarkerColorOnDarkBackground; + QColor mMarkerColorOnLightBackground; + QList mTools; + qreal mSystemScaleFactor; + bool mCleanupDone; + QMap > mActionTexts; + + private slots: + void stylusToolDoubleClicked(int tool); + void boardViewResized(QResizeEvent* event); + void documentWillBeDeleted(UBDocumentProxy* pProxy); + void updateBackgroundActionsState(bool isDark, bool isCrossed); + void updateBackgroundState(); + void colorPaletteChanged(); + void libraryDialogClosed(int ret); + void lastWindowClosed(); + void onDownloadModalFinished(); + +}; + + +#endif /* UBBOARDCONTROLLER_H_ */ diff --git a/src/core/UBApplication.cpp b/src/core/UBApplication.cpp index a1a2d19d..aadb0367 100644 --- a/src/core/UBApplication.cpp +++ b/src/core/UBApplication.cpp @@ -237,8 +237,11 @@ int UBApplication::exec(const QString& pFileToImport) mainWindow->actionCut->setShortcuts(QKeySequence::Cut); connect(mainWindow->actionBoard, SIGNAL(triggered()), this, SLOT(showBoard())); + connect(mainWindow->actionBoard, SIGNAL(triggered()), this, SLOT(startScript())); connect(mainWindow->actionWeb, SIGNAL(triggered()), this, SLOT(showInternet())); + connect(mainWindow->actionWeb, SIGNAL(triggered()), this, SLOT(stopScript())); connect(mainWindow->actionDocument, SIGNAL(triggered()), this, SLOT(showDocument())); + connect(mainWindow->actionDocument, SIGNAL(triggered()), this, SLOT(stopScript())); connect(mainWindow->actionQuit, SIGNAL(triggered()), this, SLOT(closing())); connect(mainWindow, SIGNAL(closeEvent_Signal(QCloseEvent*)), this, SLOT(closeEvent(QCloseEvent*))); @@ -262,6 +265,7 @@ int UBApplication::exec(const QString& pFileToImport) connect(mainWindow->actionDesktop, SIGNAL(triggered(bool)), applicationController, SLOT(showDesktop(bool))); + connect(mainWindow->actionDesktop, SIGNAL(triggered(bool)), this, SLOT(stopScript())); #ifndef Q_WS_MAC connect(mainWindow->actionHideApplication, SIGNAL(triggered()), mainWindow, SLOT(showMinimized())); #else @@ -274,6 +278,7 @@ int UBApplication::exec(const QString& pFileToImport) connect(mainWindow->actionPreferences, SIGNAL(triggered()), mPreferencesController, SLOT(show())); connect(mainWindow->actionTutorial, SIGNAL(triggered()), applicationController, SLOT(showTutorial())); + connect(mainWindow->actionTutorial, SIGNAL(triggered()), this, SLOT(stopScript())); connect(mainWindow->actionSankoreEditor, SIGNAL(triggered()), applicationController, SLOT(showSankoreEditor())); connect(mainWindow->actionCheckUpdate, SIGNAL(triggered()), applicationController, SLOT(checkUpdateRequest())); @@ -353,6 +358,16 @@ void UBApplication::showMinimized() #endif +void UBApplication::startScript() +{ + this->boardController->freezeW3CWidgets(false); +} + +void UBApplication::stopScript() +{ + this->boardController->freezeW3CWidgets(true); +} + void UBApplication::showBoard() { applicationController->showBoard(); diff --git a/src/core/UBApplication.h b/src/core/UBApplication.h index db7edeb9..0ca7ac37 100644 --- a/src/core/UBApplication.h +++ b/src/core/UBApplication.h @@ -1,161 +1,163 @@ -/* - * 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 UBAPPLICATION_H_ -#define UBAPPLICATION_H_ - -#include - -#include "qtsingleapplication.h" - -#include "transition/UniboardSankoreTransition.h" - -namespace Ui -{ - class MainWindow; -} - - -class UBBoardController; -class UBWebController; -class UBControlView; -class UBPreferencesController; -class UBResources; -class UBSettings; -class UBPersistenceManager; -class UBApplicationController; -class UBDocumentController; -class UBSoftwareUpdateController; -class UBMainWindow; - -class UBApplication : public QtSingleApplication -{ - Q_OBJECT; - - public: - - UBApplication(const QString &id, int &argc, char **argv); - virtual ~UBApplication(); - - int exec(const QString& pFileToImport); - - void cleanup(); - - static QPointer undoStack; - - static UBApplicationController *applicationController; - static UBBoardController* boardController; - static UBWebController* webController; - static UBDocumentController* documentController; - static UBSoftwareUpdateController* softwareUpdateController; - static UniboardSankoreTransition* mUniboardSankoreTransition; - - static UBMainWindow* mainWindow; - - static UBApplication* app() - { - return static_castqApp; - } - - static const QString mimeTypeUniboardDocument; - static const QString mimeTypeUniboardPage; - static const QString mimeTypeUniboardPageItem; - static const QString mimeTypeUniboardPageThumbnail; - - static void showMessage(const QString& message, bool showSpinningWheel = false); - static void setDisabled(bool disable); - - static QObject* staticMemoryCleaner; - static QString globalStyleSheet(); - - void decorateActionMenu(QAction* action); - void insertSpaceToToolbarBeforeAction(QToolBar* toolbar, QAction* action, int width = -1); - - int toolBarHeight(); - bool eventFilter(QObject *obj, QEvent *event); - - bool isVerbose() { return mIsVerbose;} - void setVerbose(bool verbose){mIsVerbose = verbose;} - static QString urlFromHtml(QString html); - static bool isFromWeb(QString url); - - signals: - - public slots: - - void showBoard(); - void showInternet(); - void showDocument(); - - void toolBarPositionChanged(QVariant topOrBottom); - void toolBarDisplayTextChanged(QVariant display); - - void closeEvent(QCloseEvent *event); - - /** - * Used on Windows platform to open file in running application. On MacOS X opening file is done through the - * FileOpen event that is handle in eventFilter method. - */ - bool handleOpenMessage(const QString& pMessage); - - private slots: - - void closing(); -#ifdef Q_WS_MAC - void showMinimized(); -#endif - void importUniboardFiles(); - private: - - void updateProtoActionsState(); - QList mProtoMenus; - bool mIsVerbose; - - protected: - -#if defined(Q_WS_MACX) && !defined(QT_MAC_USE_COCOA) - bool macEventFilter(EventHandlerCallRef caller, EventRef event); -#endif - - UBPreferencesController* mPreferencesController; - -}; - - -class UBStyle : public QPlastiqueStyle -{ - public: - - UBStyle() - : QPlastiqueStyle() - { - // NOOP - } - - virtual ~UBStyle() - { - // NOOP - } - - /* - * redefined to be more cocoa like on texts - */ - virtual void drawItemText(QPainter *painter, const QRect &rect, int alignment, const QPalette &pal, - bool enabled, const QString& text, QPalette::ColorRole textRole) const; - - -}; - -#endif /* UBAPPLICATION_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 UBAPPLICATION_H_ +#define UBAPPLICATION_H_ + +#include + +#include "qtsingleapplication.h" + +#include "transition/UniboardSankoreTransition.h" + +namespace Ui +{ + class MainWindow; +} + + +class UBBoardController; +class UBWebController; +class UBControlView; +class UBPreferencesController; +class UBResources; +class UBSettings; +class UBPersistenceManager; +class UBApplicationController; +class UBDocumentController; +class UBSoftwareUpdateController; +class UBMainWindow; + +class UBApplication : public QtSingleApplication +{ + Q_OBJECT; + + public: + + UBApplication(const QString &id, int &argc, char **argv); + virtual ~UBApplication(); + + int exec(const QString& pFileToImport); + + void cleanup(); + + static QPointer undoStack; + + static UBApplicationController *applicationController; + static UBBoardController* boardController; + static UBWebController* webController; + static UBDocumentController* documentController; + static UBSoftwareUpdateController* softwareUpdateController; + static UniboardSankoreTransition* mUniboardSankoreTransition; + + static UBMainWindow* mainWindow; + + static UBApplication* app() + { + return static_castqApp; + } + + static const QString mimeTypeUniboardDocument; + static const QString mimeTypeUniboardPage; + static const QString mimeTypeUniboardPageItem; + static const QString mimeTypeUniboardPageThumbnail; + + static void showMessage(const QString& message, bool showSpinningWheel = false); + static void setDisabled(bool disable); + + static QObject* staticMemoryCleaner; + static QString globalStyleSheet(); + + void decorateActionMenu(QAction* action); + void insertSpaceToToolbarBeforeAction(QToolBar* toolbar, QAction* action, int width = -1); + + int toolBarHeight(); + bool eventFilter(QObject *obj, QEvent *event); + + bool isVerbose() { return mIsVerbose;} + void setVerbose(bool verbose){mIsVerbose = verbose;} + static QString urlFromHtml(QString html); + static bool isFromWeb(QString url); + + signals: + + public slots: + + void showBoard(); + void showInternet(); + void showDocument(); + void startScript(); + void stopScript(); + + void toolBarPositionChanged(QVariant topOrBottom); + void toolBarDisplayTextChanged(QVariant display); + + void closeEvent(QCloseEvent *event); + + /** + * Used on Windows platform to open file in running application. On MacOS X opening file is done through the + * FileOpen event that is handle in eventFilter method. + */ + bool handleOpenMessage(const QString& pMessage); + + private slots: + + void closing(); +#ifdef Q_WS_MAC + void showMinimized(); +#endif + void importUniboardFiles(); + private: + + void updateProtoActionsState(); + QList mProtoMenus; + bool mIsVerbose; + + protected: + +#if defined(Q_WS_MACX) && !defined(QT_MAC_USE_COCOA) + bool macEventFilter(EventHandlerCallRef caller, EventRef event); +#endif + + UBPreferencesController* mPreferencesController; + +}; + + +class UBStyle : public QPlastiqueStyle +{ + public: + + UBStyle() + : QPlastiqueStyle() + { + // NOOP + } + + virtual ~UBStyle() + { + // NOOP + } + + /* + * redefined to be more cocoa like on texts + */ + virtual void drawItemText(QPainter *painter, const QRect &rect, int alignment, const QPalette &pal, + bool enabled, const QString& text, QPalette::ColorRole textRole) const; + + +}; + +#endif /* UBAPPLICATION_H_ */ diff --git a/src/core/UBDocumentManager.cpp b/src/core/UBDocumentManager.cpp index f39a242b..48dd0352 100644 --- a/src/core/UBDocumentManager.cpp +++ b/src/core/UBDocumentManager.cpp @@ -1,294 +1,294 @@ -/* - * 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 "UBDocumentManager.h" - -#include "frameworks/UBStringUtils.h" - -#include "adaptors/UBExportFullPDF.h" -#include "adaptors/UBExportDocument.h" -#include "adaptors/UBExportWeb.h" -#include "adaptors/UBWebPublisher.h" -#include "adaptors/UBImportDocument.h" -#include "adaptors/UBImportPDF.h" -#include "adaptors/UBImportImage.h" -#include "adaptors/UBImportCFF.h" - -#include "domain/UBGraphicsScene.h" -#include "domain/UBGraphicsSvgItem.h" -#include "domain/UBGraphicsPixmapItem.h" - -#include "document/UBDocumentProxy.h" - -#include "UBApplication.h" -#include "UBSettings.h" -#include "UBPersistenceManager.h" - -#include "../adaptors/UBExportWeb.h" - -#include "core/memcheck.h" - -UBDocumentManager* UBDocumentManager::sDocumentManager = 0; - -UBDocumentManager* UBDocumentManager::documentManager() -{ - if (!sDocumentManager) - { - sDocumentManager = new UBDocumentManager(qApp); - } - return sDocumentManager; -} - - -UBDocumentManager::UBDocumentManager(QObject *parent) - :QObject(parent) -{ - // TODO UB 4.7 string used in document persistence (folder names) - QString dummyImages = tr("images"); - QString dummyVideos = tr("videos"); - QString dummyObjects = tr("objects"); - QString dummyWidgets = tr("widgets"); - - UBExportFullPDF* exportFullPdf = new UBExportFullPDF(this); - mExportAdaptors.append(exportFullPdf); - UBExportDocument* exportDocument = new UBExportDocument(this); - mExportAdaptors.append(exportDocument); -// UBExportWeb* exportWeb = new UBExportWeb(this); -// mExportAdaptors.append(exportWeb); - UBWebPublisher* webPublished = new UBWebPublisher(this); - mExportAdaptors.append(webPublished); - - UBImportDocument* documentImport = new UBImportDocument(this); - mImportAdaptors.append(documentImport); - UBImportPDF* pdfImport = new UBImportPDF(this); - mImportAdaptors.append(pdfImport); - UBImportImage* imageImport = new UBImportImage(this); - mImportAdaptors.append(imageImport); - UBImportCFF* cffImport = new UBImportCFF(this); - mImportAdaptors.append(cffImport); -} - - -UBDocumentManager::~UBDocumentManager() -{ - // NOOP -} - - -QStringList UBDocumentManager::importFileExtensions() -{ - QStringList result; - - foreach (UBImportAdaptor *importAdaptor, mImportAdaptors) - { - result << importAdaptor->supportedExtentions(); - } - return result; -} - - -QString UBDocumentManager::importFileFilter() -{ - QString result; - - result += tr("All supported files (*.%1)").arg(importFileExtensions().join(" *.")); - foreach (UBImportAdaptor *importAdaptor, mImportAdaptors) - { - if (importAdaptor->importFileFilter().length() > 0) - { - if (result.length()) - { - result += ";;"; - } - result += importAdaptor->importFileFilter(); - } - } - qDebug() << "import file filter" << result; - return result; -} - - -UBDocumentProxy* UBDocumentManager::importFile(const QFile& pFile, const QString& pGroup) -{ - QFileInfo fileInfo(pFile); - - UBDocumentProxy* document = 0; - - foreach (UBImportAdaptor *importAdaptor, mImportAdaptors) - { - if (importAdaptor->supportedExtentions().lastIndexOf(fileInfo.suffix().toLower()) != -1) - { - UBApplication::setDisabled(true); - document = importAdaptor->importFile(pFile, pGroup); - UBApplication::setDisabled(false); - } - } - - return document; -} - - -bool UBDocumentManager::addFileToDocument(UBDocumentProxy* pDocument, const QFile& pFile) -{ - QFileInfo fileInfo(pFile); - foreach (UBImportAdaptor *importAdaptor, mImportAdaptors) - { - if (importAdaptor->supportedExtentions().lastIndexOf(fileInfo.suffix().toLower()) != -1) - { - UBApplication::setDisabled(true); - bool result = importAdaptor->addFileToDocument(pDocument, pFile); - UBApplication::setDisabled(false); - return result; - } - } - return false; -} - - -int UBDocumentManager::addImageDirToDocument(const QDir& pDir, UBDocumentProxy* pDocument) -{ - QStringList filenames = pDir.entryList(QDir::Files | QDir::NoDotAndDotDot); - - filenames = UBStringUtils::sortByLastDigit(filenames); - - QStringList fullPathFilenames; - - foreach(QString f, filenames) - { - fullPathFilenames << pDir.absolutePath() + "/" + f; - } - - return addImageAsPageToDocument(fullPathFilenames, pDocument); - -} - - -UBDocumentProxy* UBDocumentManager::importDir(const QDir& pDir, const QString& pGroup) -{ - UBDocumentProxy* doc = UBPersistenceManager::persistenceManager()->createDocument(pGroup, pDir.dirName()); - - int result = addImageDirToDocument(pDir, doc); - - if (result > 0) - { - doc->setMetaData(UBSettings::documentGroupName, pGroup); - doc->setMetaData(UBSettings::documentName, pDir.dirName()); - - UBPersistenceManager::persistenceManager()->persistDocumentMetadata(doc); - - UBApplication::showMessage(tr("File %1 saved").arg(pDir.dirName())); - - } - else - { - UBPersistenceManager::persistenceManager()->deleteDocument(doc); - } - - return doc; -} - - -QList UBDocumentManager::supportedExportAdaptors() -{ - return mExportAdaptors; -} - -int UBDocumentManager::addImageAsPageToDocument(const QStringList& filenames, UBDocumentProxy* pDocument) -{ - - int result = 0; - - if (filenames.size() > 0) - { - QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); - - QApplication::processEvents(); - - int pageIndex = pDocument->pageCount(); - - if (pageIndex == 1 && UBPersistenceManager::persistenceManager()->loadDocumentScene(pDocument, 0)->isEmpty()) - { - pageIndex = 0; - } - - int expectedPageCount = filenames.size(); - - for(int i = 0; i < filenames.size(); i ++) - { - UBApplication::showMessage(tr("Importing page %1 of %2").arg(i + 1).arg(expectedPageCount)); - - UBGraphicsScene* scene = 0; - - QString fullPath = filenames.at(i); - - QGraphicsItem *gi = 0; - - if (pageIndex == 0) - { - scene = UBPersistenceManager::persistenceManager()->loadDocumentScene(pDocument, pageIndex); - } - else - { - scene = UBPersistenceManager::persistenceManager()->createDocumentSceneAt(pDocument, pageIndex); - } - - scene->setBackground(false, false); - - if (fullPath.endsWith(".svg") || fullPath.endsWith(".svgz")) - { - gi = scene->addSvg(QUrl::fromLocalFile(fullPath), QPointF(0, 0)); - } - else - { - QPixmap pix(fullPath); - - if (pix.isNull()) - { - UBApplication::showMessage(tr("Erronous image data, skipping file %1").arg(filenames.at(i))); - expectedPageCount--; - continue; - } - else - { - gi = scene->addPixmap(pix, QPointF(0, 0)); - } - } - - if (gi) - { - scene->setAsBackgroundObject(gi, true); - - UBPersistenceManager::persistenceManager()->persistDocumentScene(pDocument, scene, pageIndex); - - pageIndex++; - } - - } - - result = expectedPageCount; - - QApplication::restoreOverrideCursor(); - - } - - return result; - -} - -void UBDocumentManager::emitDocumentUpdated(UBDocumentProxy* pDocument) -{ - emit documentUpdated(pDocument); -} +/* + * 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 "UBDocumentManager.h" + +#include "frameworks/UBStringUtils.h" + +#include "adaptors/UBExportFullPDF.h" +#include "adaptors/UBExportDocument.h" +#include "adaptors/UBExportWeb.h" +#include "adaptors/UBWebPublisher.h" +#include "adaptors/UBImportDocument.h" +#include "adaptors/UBImportPDF.h" +#include "adaptors/UBImportImage.h" +#include "adaptors/UBImportCFF.h" + +#include "domain/UBGraphicsScene.h" +#include "domain/UBGraphicsSvgItem.h" +#include "domain/UBGraphicsPixmapItem.h" + +#include "document/UBDocumentProxy.h" + +#include "UBApplication.h" +#include "UBSettings.h" +#include "UBPersistenceManager.h" + +#include "../adaptors/UBExportWeb.h" + +#include "core/memcheck.h" + +UBDocumentManager* UBDocumentManager::sDocumentManager = 0; + +UBDocumentManager* UBDocumentManager::documentManager() +{ + if (!sDocumentManager) + { + sDocumentManager = new UBDocumentManager(qApp); + } + return sDocumentManager; +} + + +UBDocumentManager::UBDocumentManager(QObject *parent) + :QObject(parent) +{ + // TODO UB 4.7 string used in document persistence (folder names) + QString dummyImages = tr("images"); + QString dummyVideos = tr("videos"); + QString dummyObjects = tr("objects"); + QString dummyWidgets = tr("widgets"); + + UBExportFullPDF* exportFullPdf = new UBExportFullPDF(this); + mExportAdaptors.append(exportFullPdf); + UBExportDocument* exportDocument = new UBExportDocument(this); + mExportAdaptors.append(exportDocument); +// UBExportWeb* exportWeb = new UBExportWeb(this); +// mExportAdaptors.append(exportWeb); + UBWebPublisher* webPublished = new UBWebPublisher(this); + mExportAdaptors.append(webPublished); + + UBImportDocument* documentImport = new UBImportDocument(this); + mImportAdaptors.append(documentImport); + UBImportPDF* pdfImport = new UBImportPDF(this); + mImportAdaptors.append(pdfImport); + UBImportImage* imageImport = new UBImportImage(this); + mImportAdaptors.append(imageImport); + UBImportCFF* cffImport = new UBImportCFF(this); + mImportAdaptors.append(cffImport); +} + + +UBDocumentManager::~UBDocumentManager() +{ + // NOOP +} + + +QStringList UBDocumentManager::importFileExtensions() +{ + QStringList result; + + foreach (UBImportAdaptor *importAdaptor, mImportAdaptors) + { + result << importAdaptor->supportedExtentions(); + } + return result; +} + + +QString UBDocumentManager::importFileFilter() +{ + QString result; + + result += tr("All supported files (*.%1)").arg(importFileExtensions().join(" *.")); + foreach (UBImportAdaptor *importAdaptor, mImportAdaptors) + { + if (importAdaptor->importFileFilter().length() > 0) + { + if (result.length()) + { + result += ";;"; + } + result += importAdaptor->importFileFilter(); + } + } + qDebug() << "import file filter" << result; + return result; +} + + +UBDocumentProxy* UBDocumentManager::importFile(const QFile& pFile, const QString& pGroup) +{ + QFileInfo fileInfo(pFile); + + UBDocumentProxy* document = 0; + + foreach (UBImportAdaptor *importAdaptor, mImportAdaptors) + { + if (importAdaptor->supportedExtentions().lastIndexOf(fileInfo.suffix().toLower()) != -1) + { + UBApplication::setDisabled(true); + document = importAdaptor->importFile(pFile, pGroup); + UBApplication::setDisabled(false); + } + } + + return document; +} + + +bool UBDocumentManager::addFileToDocument(UBDocumentProxy* pDocument, const QFile& pFile) +{ + QFileInfo fileInfo(pFile); + foreach (UBImportAdaptor *importAdaptor, mImportAdaptors) + { + if (importAdaptor->supportedExtentions().lastIndexOf(fileInfo.suffix().toLower()) != -1) + { + UBApplication::setDisabled(true); + bool result = importAdaptor->addFileToDocument(pDocument, pFile); + UBApplication::setDisabled(false); + return result; + } + } + return false; +} + + +int UBDocumentManager::addImageDirToDocument(const QDir& pDir, UBDocumentProxy* pDocument) +{ + QStringList filenames = pDir.entryList(QDir::Files | QDir::NoDotAndDotDot); + + filenames = UBStringUtils::sortByLastDigit(filenames); + + QStringList fullPathFilenames; + + foreach(QString f, filenames) + { + fullPathFilenames << pDir.absolutePath() + "/" + f; + } + + return addImageAsPageToDocument(fullPathFilenames, pDocument); + +} + + +UBDocumentProxy* UBDocumentManager::importDir(const QDir& pDir, const QString& pGroup) +{ + UBDocumentProxy* doc = UBPersistenceManager::persistenceManager()->createDocument(pGroup, pDir.dirName()); + + int result = addImageDirToDocument(pDir, doc); + + if (result > 0) + { + doc->setMetaData(UBSettings::documentGroupName, pGroup); + doc->setMetaData(UBSettings::documentName, pDir.dirName()); + + UBPersistenceManager::persistenceManager()->persistDocumentMetadata(doc); + + UBApplication::showMessage(tr("File %1 saved").arg(pDir.dirName())); + + } + else + { + UBPersistenceManager::persistenceManager()->deleteDocument(doc); + } + + return doc; +} + + +QList UBDocumentManager::supportedExportAdaptors() +{ + return mExportAdaptors; +} + +int UBDocumentManager::addImageAsPageToDocument(const QStringList& filenames, UBDocumentProxy* pDocument) +{ + + int result = 0; + + if (filenames.size() > 0) + { + QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + + QApplication::processEvents(); + + int pageIndex = pDocument->pageCount(); + + if (pageIndex == 1 && UBPersistenceManager::persistenceManager()->loadDocumentScene(pDocument, 0)->isEmpty()) + { + pageIndex = 0; + } + + int expectedPageCount = filenames.size(); + + for(int i = 0; i < filenames.size(); i ++) + { + UBApplication::showMessage(tr("Importing page %1 of %2").arg(i + 1).arg(expectedPageCount)); + + UBGraphicsScene* scene = 0; + + QString fullPath = filenames.at(i); + + QGraphicsItem *gi = 0; + + if (pageIndex == 0) + { + scene = UBPersistenceManager::persistenceManager()->loadDocumentScene(pDocument, pageIndex); + } + else + { + scene = UBPersistenceManager::persistenceManager()->createDocumentSceneAt(pDocument, pageIndex); + } + + scene->setBackground(false, false); + + if (fullPath.endsWith(".svg") || fullPath.endsWith(".svgz")) + { + gi = scene->addSvg(QUrl::fromLocalFile(fullPath), QPointF(0, 0)); + } + else + { + QPixmap pix(fullPath); + + if (pix.isNull()) + { + UBApplication::showMessage(tr("Erronous image data, skipping file %1").arg(filenames.at(i))); + expectedPageCount--; + continue; + } + else + { + gi = scene->addPixmap(pix, QPointF(0, 0)); + } + } + + if (gi) + { + scene->setAsBackgroundObject(gi, true); + + UBPersistenceManager::persistenceManager()->persistDocumentScene(pDocument, scene, pageIndex); + + pageIndex++; + } + + } + + result = expectedPageCount; + + QApplication::restoreOverrideCursor(); + + } + + return result; + +} + +void UBDocumentManager::emitDocumentUpdated(UBDocumentProxy* pDocument) +{ + emit documentUpdated(pDocument); +} diff --git a/src/domain/UBGraphicsItemUndoCommand.cpp b/src/domain/UBGraphicsItemUndoCommand.cpp index 467080e6..d027c1f0 100644 --- a/src/domain/UBGraphicsItemUndoCommand.cpp +++ b/src/domain/UBGraphicsItemUndoCommand.cpp @@ -1,110 +1,137 @@ -/* - * 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 "UBGraphicsItemUndoCommand.h" - -#include - -#include "UBGraphicsScene.h" - -#include "core/memcheck.h" - - -UBGraphicsItemUndoCommand::UBGraphicsItemUndoCommand(UBGraphicsScene* pScene, const QSet& pRemovedItems, - const QSet& pAddedItems) - : mScene(pScene) - , mRemovedItems(pRemovedItems - pAddedItems) - , mAddedItems(pAddedItems - pRemovedItems) -{ - mFirstRedo = true; -} - -UBGraphicsItemUndoCommand::UBGraphicsItemUndoCommand(UBGraphicsScene* pScene, QGraphicsItem* pRemovedItem, - QGraphicsItem* pAddedItem) : - mScene(pScene) -{ - - if (pRemovedItem) - mRemovedItems.insert(pRemovedItem); - - if (pAddedItem) - mAddedItems.insert(pAddedItem); - - mFirstRedo = true; - -} - -UBGraphicsItemUndoCommand::~UBGraphicsItemUndoCommand() -{ - //NOOP -} - -void UBGraphicsItemUndoCommand::undo() -{ - if (!mScene){ - return; - } - - QSetIterator itAdded(mAddedItems); - while (itAdded.hasNext()) - { - QGraphicsItem* item = itAdded.next(); - item->setSelected(false); - mScene->removeItem(item); - } - - QSetIterator itRemoved(mRemovedItems); - while (itRemoved.hasNext()) - { - mScene->addItem(itRemoved.next()); - } - - // force refresh, QT is a bit lazy and take a lot of time (nb item ^2 ?) to trigger repaint - mScene->update(mScene->sceneRect()); - -} - -void UBGraphicsItemUndoCommand::redo() -{ - // the Undo framework calls a redo while appending the undo command. - // as we have already plotted the elements, we do not want to do it twice - if (!mFirstRedo) - { - if (!mScene){ - return; - } - - QSetIterator itRemoved(mRemovedItems); - while (itRemoved.hasNext()) - { - QGraphicsItem* item = itRemoved.next(); - item->setSelected(false); - mScene->removeItem(item); - } - - QSetIterator itAdded(mAddedItems); - while (itAdded.hasNext()) - { - mScene->addItem(itAdded.next()); - } - - // force refresh, QT is a bit lazy and take a lot of time (nb item ^2) to trigger repaint - mScene->update(mScene->sceneRect()); - } - else - { - mFirstRedo = false; - } -} +/* + * 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 "UBGraphicsItemUndoCommand.h" + +#include + +#include "UBGraphicsScene.h" + +#include "core/memcheck.h" + +#include "core/UBApplication.h" + +#include "board/UBBoardController.h" + +UBGraphicsItemUndoCommand::UBGraphicsItemUndoCommand(UBGraphicsScene* pScene, const QSet& pRemovedItems, + const QSet& pAddedItems) + : mScene(pScene) + , mRemovedItems(pRemovedItems - pAddedItems) + , mAddedItems(pAddedItems - pRemovedItems) +{ + mFirstRedo = true; + + QSetIterator itAdded(mAddedItems); + while (itAdded.hasNext()) + { + UBApplication::boardController->freezeW3CWidget(itAdded.next(), true); + } + + QSetIterator itRemoved(mRemovedItems); + while (itRemoved.hasNext()) + { + UBApplication::boardController->freezeW3CWidget(itRemoved.next(), false); + } +} + +UBGraphicsItemUndoCommand::UBGraphicsItemUndoCommand(UBGraphicsScene* pScene, QGraphicsItem* pRemovedItem, + QGraphicsItem* pAddedItem) : + mScene(pScene) +{ + + if (pRemovedItem) + { + mRemovedItems.insert(pRemovedItem); + UBApplication::boardController->freezeW3CWidget(pRemovedItem, true); + } + + if (pAddedItem) + { + mAddedItems.insert(pAddedItem); + UBApplication::boardController->freezeW3CWidget(pAddedItem, false); + } + + mFirstRedo = true; + +} + +UBGraphicsItemUndoCommand::~UBGraphicsItemUndoCommand() +{ + //NOOP +} + +void UBGraphicsItemUndoCommand::undo() +{ + if (!mScene){ + return; + } + + QSetIterator itAdded(mAddedItems); + while (itAdded.hasNext()) + { + QGraphicsItem* item = itAdded.next(); + item->setSelected(false); + mScene->removeItem(item); + UBApplication::boardController->freezeW3CWidget(item, true); + } + + QSetIterator itRemoved(mRemovedItems); + while (itRemoved.hasNext()) + { + QGraphicsItem* item = itRemoved.next(); + mScene->addItem(item); + UBApplication::boardController->freezeW3CWidget(item, false); + } + + // force refresh, QT is a bit lazy and take a lot of time (nb item ^2 ?) to trigger repaint + mScene->update(mScene->sceneRect()); + +} + +void UBGraphicsItemUndoCommand::redo() +{ + // the Undo framework calls a redo while appending the undo command. + // as we have already plotted the elements, we do not want to do it twice + if (!mFirstRedo) + { + if (!mScene){ + return; + } + + QSetIterator itRemoved(mRemovedItems); + while (itRemoved.hasNext()) + { + QGraphicsItem* item = itRemoved.next(); + item->setSelected(false); + mScene->removeItem(item); + UBApplication::boardController->freezeW3CWidget(item, true); + } + + QSetIterator itAdded(mAddedItems); + while (itAdded.hasNext()) + { + QGraphicsItem* item = itAdded.next(); + mScene->addItem(item); + UBApplication::boardController->freezeW3CWidget(item, false); + } + + // force refresh, QT is a bit lazy and take a lot of time (nb item ^2) to trigger repaint + mScene->update(mScene->sceneRect()); + } + else + { + mFirstRedo = false; + } +} diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index d2632678..b20cf7f8 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -1,2010 +1,2008 @@ -/* - * 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 "UBGraphicsScene.h" - -#include -#include -#include -#include - -#include "frameworks/UBGeometryUtils.h" -#include "frameworks/UBPlatformUtils.h" - -#include "core/UBApplication.h" -#include "core/UBSettings.h" -#include "core/UBApplicationController.h" -#include "core/UBDisplayManager.h" -#include "core/UBPersistenceManager.h" - -#include "gui/UBMagnifer.h" - -#include "tools/UBGraphicsRuler.h" -#include "tools/UBGraphicsProtractor.h" -#include "tools/UBGraphicsCompass.h" -#include "tools/UBGraphicsTriangle.h" -#include "tools/UBGraphicsCurtainItem.h" -#include "tools/UBGraphicsCache.h" - -#include "document/UBDocumentProxy.h" - -#include "board/UBBoardController.h" -#include "board/UBDrawingController.h" - -#include "UBGraphicsItemUndoCommand.h" -#include "UBGraphicsTextItemUndoCommand.h" -#include "UBGraphicsProxyWidget.h" -#include "UBGraphicsPixmapItem.h" -#include "UBGraphicsSvgItem.h" -#include "UBGraphicsPolygonItem.h" -#include "UBGraphicsVideoItem.h" -#include "UBGraphicsAudioItem.h" -#include "UBGraphicsWidgetItem.h" -#include "UBGraphicsPDFItem.h" -#include "UBGraphicsTextItem.h" - -#include "UBAppleWidget.h" -#include "UBW3CWidget.h" -#include "UBGraphicsStroke.h" - -#include "core/memcheck.h" - -qreal UBGraphicsScene::backgroundLayerStart = -20000000.0; -qreal UBGraphicsScene::objectLayerStart = -10000000.0; -qreal UBGraphicsScene::drawingLayerStart = 0.0; -qreal UBGraphicsScene::toolLayerStart = 10000000.0; - -qreal UBGraphicsScene::toolOffsetRuler = 100; -qreal UBGraphicsScene::toolOffsetProtractor = 100; -qreal UBGraphicsScene::toolOffsetTriangle = 100; -qreal UBGraphicsScene::toolOffsetCompass = 100; -qreal UBGraphicsScene::toolOffsetEraser = 200; - -qreal UBGraphicsScene::toolOffsetCurtain = 1000; -qreal UBGraphicsScene::toolOffsetPointer = 1100; - -qreal UBGraphicsScene::toolOffsetCache = 1000;//Didier please define offset you want - -UBGraphicsScene::UBGraphicsScene(UBDocumentProxy* parent) - : UBCoreGraphicsScene(parent) - , mEraser(0) - , mPointer(0) - , mDocument(parent) - , mDarkBackground(false) - , mCrossedBackground(false) - , mIsModified(true) - , mBackgroundObject(0) - , mPreviousWidth(0) - , mInputDeviceIsPressed(false) - , mArcPolygonItem(0) - , mRenderingContext(Screen) - , mCurrentStroke(0) - , mShouldUseOMP(true) - , mItemCount(0) - , enableUndoRedoStack(true) - , magniferControlViewWidget(0) - , magniferDisplayViewWidget(0) - -{ - -#ifdef __ppc__ - mShouldUseOMP = false; -#elif defined(Q_WS_MAC) - mShouldUseOMP = QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5; -#endif - - setDocument(parent); - - mDrawingZIndex = drawingLayerStart; - mObjectZIndex = objectLayerStart; - - mEraser = new QGraphicsEllipseItem(); // mem : owned and destroyed by the scene - mEraser->setRect(QRect(0, 0, 0, 0)); - mEraser->setVisible(false); - - mEraser->setZValue(/*toolLayerStart + toolOffsetEraser*/2); - mEraser->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Control)); - - mTools << mEraser; - addItem(mEraser); - - mPointer = new QGraphicsEllipseItem(); // mem : owned and destroyed by the scene - mPointer->setRect(QRect(0, 0, 20, 20)); - mPointer->setVisible(false); - - mPointer->setPen(Qt::NoPen); - mPointer->setBrush(QBrush(QColor(255, 0, 0, 186))); - - mPointer->setZValue( /*toolLayerStart + toolOffsetPointer*/ 2); - mPointer->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Tool)); - - mTools << mPointer; - addItem(mPointer); - - if (UBApplication::applicationController) - { - setViewState(SceneViewState(1, - UBApplication::applicationController->initialHScroll(), - UBApplication::applicationController->initialVScroll())); - } - - connect(this, SIGNAL(selectionChanged()), this, SLOT(selectionChangedProcessing())); - - -} - -UBGraphicsScene::~UBGraphicsScene() -{ - DisposeMagnifierQWidgets(); - - if (mCurrentStroke) - if (mCurrentStroke->polygons().empty()) - delete mCurrentStroke; -} - -void UBGraphicsScene::selectionChangedProcessing() -{ - if (selectedItems().count()) - UBApplication::showMessage("ZValue is " + QString::number(selectedItems().first()->zValue(), 'f')); - - - QList allItemsList = items(); - qreal maxZ = 0.; - for( int i = 0; i < allItemsList.size(); i++ ) { - QGraphicsItem *nextItem = allItemsList.at(i); - //Temporary stub. Due to ugly z-order implementation I need to do this (sankore 360) - //z-order behavior should be reimplemented and this stub should be deleted - if (nextItem == mBackgroundObject) - continue; - //Temporary stub end (sankore 360) - if (nextItem->zValue() > maxZ) - maxZ = nextItem->zValue(); - nextItem->setZValue(nextItem->data(UBGraphicsItemData::ItemOwnZValue).toReal()); -// nextItem->setZValue(qreal(1)); - } - QList selItemsList = selectedItems(); - for( int i = 0; i < selItemsList.size(); i++ ) { - QGraphicsItem *nextItem = selItemsList.at(i); - nextItem->setZValue(maxZ + 0.0001); - } -} - -// MARK: - -// MARK: Mouse/Tablet events handling - -bool UBGraphicsScene::inputDevicePress(const QPointF& scenePos, const qreal& pressure) -{ - //mMesure1Ms = 0; - //mMesure2Ms = 0; - - bool accepted = false; - - if (mInputDeviceIsPressed) - { - qWarning() << "scene received input device pressed, without input device release, muting event as input device move"; - accepted = inputDeviceMove(scenePos, pressure); - } - else - { - mInputDeviceIsPressed = true; - - UBStylusTool::Enum currentTool = (UBStylusTool::Enum)UBDrawingController::drawingController()->stylusTool(); - - if (UBDrawingController::drawingController()->isDrawingTool()) - { - qreal width = 0; - - // delete current stroke, if not assigned to any polygon - if (mCurrentStroke) - if (mCurrentStroke->polygons().empty()) - delete mCurrentStroke; - - mCurrentStroke = new UBGraphicsStroke(); - - if (currentTool != UBStylusTool::Line) - width = UBDrawingController::drawingController()->currentToolWidth() * pressure; - else - width = UBDrawingController::drawingController()->currentToolWidth(); //ignore pressure for line tool - - width /= UBApplication::boardController->systemScaleFactor(); - width /= UBApplication::boardController->currentZoom(); - - mAddedItems.clear(); - mRemovedItems.clear(); - - if (UBDrawingController::drawingController()->mActiveRuler) - { - UBDrawingController::drawingController()->mActiveRuler->StartLine( - scenePos, width); - } - else - { - moveTo(scenePos); - drawLineTo(scenePos, width, - UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Line); - } - accepted = true; - } - else if (currentTool == UBStylusTool::Eraser) - { - mAddedItems.clear(); - mRemovedItems.clear(); - moveTo(scenePos); - - qreal eraserWidth = UBSettings::settings()->currentEraserWidth(); - eraserWidth /= UBApplication::boardController->systemScaleFactor(); - eraserWidth /= UBApplication::boardController->currentZoom(); - - eraseLineTo(scenePos, eraserWidth); - drawEraser(scenePos, true); - - accepted = true; - } - else if (currentTool == UBStylusTool::Pointer) - { - drawPointer(scenePos, true); - accepted = true; - } - } - - return accepted; -} - - -bool UBGraphicsScene::inputDeviceMove(const QPointF& scenePos, const qreal& pressure) -{ - bool accepted = false; - - UBDrawingController *dc = UBDrawingController::drawingController(); - UBStylusTool::Enum currentTool = (UBStylusTool::Enum)dc->stylusTool(); - - QPointF position = QPointF(scenePos); - - if (currentTool == UBStylusTool::Eraser) - { - drawEraser(position); - accepted = true; - } - - if (mInputDeviceIsPressed) - { - if (dc->isDrawingTool()) - { - qreal width = 0; - - if (currentTool != UBStylusTool::Line) - width = dc->currentToolWidth() * pressure; - else - width = dc->currentToolWidth();//ignore pressure for line tool - - width /= UBApplication::boardController->systemScaleFactor(); - width /= UBApplication::boardController->currentZoom(); - - if (dc->mActiveRuler) - { - dc->mActiveRuler->DrawLine(position, width); - } - else - { - if (currentTool == UBStylusTool::Line) - { - // TODO: Verify this beautiful implementation and check if - // it is possible to optimize it - QLineF radius(mPreviousPoint, position); - qreal angle = radius.angle(); - angle = qRound(angle / 45) * 45; - qreal radiusLength = radius.length(); - QPointF newPosition( - mPreviousPoint.x() + radiusLength * cos((angle * PI) / 180), - mPreviousPoint.y() - radiusLength * sin((angle * PI) / 180)); - QLineF chord(position, newPosition); - if (chord.length() < qMin((int)16, (int)(radiusLength / 20))) - position = newPosition; - } - - drawLineTo(position, width, - UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Line); - } - } - else if (currentTool == UBStylusTool::Eraser) - { - qreal eraserWidth = UBSettings::settings()->currentEraserWidth(); - eraserWidth /= UBApplication::boardController->systemScaleFactor(); - eraserWidth /= UBApplication::boardController->currentZoom(); - - eraseLineTo(position, eraserWidth); - } - else if (currentTool == UBStylusTool::Pointer) - { - drawPointer(position); - } - - accepted = true; - } - - return accepted; -} - - -bool UBGraphicsScene::inputDeviceRelease() -{ - /* - if (mMesure1Ms > 0 || mMesure2Ms > 0) - { - qWarning() << "---------------------------"; - qWarning() << "mMesure1Ms: " << mMesure1Ms; - qWarning() << "mMesure2Ms: " << mMesure2Ms; - - mMesure1Ms = 0; - mMesure2Ms = 0; - } - */ - - bool accepted = false; - - - - if (mPointer) - { - mPointer->hide(); - accepted = true; - } - - UBDrawingController *dc = UBDrawingController::drawingController(); - if (dc->isDrawingTool()) - { - if (mCurrentStroke) - { - if (mCurrentStroke->polygons().empty()) - delete mCurrentStroke; - mCurrentStroke = 0; - } - } - - if (mRemovedItems.size() > 0 || mAddedItems.size() > 0) - { - - if (enableUndoRedoStack) { //should be deleted after scene own undo stack implemented - UBGraphicsItemUndoCommand* udcmd = new UBGraphicsItemUndoCommand(this, mRemovedItems, mAddedItems); //deleted by the undoStack - - if(UBApplication::undoStack) - UBApplication::undoStack->push(udcmd); - } - - mRemovedItems.clear(); - mAddedItems.clear(); - accepted = true; - } - - mInputDeviceIsPressed = false; - - setDocumentUpdated(); - - return accepted; -} - -// MARK: - - -void UBGraphicsScene::drawEraser(const QPointF &pPoint, bool isFirstDraw) -{ - qreal eraserWidth = UBSettings::settings()->currentEraserWidth(); - eraserWidth /= UBApplication::boardController->systemScaleFactor(); - eraserWidth /= UBApplication::boardController->currentZoom(); - - qreal eraserRadius = eraserWidth / 2; - - // TODO UB 4.x optimize - no need to do that every time we move it - if (mEraser) - { - mEraser->setRect(QRectF(pPoint.x() - eraserRadius, pPoint.y() - eraserRadius, eraserWidth, eraserWidth)); - - if(isFirstDraw) - { - qreal maxZ = 0.; - QList allItemsList = items(); - for( int i = 0; i < allItemsList.size(); i++ ) - { - QGraphicsItem *nextItem = allItemsList.at(i); - qreal zValue = nextItem->zValue(); - if (zValue > maxZ) - maxZ = zValue; - nextItem->setZValue(nextItem->data(UBGraphicsItemData::ItemOwnZValue).toReal()); - } - - mEraser->setZValue(maxZ + 0.0001); - mEraser->show(); - } - } -} - -void UBGraphicsScene::drawPointer(const QPointF &pPoint, bool isFirstDraw) -{ - qreal pointerDiameter = UBSettings::pointerDiameter / UBApplication::boardController->currentZoom(); - qreal pointerRadius = pointerDiameter / 2; - - // TODO UB 4.x optimize - no need to do that every time we move it - if (mPointer) - { - mPointer->setRect(QRectF(pPoint.x() - pointerRadius, - pPoint.y() - pointerRadius, - pointerDiameter, - pointerDiameter)); - - if(isFirstDraw) - { - qreal maxZ = 0.; - QList allItemsList = items(); - for( int i = 0; i < allItemsList.size(); i++ ) - { - QGraphicsItem *nextItem = allItemsList.at(i); - qreal zValue = nextItem->zValue(); - if (zValue > maxZ) - maxZ = zValue; - nextItem->setZValue(nextItem->data(UBGraphicsItemData::ItemOwnZValue).toReal()); - } - - mPointer->setZValue(maxZ + 0.0001); - mPointer->show(); - } - } -} - -// call this function when user release mouse button in Magnifier mode -void UBGraphicsScene::DisposeMagnifierQWidgets() -{ - if(magniferControlViewWidget) - { - magniferControlViewWidget->hide(); - magniferControlViewWidget->setParent(0); - delete magniferControlViewWidget; - magniferControlViewWidget = NULL; - } - - if(magniferDisplayViewWidget) - { - magniferDisplayViewWidget->hide(); - magniferDisplayViewWidget->setParent(0); - delete magniferDisplayViewWidget; - magniferDisplayViewWidget = NULL; - } - - // some time have crash here on access to app (when call from destructor when close sankore app) - // so i just add try/catch section here - try - { - UBApplication::app()->restoreOverrideCursor(); - } - catch (...) - { - } - -} - -void UBGraphicsScene::moveTo(const QPointF &pPoint) -{ - mPreviousPoint = pPoint; - mPreviousWidth = -1.0; - mPreviousPolygonItems.clear(); - mArcPolygonItem = 0; -} - - -void UBGraphicsScene::drawLineTo(const QPointF &pEndPoint, const qreal &pWidth, bool bLineStyle) -{ - if (mPreviousWidth == -1.0) - mPreviousWidth = pWidth; - - UBGraphicsPolygonItem *polygonItem = lineToPolygonItem(QLineF(mPreviousPoint, pEndPoint), pWidth); - - if (!polygonItem->brush().isOpaque()) - { - for (int i = 0; i < mPreviousPolygonItems.size(); i++) - { - UBGraphicsPolygonItem* previous = mPreviousPolygonItems.value(i); - polygonItem->subtract(previous); - } - } - - if (bLineStyle) - { - QSetIterator itItems(mAddedItems); - - while (itItems.hasNext()) - { - QGraphicsItem* item = itItems.next(); - removeItem(item); - } - mAddedItems.clear(); - } - - mAddedItems.insert(polygonItem); - - if (mCurrentStroke) - { - polygonItem->setStroke(mCurrentStroke); - } - - addItem(polygonItem); - - mPreviousPolygonItems.append(polygonItem); - - if (!bLineStyle) - { - mPreviousPoint = pEndPoint; - mPreviousWidth = pWidth; - } -} - - -void UBGraphicsScene::eraseLineTo(const QPointF &pEndPoint, const qreal &pWidth) -{ - const QLineF line(mPreviousPoint, pEndPoint); - - const QPolygonF eraserPolygon = UBGeometryUtils::lineToPolygon(line, pWidth); - const QRectF eraserBoundingRect = eraserPolygon.boundingRect(); - const QRectF eraserInnerRect = UBGeometryUtils::lineToInnerRect(line, pWidth); - - QPainterPath eraserPathVar; - eraserPathVar.addPolygon(eraserPolygon); - const QPainterPath eraserPath = eraserPathVar; - - QList collidItems = items(eraserBoundingRect, Qt::IntersectsItemBoundingRect); - - QSet toBeAddedItems; - QSet toBeRemovedItems; - - int collidItemsSize = collidItems.size(); - - toBeAddedItems.reserve(collidItemsSize); - toBeRemovedItems.reserve(collidItemsSize); - - if (mShouldUseOMP) - { -#pragma omp parallel for - for (int i = 0; i < collidItemsSize; i++) - { - UBGraphicsPolygonItem *collidingPolygonItem - = qgraphicsitem_cast (collidItems.at(i)); - - if (collidingPolygonItem) - { - if(eraserInnerRect.contains(collidingPolygonItem->boundingRect())) - { -#pragma omp critical - toBeRemovedItems << collidingPolygonItem; - } - else - { - QPolygonF collidingPolygon = collidingPolygonItem->polygon(); - QPainterPath collidingPath; - collidingPath.addPolygon(collidingPolygon); - - QPainterPath croppedPath = collidingPath.subtracted(eraserPath); - QPainterPath croppedPathSimplified = croppedPath.simplified(); - - if (croppedPath == collidingPath) - { - // NOOP - } - else if (croppedPathSimplified.isEmpty()) - { -#pragma omp critical - toBeRemovedItems << collidingPolygonItem; - } - else - { - foreach(const QPolygonF &pol, croppedPathSimplified.toFillPolygons()) - { - UBGraphicsPolygonItem* croppedPolygonItem = collidingPolygonItem->deepCopy(pol); -#pragma omp critical - toBeAddedItems << croppedPolygonItem; - } -#pragma omp critical - toBeRemovedItems << collidingPolygonItem; - } - } - } - } - } - else - { - for (int i = 0; i < collidItemsSize; i++) - { - UBGraphicsPolygonItem *collidingPolygonItem - = qgraphicsitem_cast (collidItems.at(i)); - - if (collidingPolygonItem) - { - if(eraserInnerRect.contains(collidingPolygonItem->boundingRect())) - { - toBeRemovedItems << collidingPolygonItem; - } - else - { - QPolygonF collidingPolygon = collidingPolygonItem->polygon(); - QPainterPath collidingPath; - collidingPath.addPolygon(collidingPolygon); - - QPainterPath croppedPath = collidingPath.subtracted(eraserPath); - QPainterPath croppedPathSimplified = croppedPath.simplified(); - - if (croppedPath == collidingPath) - { - // NOOP - } - else if (croppedPathSimplified.isEmpty()) - { - toBeRemovedItems << collidingPolygonItem; - } - else - { - foreach(const QPolygonF &pol, croppedPathSimplified.toFillPolygons()) - { - UBGraphicsPolygonItem* croppedPolygonItem = collidingPolygonItem->deepCopy(pol); - toBeAddedItems << croppedPolygonItem; - } - - toBeRemovedItems << collidingPolygonItem; - } - } - } - } - } - - addItems(toBeAddedItems); - mAddedItems += toBeAddedItems; - - removeItems(toBeRemovedItems); - mRemovedItems += toBeRemovedItems; - - mPreviousPoint = pEndPoint; -} - - -void UBGraphicsScene::drawArcTo(const QPointF& pCenterPoint, qreal pSpanAngle) -{ - if (mArcPolygonItem) - { - mAddedItems.remove(mArcPolygonItem); - removeItem(mArcPolygonItem); - mArcPolygonItem = 0; - } - qreal penWidth = UBSettings::settings()->currentPenWidth(); - penWidth /= UBApplication::boardController->systemScaleFactor(); - penWidth /= UBApplication::boardController->currentZoom(); - - mArcPolygonItem = arcToPolygonItem(QLineF(pCenterPoint, mPreviousPoint), pSpanAngle, penWidth); - mAddedItems.insert(mArcPolygonItem); - addItem(mArcPolygonItem); - - setDocumentUpdated(); -} - - -qreal UBGraphicsScene::getNextDrawingZIndex() -{ - mDrawingZIndex = mDrawingZIndex + 1.0; - return mDrawingZIndex; -} - - -qreal UBGraphicsScene::getNextObjectZIndex() -{ - mObjectZIndex = mObjectZIndex + 1.0; - return mObjectZIndex; -} - - -void UBGraphicsScene::setBackground(bool pIsDark, bool pIsCrossed) -{ - bool needRepaint = false; - - if (mDarkBackground != pIsDark) - { - mDarkBackground = pIsDark; - - if (mEraser) - { - if (mDarkBackground) - { - mEraser->setBrush(UBSettings::eraserBrushDarkBackground); - mEraser->setPen(UBSettings::eraserPenDarkBackground); - } - else - { - mEraser->setBrush(UBSettings::eraserBrushLightBackground); - mEraser->setPen(UBSettings::eraserPenLightBackground); - } - } - - recolorAllItems(); - - needRepaint = true; - setModified(true); - } - - if (mCrossedBackground != pIsCrossed) - { - mCrossedBackground = pIsCrossed; - needRepaint = true; - setModified(true); - } - - if (needRepaint) - { - foreach(QGraphicsView* view, views()) - { - view->resetCachedContent(); - } - } -} - - -void UBGraphicsScene::recolorAllItems() -{ - QMap previousUpdateModes; - foreach(QGraphicsView* view, views()) - { - previousUpdateModes.insert(view, view->viewportUpdateMode()); - view->setViewportUpdateMode(QGraphicsView::NoViewportUpdate); - } - - for(int i = 0; i < mFastAccessItems.size(); i++) - { - UBGraphicsPolygonItem *polygonItem = qgraphicsitem_cast (mFastAccessItems.at(i)); - - if (polygonItem) - { - QColor color; - - if (mDarkBackground) - { - color = polygonItem->colorOnDarkBackground(); - } - else - { - color = polygonItem->colorOnLightBackground(); - } - - polygonItem->setColor(color); - continue; - } - } - - foreach(QGraphicsView* view, views()) - { - view->setViewportUpdateMode(previousUpdateModes.value(view)); - } -} - - -UBGraphicsPolygonItem* UBGraphicsScene::lineToPolygonItem(const QLineF &pLine, const qreal &pWidth) -{ - UBGraphicsPolygonItem *polygonItem = new UBGraphicsPolygonItem(pLine, pWidth); - - initPolygonItem(polygonItem); - - return polygonItem; -} - - -void UBGraphicsScene::initPolygonItem(UBGraphicsPolygonItem* polygonItem) -{ - QColor colorOnDarkBG; - QColor colorOnLightBG; - - if (UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Marker) - { - colorOnDarkBG = UBApplication::boardController->markerColorOnDarkBackground(); - colorOnLightBG = UBApplication::boardController->markerColorOnLightBackground(); - } - else // settings->stylusTool() == UBStylusTool::Pen + failsafe - { - colorOnDarkBG = UBApplication::boardController->penColorOnDarkBackground(); - colorOnLightBG = UBApplication::boardController->penColorOnLightBackground(); - } - - if (mDarkBackground) - { - polygonItem->setColor(colorOnDarkBG); - } - else - { - polygonItem->setColor(colorOnLightBG); - } - - polygonItem->setColorOnDarkBackground(colorOnDarkBG); - polygonItem->setColorOnLightBackground(colorOnLightBG); - - polygonItem->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Graphic)); - -// polygonItem->setZValue(getNextDrawingZIndex()); - UBGraphicsItem::assignZValue(polygonItem, getNextDrawingZIndex()); -} - - -UBGraphicsPolygonItem* UBGraphicsScene::arcToPolygonItem(const QLineF& pStartRadius, qreal pSpanAngle, qreal pWidth) -{ - QPolygonF polygon = UBGeometryUtils::arcToPolygon(pStartRadius, pSpanAngle, pWidth); - - return polygonToPolygonItem(polygon); -} - - -UBGraphicsPolygonItem* UBGraphicsScene::polygonToPolygonItem(const QPolygonF pPolygon) -{ - UBGraphicsPolygonItem *polygonItem = new UBGraphicsPolygonItem(pPolygon); - - initPolygonItem(polygonItem); - - return polygonItem; -} - - -void UBGraphicsScene::hideEraser() -{ - if (mEraser) - mEraser->hide(); -} - - -void UBGraphicsScene::leaveEvent(QEvent * event) -{ - Q_UNUSED(event); - hideEraser(); -} - - -UBGraphicsScene* UBGraphicsScene::sceneDeepCopy() const -{ - UBGraphicsScene* copy = new UBGraphicsScene(this->document()); - - copy->setBackground(this->isDarkBackground(), this->isCrossedBackground()); - - copy->mDrawingZIndex = this->mDrawingZIndex; - copy->mObjectZIndex = this->mObjectZIndex; - copy->setSceneRect(this->sceneRect()); - - if (this->mNominalSize.isValid()) - copy->setNominalSize(this->mNominalSize); - - QListIterator itItems(this->mFastAccessItems); - - QMap groupClone; - - while (itItems.hasNext()) - { - QGraphicsItem* item = itItems.next(); - QGraphicsItem* cloneItem = 0; - - UBItem* ubItem = dynamic_cast(item); - UBGraphicsStroke* stroke = dynamic_cast(item); - - if (ubItem && !stroke) - { - cloneItem = dynamic_cast(ubItem->deepCopy()); - } - - if (cloneItem) - { - copy->addItem(cloneItem); - - if (isBackgroundObject(item)) - { - copy->setAsBackgroundObject(cloneItem); - } - - if (this->mTools.contains(item)) - { - copy->mTools << cloneItem; - } - - UBGraphicsPolygonItem* polygon = dynamic_cast(item); - - if(polygon) - { - UBGraphicsStroke* stroke = dynamic_cast(item->parentItem()); - - if (stroke) - { - UBGraphicsStroke* cloneStroke = groupClone.value(stroke); - - if (!cloneStroke) - { - cloneStroke = stroke->deepCopy(); - groupClone.insert(stroke, cloneStroke); - } - - polygon->setStroke(cloneStroke); - } - } - } - } - - // TODO UB 4.7 ... complete all members ? - - return copy; -} - - -UBItem* UBGraphicsScene::deepCopy() const -{ - return sceneDeepCopy(); -} - - -void UBGraphicsScene::clearItemsAndAnnotations() -{ - deselectAllItems(); - - QSet emptyList; - QSet removedItems; - - QListIterator itItems(mFastAccessItems); - - while (itItems.hasNext()) - { - QGraphicsItem* item = itItems.next(); - - if(!mTools.contains(item) && !isBackgroundObject(item)) - { - removeItem(item); - removedItems << item; - } - } - - // force refresh, QT is a bit lazy and take a lot of time (nb item ^2 ?) to trigger repaint - update(sceneRect()); - - if (enableUndoRedoStack) { //should be deleted after scene own undo stack implemented - UBGraphicsItemUndoCommand* uc = new UBGraphicsItemUndoCommand(this, removedItems, emptyList); - UBApplication::undoStack->push(uc); - } - - setDocumentUpdated(); -} - - -void UBGraphicsScene::clearItems() -{ - deselectAllItems(); - - QSet emptyList; - QSet removedItems; - - QListIterator itItems(mFastAccessItems); - - while (itItems.hasNext()) - { - QGraphicsItem* item = itItems.next(); - - if (!item->parentItem()) - { - UBGraphicsPolygonItem* pi = qgraphicsitem_cast(item); - - if(!pi && !mTools.contains(item) && !isBackgroundObject(item)) - { - removeItem(item); - removedItems << item; - } - } - } - - // force refresh, QT is a bit lazy and take a lot of time (nb item ^2 ?) to trigger repaint - update(sceneRect()); - - - if (enableUndoRedoStack) { //should be deleted after scene own undo stack implemented - UBGraphicsItemUndoCommand* uc = new UBGraphicsItemUndoCommand(this, removedItems, emptyList); - UBApplication::undoStack->push(uc); - } - - setDocumentUpdated(); -} - - -void UBGraphicsScene::clearAnnotations() -{ - QSet emptyList; - QSet removedItems; - - QListIterator itItems(mFastAccessItems); - - while (itItems.hasNext()) - { - QGraphicsItem* item = itItems.next(); - UBGraphicsPolygonItem* pi = qgraphicsitem_cast(item); - if (pi) - { - removeItem(item); - removedItems << item; - } - } - - // force refresh, QT is a bit lazy and take a lot of time (nb item ^2 ?) to trigger repaint - update(sceneRect()); - - - if (enableUndoRedoStack) { //should be deleted after scene own undo stack implemented - UBGraphicsItemUndoCommand* uc = new UBGraphicsItemUndoCommand(this, removedItems, emptyList); - UBApplication::undoStack->push(uc); - } - - setDocumentUpdated(); -} - - -UBGraphicsPixmapItem* UBGraphicsScene::addPixmap(const QPixmap& pPixmap, const QPointF& pPos, qreal pScaleFactor, bool pUseAnimation) -{ - UBGraphicsPixmapItem* pixmapItem = new UBGraphicsPixmapItem(); - - pixmapItem->setFlag(QGraphicsItem::ItemIsMovable, true); - pixmapItem->setFlag(QGraphicsItem::ItemIsSelectable, true); -// pixmapItem->setZValue(getNextObjectZIndex()); - UBGraphicsItem::assignZValue(pixmapItem, getNextObjectZIndex()); - - pixmapItem->setPixmap(pPixmap); - - QPointF half(pPixmap.width() * pScaleFactor / 2, pPixmap.height() * pScaleFactor / 2); - pixmapItem->setPos(pPos - half); - - addItem(pixmapItem); - - if (enableUndoRedoStack) { //should be deleted after scene own undo stack implemented - UBGraphicsItemUndoCommand* uc = new UBGraphicsItemUndoCommand(this, 0, pixmapItem); - UBApplication::undoStack->push(uc); - } - - pixmapItem->scale(pScaleFactor, pScaleFactor); - - if (pUseAnimation) - { - pixmapItem->setOpacity(0); - - QPropertyAnimation *animation = new QPropertyAnimation(pixmapItem, "opacity"); - animation->setDuration(1000); - animation->setStartValue(0.0); - animation->setEndValue(1.0); - - animation->start(); - } - - pixmapItem->show(); - setDocumentUpdated(); - - return pixmapItem; -} - - -void UBGraphicsScene::textUndoCommandAdded(UBGraphicsTextItem *textItem) -{ - if (enableUndoRedoStack) { //should be deleted after scene own undo stack implemented - UBGraphicsTextItemUndoCommand* uc = new UBGraphicsTextItemUndoCommand(textItem); - UBApplication::undoStack->push(uc); - } -} - - -UBGraphicsVideoItem* UBGraphicsScene::addVideo(const QUrl& pVideoFileUrl, bool shouldPlayAsap, const QPointF& pPos) -{ - UBGraphicsVideoItem* videoItem = new UBGraphicsVideoItem(pVideoFileUrl); - - videoItem->setPos(pPos); - - videoItem->setFlag(QGraphicsItem::ItemIsMovable, true); - videoItem->setFlag(QGraphicsItem::ItemIsSelectable, true); -// videoItem->setZValue(getNextObjectZIndex()); - UBGraphicsItem::assignZValue(videoItem, getNextObjectZIndex()); - - addItem(videoItem); - - videoItem->show(); - - if (enableUndoRedoStack) { //should be deleted after scene own undo stack implemented - UBGraphicsItemUndoCommand* uc = new UBGraphicsItemUndoCommand(this, 0, videoItem); - UBApplication::undoStack->push(uc); - } - - videoItem->mediaObject()->play(); - - if (!shouldPlayAsap) - { - videoItem->mediaObject()->pause(); - videoItem->mediaObject()->seek(0); - } - - setDocumentUpdated(); - - return videoItem; -} - -UBGraphicsAudioItem* UBGraphicsScene::addAudio(const QUrl& pAudioFileUrl, bool shouldPlayAsap, const QPointF& pPos) -{ - UBGraphicsAudioItem* audioItem = new UBGraphicsAudioItem(pAudioFileUrl); - - audioItem->setPos(pPos); - - audioItem->setFlag(QGraphicsItem::ItemIsMovable, true); - audioItem->setFlag(QGraphicsItem::ItemIsSelectable, true); -// audioItem->setZValue(getNextObjectZIndex()); - UBGraphicsItem::assignZValue(audioItem, getNextObjectZIndex()); - - addItem(audioItem); - - audioItem->show(); - - if (enableUndoRedoStack) { //should be deleted after scene own undo stack implemented - UBGraphicsItemUndoCommand* uc = new UBGraphicsItemUndoCommand(this, 0, audioItem); - UBApplication::undoStack->push(uc); - } - - audioItem->mediaObject()->play(); - - if (!shouldPlayAsap) - { - audioItem->mediaObject()->pause(); - audioItem->mediaObject()->seek(0); - } - - setDocumentUpdated(); - - return audioItem; -} - - -UBGraphicsWidgetItem* UBGraphicsScene::addWidget(const QUrl& pWidgetUrl, const QPointF& pPos) -{ - int widgetType = UBAbstractWidget::widgetType(pWidgetUrl); - - if(widgetType == UBWidgetType::Apple) - { - return addAppleWidget(pWidgetUrl, pPos); - } - else if(widgetType == UBWidgetType::W3C) - { - return addW3CWidget(pWidgetUrl, pPos); - } - else - { - qDebug() << "UBGraphicsScene::addWidget: Unknown widget Type"; - return 0; - } -} - - -UBGraphicsAppleWidgetItem* UBGraphicsScene::addAppleWidget(const QUrl& pWidgetUrl, const QPointF& pPos) -{ - UBGraphicsAppleWidgetItem *appleWidget = new UBGraphicsAppleWidgetItem(pWidgetUrl); - - addGraphicsWidget(appleWidget, pPos); - - return appleWidget; -} - - -UBGraphicsW3CWidgetItem* UBGraphicsScene::addW3CWidget(const QUrl& pWidgetUrl, const QPointF& pPos, int widgetType) -{ - UBGraphicsW3CWidgetItem *w3CWidget = new UBGraphicsW3CWidgetItem(pWidgetUrl, 0, widgetType); - - addGraphicsWidget(w3CWidget, pPos); - - return w3CWidget; -} - -void UBGraphicsScene::addGraphicsWidget(UBGraphicsWidgetItem* graphicsWidget, const QPointF& pPos) -{ - graphicsWidget->setFlag(QGraphicsItem::ItemIsSelectable, true); -// graphicsWidget->setZValue(getNextObjectZIndex()); - UBGraphicsItem::assignZValue(graphicsWidget, getNextObjectZIndex()); - - addItem(graphicsWidget); - - qreal ssf = 1 / UBApplication::boardController->systemScaleFactor(); - - graphicsWidget->scale(ssf, ssf); - - graphicsWidget->setPos(QPointF(pPos.x() - graphicsWidget->boundingRect().width() / 2, - pPos.y() - graphicsWidget->boundingRect().height() / 2)); - - if (graphicsWidget->widgetWebView()->canBeContent()) - { -// graphicsWidget->widgetWebView()->loadMainHtml(); - - graphicsWidget->setSelected(true); - if (enableUndoRedoStack) { //should be deleted after scene own undo stack implemented - UBGraphicsItemUndoCommand* uc = new UBGraphicsItemUndoCommand(this, 0, graphicsWidget); - UBApplication::undoStack->push(uc); - } - - setDocumentUpdated(); - } - else - { - UBApplication::boardController->moveGraphicsWidgetToControlView(graphicsWidget); - } -} - - -UBGraphicsW3CWidgetItem* UBGraphicsScene::addOEmbed(const QUrl& pContentUrl, const QPointF& pPos) -{ - QStringList widgetPaths = UBPersistenceManager::persistenceManager()->allWidgets(UBSettings::settings()->applicationApplicationsLibraryDirectory()); - - UBGraphicsW3CWidgetItem *widget = 0; - - foreach(QString widgetPath, widgetPaths) - { - if (widgetPath.contains("VideoPicker")) - { - widget = addW3CWidget(QUrl::fromLocalFile(widgetPath), pPos); - - if (widget) - { - widget->setPreference("oembedUrl", pContentUrl.toString()); - setDocumentUpdated(); - break; - } - } - } - - return widget; -} - -UBGraphicsSvgItem* UBGraphicsScene::addSvg(const QUrl& pSvgFileUrl, const QPointF& pPos) -{ - QString path = pSvgFileUrl.toLocalFile(); - - UBGraphicsSvgItem *svgItem = new UBGraphicsSvgItem(path); - - svgItem->setFlag(QGraphicsItem::ItemIsMovable, true); - svgItem->setFlag(QGraphicsItem::ItemIsSelectable, true); -// svgItem->setZValue(getNextObjectZIndex()); - UBGraphicsItem::assignZValue(svgItem, getNextObjectZIndex()); - - qreal sscale = 1 / UBApplication::boardController->systemScaleFactor(); - svgItem->scale(sscale, sscale); - - QPointF half(svgItem->boundingRect().width() / 2, svgItem->boundingRect().height() / 2); - svgItem->setPos(pPos - half); - svgItem->show(); - - addItem(svgItem); - - if (enableUndoRedoStack) { //should be deleted after scene own undo stack implemented - UBGraphicsItemUndoCommand* uc = new UBGraphicsItemUndoCommand(this, 0, svgItem); - UBApplication::undoStack->push(uc); - } - - setDocumentUpdated(); - - return svgItem; -} - - -UBGraphicsTextItem* UBGraphicsScene::addText(const QString& pString, const QPointF& pTopLeft) -{ - return addTextWithFont(pString, pTopLeft, UBSettings::settings()->fontPixelSize() - , UBSettings::settings()->fontFamily(), UBSettings::settings()->isBoldFont() - , UBSettings::settings()->isItalicFont()); -} - - -UBGraphicsTextItem* UBGraphicsScene::addTextWithFont(const QString& pString, const QPointF& pTopLeft - , int pointSize, const QString& fontFamily, bool bold, bool italic) -{ - UBGraphicsTextItem *textItem = new UBGraphicsTextItem(); - textItem->setPlainText(pString); -// textItem->setZValue(getNextObjectZIndex()); - UBGraphicsItem::assignZValue(textItem, getNextObjectZIndex()); - - QFont font = textItem->font(); - - if (fontFamily == "") - { - font = QFont(UBSettings::settings()->fontFamily()); - } - else - { - font = QFont(fontFamily); - } - - if (pointSize < 1) - { - font.setPixelSize(UBSettings::settings()->fontPixelSize()); - } - else - { - font.setPointSize(pointSize); - } - - font.setBold(bold); - font.setItalic(italic); - textItem->setFont(font); - - QFontMetrics fi(font); - QRect br = fi.boundingRect(pString); - - textItem->setTextWidth(qMax((qreal)br.width() + 50, (qreal)200)); - textItem->setTextHeight(br.height()); - - addItem(textItem); - - textItem->setPos(pTopLeft); - - textItem->show(); - - if (enableUndoRedoStack) { //should be deleted after scene own undo stack implemented - UBGraphicsItemUndoCommand* uc = new UBGraphicsItemUndoCommand(this, 0, textItem); - UBApplication::undoStack->push(uc); - } - - connect(textItem, SIGNAL(textUndoCommandAdded(UBGraphicsTextItem *)), this, SLOT(textUndoCommandAdded(UBGraphicsTextItem *))); - - textItem->setSelected(true); - textItem->setFocus(); - - setDocumentUpdated(); - - return textItem; -} -UBGraphicsTextItem *UBGraphicsScene::addTextHtml(const QString &pString, const QPointF& pTopLeft) -{ - UBGraphicsTextItem *textItem = new UBGraphicsTextItem(); - textItem->setPlainText(""); - textItem->setHtml(pString); -// textItem->setZValue(getNextObjectZIndex()); - UBGraphicsItem::assignZValue(textItem, getNextObjectZIndex()); - - addItem(textItem); - textItem->show(); - - if (enableUndoRedoStack) { //should be deleted after scene own undo stack implemented - UBGraphicsItemUndoCommand* uc = new UBGraphicsItemUndoCommand(this, 0, textItem); - UBApplication::undoStack->push(uc); - } - - connect(textItem, SIGNAL(textUndoCommandAdded(UBGraphicsTextItem *)), - this, SLOT(textUndoCommandAdded(UBGraphicsTextItem *))); - - textItem->setFocus(); - - setDocumentUpdated(); - textItem->setPos(pTopLeft); - - return textItem; -} - -void UBGraphicsScene::addItem(QGraphicsItem* item) -{ - setModified(true); - UBCoreGraphicsScene::addItem(item); - - if (!mTools.contains(item)) - ++mItemCount; - - mFastAccessItems << item; -} - -void UBGraphicsScene::addItems(const QSet& items) -{ - setModified(true); - - foreach(QGraphicsItem* item, items) - UBCoreGraphicsScene::addItem(item); - - mItemCount += items.size(); - - mFastAccessItems += items.toList(); -} - -void UBGraphicsScene::removeItem(QGraphicsItem* item) -{ - setModified(true); - UBCoreGraphicsScene::removeItem(item); - - if (!mTools.contains(item)) - --mItemCount; - - mFastAccessItems.removeAll(item); -} - - -void UBGraphicsScene::removeItems(const QSet& items) -{ - setModified(true); - - foreach(QGraphicsItem* item, items) - UBCoreGraphicsScene::removeItem(item); - - mItemCount -= items.size(); - - foreach(QGraphicsItem* item, items) - mFastAccessItems.removeAll(item); -} - - -void UBGraphicsScene::deselectAllItems() -{ - foreach(QGraphicsItem *gi, selectedItems ()) - { - gi->setSelected(false); - } -} - -bool UBGraphicsScene::isEmpty() const -{ - return mItemCount == 0; -} - -QGraphicsItem* UBGraphicsScene::setAsBackgroundObject(QGraphicsItem* item, bool pAdaptTransformation, bool pExpand) -{ - if (mBackgroundObject) - { - removeItem(mBackgroundObject); - mBackgroundObject = 0; - } - - if (item) - { - item->setFlag(QGraphicsItem::ItemIsSelectable, false); - item->setFlag(QGraphicsItem::ItemIsMovable, false); - item->setAcceptedMouseButtons(Qt::NoButton); - item->setData(UBGraphicsItemData::ItemLayerType, UBItemLayerType::FixedBackground); - -// item->setZValue(backgroundLayerStart); - UBGraphicsItem::assignZValue(item, backgroundLayerStart); - - if (pAdaptTransformation) - { - item = scaleToFitDocumentSize(item, true, 0, pExpand); - } - - if (item->scene() != this) - addItem(item); - - mBackgroundObject = item; - - } - - return item; -} - - -QRectF UBGraphicsScene::normalizedSceneRect(qreal ratio) -{ - - QRectF normalizedRect(nominalSize().width() / -2, nominalSize().height() / -2, - nominalSize().width(), nominalSize().height()); - - foreach(QGraphicsItem* gi, mFastAccessItems) - { - if(gi && gi->isVisible() && !mTools.contains(gi)) - { - normalizedRect = normalizedRect.united(gi->sceneBoundingRect()); - } - } - - if (ratio > 0.0) - { - qreal normalizedRectRatio = normalizedRect.width() / normalizedRect.height(); - - if (normalizedRectRatio > ratio) - { - //the normalized rect is too wide, we increase height - qreal newHeight = normalizedRect.width() / ratio; - qreal offset = (newHeight - normalizedRect.height()) / 2; - normalizedRect.setY(normalizedRect.y() - offset); - normalizedRect.setHeight(newHeight); - } - else if (normalizedRectRatio < ratio) - { - //the normalized rect is too high, we increase the width - qreal newWidth = normalizedRect.height() * ratio; - qreal offset = (newWidth - normalizedRect.width()) / 2; - normalizedRect.setX(normalizedRect.x() - offset); - normalizedRect.setWidth(newWidth); - } - } - - return normalizedRect; -} - - -void UBGraphicsScene::setDocument(UBDocumentProxy* pDocument) -{ - if (pDocument != mDocument) - { - if (mDocument) - { - setModified(true); - } - - mDocument = pDocument; - setParent(pDocument); - } -} - - -QGraphicsItem* UBGraphicsScene::scaleToFitDocumentSize(QGraphicsItem* item, bool center, int margin, bool expand) -{ - int maxWidth = mNominalSize.width() - (margin * 2); - int maxHeight = mNominalSize.height() - (margin * 2); - - QRectF size = item->sceneBoundingRect(); - - if (expand || size.width() > maxWidth || size.height() > maxHeight) - { - qreal ratio = qMin(maxWidth / size.width(), maxHeight / size.height()); - - item->scale(ratio, ratio); - - if(center) - { - item->setPos(item->sceneBoundingRect().width() / -2.0, - item->sceneBoundingRect().height() / -2.0); - } - } - - return item; -} - - -void UBGraphicsScene::addRuler(QPointF center) -{ - UBGraphicsRuler* ruler = new UBGraphicsRuler(); // mem : owned and destroyed by the scene - mTools << ruler; - QRectF rect = ruler->rect(); - ruler->setRect(center.x() - rect.width()/2, center.y() - rect.height()/2, rect.width(), rect.height()); - -// ruler->setZValue(toolLayerStart + toolOffsetRuler); - UBGraphicsItem::assignZValue(ruler, toolLayerStart + toolOffsetRuler); - - ruler->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Tool)); - - addItem(ruler); - - ruler->setVisible(true); - setModified(true); -} - - -void UBGraphicsScene::addProtractor(QPointF center) -{ - // Protractor - - UBGraphicsProtractor* protractor = new UBGraphicsProtractor(); // mem : owned and destroyed by the scene - mTools << protractor; - -// protractor->setZValue(toolLayerStart + toolOffsetProtractor); - UBGraphicsItem::assignZValue(protractor, toolLayerStart + toolOffsetProtractor); - - protractor->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Tool)); - - addItem(protractor); - - QPointF itemSceneCenter = protractor->sceneBoundingRect().center(); - protractor->moveBy(center.x() - itemSceneCenter.x(), center.y() - itemSceneCenter.y()); - - protractor->setVisible(true); - setModified(true); -} - -void UBGraphicsScene::addTriangle(QPointF center) -{ - // Triangle - - UBGraphicsTriangle* triangle = new UBGraphicsTriangle(); // mem : owned and destroyed by the scene - mTools << triangle; - -// triangle->setZValue(toolLayerStart + toolOffsetProtractor); - UBGraphicsItem::assignZValue(triangle, toolLayerStart + toolOffsetTriangle); - - triangle->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Tool)); - - addItem(triangle); - - QPointF itemSceneCenter = triangle->sceneBoundingRect().center(); - triangle->moveBy(center.x() - itemSceneCenter.x(), center.y() - itemSceneCenter.y()); - - triangle->setVisible(true); - setModified(true); -} - -void UBGraphicsScene::addMagnifier(UBMagnifierParams params) -{ - // can have only one magnifier at one time - if(magniferControlViewWidget) return; - - QWidget *cContainer = (QWidget*)(UBApplication::boardController->controlContainer()); - QGraphicsView *cView = (QGraphicsView*)UBApplication::boardController->controlView(); - QGraphicsView *dView = (QGraphicsView*)UBApplication::boardController->displayView(); - - QPoint dvZeroPoint = dView->mapToGlobal(QPoint(0,0)); - - int cvW = cView->width(); - int dvW = dView->width(); - qreal wCoeff = (qreal)dvW / (qreal)cvW; - - int cvH = cView->height(); - int dvH = dView->height(); - qreal hCoeff = (qreal)dvH / (qreal)cvH; - - QPoint ccPoint(params.x,params.y); - QPoint globalPoint = cContainer->mapToGlobal(ccPoint); - QPoint cvPoint = cView->mapFromGlobal(globalPoint); - QPoint dvPoint( cvPoint.x() * wCoeff + dvZeroPoint.x(), cvPoint.y() * hCoeff + dvZeroPoint.y()); - - magniferControlViewWidget = new UBMagnifier((QWidget*)(UBApplication::boardController->controlContainer()), true); - magniferControlViewWidget->setGrabView((QGraphicsView*)UBApplication::boardController->controlView()); - magniferControlViewWidget->setMoveView((QWidget*)(UBApplication::boardController->controlContainer())); - magniferControlViewWidget->setSize(params.sizePercentFromScene); - magniferControlViewWidget->setZoom(params.zoom); - - magniferDisplayViewWidget = new UBMagnifier((QWidget*)(UBApplication::boardController->displayView()), false); - magniferDisplayViewWidget->setGrabView((QGraphicsView*)UBApplication::boardController->controlView()); - magniferDisplayViewWidget->setMoveView((QGraphicsView*)UBApplication::boardController->displayView()); - magniferDisplayViewWidget->setSize(params.sizePercentFromScene); - magniferDisplayViewWidget->setZoom(params.zoom); - - magniferControlViewWidget->grabNMove(globalPoint, globalPoint, true); - magniferDisplayViewWidget->grabNMove(globalPoint, dvPoint, true); - magniferControlViewWidget->show(); - magniferDisplayViewWidget->show(); - - connect(magniferControlViewWidget, SIGNAL(magnifierMoved_Signal(QPoint)), this, SLOT(moveMagnifier(QPoint))); - connect(magniferControlViewWidget, SIGNAL(magnifierClose_Signal()), this, SLOT(closeMagnifier())); - connect(magniferControlViewWidget, SIGNAL(magnifierZoomIn_Signal()), this, SLOT(zoomInMagnifier())); - connect(magniferControlViewWidget, SIGNAL(magnifierZoomOut_Signal()), this, SLOT(zoomOutMagnifier())); - connect(magniferControlViewWidget, SIGNAL(magnifierResized_Signal(qreal)), this, SLOT(resizedMagnifier(qreal))); - - setModified(true); -} - -void UBGraphicsScene::moveMagnifier(QPoint newPos) -{ - QWidget *cContainer = (QWidget*)(UBApplication::boardController->controlContainer()); - QGraphicsView *cView = (QGraphicsView*)UBApplication::boardController->controlView(); - QGraphicsView *dView = (QGraphicsView*)UBApplication::boardController->displayView(); - - QPoint dvZeroPoint = dView->mapToGlobal(QPoint(0,0)); - - int cvW = cView->width(); - int dvW = dView->width(); - qreal wCoeff = (qreal)dvW / (qreal)cvW; - - int cvH = cView->height(); - int dvH = dView->height(); - qreal hCoeff = (qreal)dvH / (qreal)cvH; - - QPoint globalPoint = cContainer->mapToGlobal(newPos); - QPoint cvPoint = cView->mapFromGlobal(globalPoint); - QPoint dvPoint( cvPoint.x() * wCoeff + dvZeroPoint.x(), cvPoint.y() * hCoeff + dvZeroPoint.y()); - - magniferControlViewWidget->grabNMove(globalPoint, globalPoint, false, false); - magniferDisplayViewWidget->grabNMove(globalPoint, dvPoint, false, true); - - setModified(true); -} - -void UBGraphicsScene::closeMagnifier() -{ - DisposeMagnifierQWidgets(); -} - -void UBGraphicsScene::zoomInMagnifier() -{ - if(magniferControlViewWidget->params.zoom < 8) - { - magniferControlViewWidget->setZoom(magniferControlViewWidget->params.zoom + 0.5); - magniferDisplayViewWidget->setZoom(magniferDisplayViewWidget->params.zoom + 0.5); - } -} - -void UBGraphicsScene::zoomOutMagnifier() -{ - if(magniferControlViewWidget->params.zoom > 1) - { - magniferControlViewWidget->setZoom(magniferControlViewWidget->params.zoom - 0.5); - magniferDisplayViewWidget->setZoom(magniferDisplayViewWidget->params.zoom - 0.5); - } -} - -void UBGraphicsScene::resizedMagnifier(qreal newPercent) -{ - if(newPercent > 18 && newPercent < 50) - { - magniferControlViewWidget->setSize(newPercent); - magniferControlViewWidget->grabPoint(); - magniferDisplayViewWidget->setSize(newPercent); - magniferDisplayViewWidget->grabPoint(); - } -} - -void UBGraphicsScene::addCompass(QPointF center) -{ - UBGraphicsCompass* compass = new UBGraphicsCompass(); // mem : owned and destroyed by the scene - mTools << compass; - addItem(compass); - - QRectF rect = compass->rect(); - compass->setRect(center.x() - rect.width() / 2, center.y() - rect.height() / 2, rect.width(), rect.height()); - -// compass->setZValue(toolLayerStart + toolOffsetCompass); - UBGraphicsItem::assignZValue(compass, toolLayerStart + toolOffsetCompass); - - compass->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Tool)); - - compass->setVisible(true); - setModified(true); -} - -void UBGraphicsScene::addCache() -{ - UBGraphicsCache* cache = new UBGraphicsCache(); - mTools << cache; - - addItem(cache); - - cache->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Tool)); - - cache->setVisible(true); - cache->setSelected(true); - UBApplication::boardController->notifyCache(true); - UBApplication::boardController->notifyPageChanged(); -} - -void UBGraphicsScene::addMask(const QPointF ¢er) -{ - UBGraphicsCurtainItem* curtain = new UBGraphicsCurtainItem(); // mem : owned and destroyed by the scene - mTools << curtain; - - addItem(curtain); - - QRectF rect = UBApplication::boardController->activeScene()->normalizedSceneRect(); - rect.setRect(center.x() - rect.width()/4, center.y() - rect.height()/4, rect.width()/2 , rect.height()/2); - curtain->setRect(rect); - UBGraphicsItem::assignZValue(curtain, toolLayerStart + toolOffsetCurtain); - - curtain->setVisible(true); - curtain->setSelected(true); - setModified(true); -} - - -void UBGraphicsScene::setRenderingQuality(UBItem::RenderingQuality pRenderingQuality) -{ - QListIterator itItems(mFastAccessItems); - - while (itItems.hasNext()) - { - QGraphicsItem *gItem = itItems.next(); - - UBItem *ubItem = dynamic_cast(gItem); - - if (ubItem) - { - ubItem->setRenderingQuality(pRenderingQuality); - } - } -} - - -QList UBGraphicsScene::relativeDependencies() const -{ - QList relativePathes; - - QListIterator itItems(mFastAccessItems); - - while (itItems.hasNext()) - { - UBGraphicsVideoItem *videoItem = qgraphicsitem_cast (itItems.next()); - - if (videoItem && videoItem->mediaFileUrl().isRelative()) - { - relativePathes << videoItem->mediaFileUrl(); - } - } - - return relativePathes; -} - - -QSize UBGraphicsScene::nominalSize() -{ - if (mDocument && !mNominalSize.isValid()) - { - mNominalSize = mDocument->defaultDocumentSize(); - } - - return mNominalSize; -} - - -void UBGraphicsScene::setNominalSize(const QSize& pSize) -{ - if (nominalSize() != pSize) - { - mNominalSize = pSize; - emit pageSizeChanged(); - - if(mDocument) - mDocument->setDefaultDocumentSize(pSize); - - } -} - - -void UBGraphicsScene::setNominalSize(int pWidth, int pHeight) -{ - setNominalSize(QSize(pWidth, pHeight)); -} - - -QGraphicsItem* UBGraphicsScene::rootItem(QGraphicsItem* item) const -{ - QGraphicsItem* root = item; - - while (root->parentItem()) - { - root = root->parentItem(); - } - - return root; -} - - -void UBGraphicsScene::drawItems (QPainter * painter, int numItems, - QGraphicsItem * items[], const QStyleOptionGraphicsItem options[], QWidget * widget) -{ - if (mRenderingContext == NonScreen || mRenderingContext == PdfExport) - { - int count = 0; - - QGraphicsItem** itemsFiltered = new QGraphicsItem*[numItems]; - QStyleOptionGraphicsItem *optionsFiltered = new QStyleOptionGraphicsItem[numItems]; - - for (int i = 0; i < numItems; i++) - { - if (!mTools.contains(rootItem(items[i]))) - { - UBGraphicsPDFItem *pdfItem = qgraphicsitem_cast (items[i]); - if(!pdfItem || mRenderingContext == NonScreen) - { - itemsFiltered[count] = items[i]; - optionsFiltered[count] = options[i]; - count++; - } - } - } - - QGraphicsScene::drawItems(painter, count, itemsFiltered, optionsFiltered, widget); - - delete[] optionsFiltered; - delete[] itemsFiltered; - - } - else if (mRenderingContext == Podcast) - { - int count = 0; - - QGraphicsItem** itemsFiltered = new QGraphicsItem*[numItems]; - QStyleOptionGraphicsItem *optionsFiltered = new QStyleOptionGraphicsItem[numItems]; - - for (int i = 0; i < numItems; i++) - { - bool ok; - int itemLayerType = items[i]->data(UBGraphicsItemData::ItemLayerType).toInt(&ok); - if (ok && (itemLayerType >= UBItemLayerType::FixedBackground && itemLayerType <= UBItemLayerType::Tool)) - { - itemsFiltered[count] = items[i]; - optionsFiltered[count] = options[i]; - count++; - } - } - - QGraphicsScene::drawItems(painter, count, itemsFiltered, optionsFiltered, widget); - - delete[] optionsFiltered; - delete[] itemsFiltered; - - } - else - { - QGraphicsScene::drawItems(painter, numItems, items, options, widget); - } -} - - -void UBGraphicsScene::keyReleaseEvent(QKeyEvent * keyEvent) -{ - - QList si = selectedItems(); - - if ((si.size() > 0) && (keyEvent->isAccepted())) - { -#ifdef Q_OS_MAC - if (keyEvent->key() == Qt::Key_Backspace) -#else - if (keyEvent->matches(QKeySequence::Delete)) -#endif - { - foreach(QGraphicsItem* item, si) - { - switch (item->type()) - { - case UBGraphicsW3CWidgetItem::Type: - { - UBGraphicsW3CWidgetItem *wc3_widget = dynamic_cast(item); - if (0 != wc3_widget) - if (!wc3_widget->hasFocus()) - wc3_widget->remove(); - break; - } - case UBGraphicsAppleWidgetItem::Type: - { - UBGraphicsAppleWidgetItem *Apple_widget = dynamic_cast(item); - if (0 !=Apple_widget) - if (!Apple_widget->hasFocus()) - Apple_widget->remove(); - break; - } - case UBGraphicsTextItem::Type: - { - UBGraphicsTextItem *text_item = dynamic_cast(item); - if (0 != text_item) - if (!text_item->hasFocus()) - text_item->remove(); - break; - } - - default: - { - UBGraphicsItem *ubgi = dynamic_cast(item); - if (0 != ubgi) - ubgi->remove(); - else - UBCoreGraphicsScene::removeItem(item); - } - } - } - } - - keyEvent->accept(); - } - - QGraphicsScene::keyReleaseEvent(keyEvent); -} - - -void UBGraphicsScene::setDocumentUpdated() -{ - if (document()) - document()->setMetaData(UBSettings::documentUpdatedAt - , UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); -} - - -void UBGraphicsScene::setToolCursor(int tool) -{ - if (tool != (int)UBStylusTool::Selector - && tool != (int)UBStylusTool::Text) - { - deselectAllItems(); - } - - if (tool != (int)UBStylusTool::Eraser) - { - hideEraser(); - } -} +/* + * 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 "UBGraphicsScene.h" + +#include +#include +#include +#include + +#include "frameworks/UBGeometryUtils.h" +#include "frameworks/UBPlatformUtils.h" + +#include "core/UBApplication.h" +#include "core/UBSettings.h" +#include "core/UBApplicationController.h" +#include "core/UBDisplayManager.h" +#include "core/UBPersistenceManager.h" + +#include "gui/UBMagnifer.h" + +#include "tools/UBGraphicsRuler.h" +#include "tools/UBGraphicsProtractor.h" +#include "tools/UBGraphicsCompass.h" +#include "tools/UBGraphicsTriangle.h" +#include "tools/UBGraphicsCurtainItem.h" +#include "tools/UBGraphicsCache.h" + +#include "document/UBDocumentProxy.h" + +#include "board/UBBoardController.h" +#include "board/UBDrawingController.h" + +#include "UBGraphicsItemUndoCommand.h" +#include "UBGraphicsTextItemUndoCommand.h" +#include "UBGraphicsProxyWidget.h" +#include "UBGraphicsPixmapItem.h" +#include "UBGraphicsSvgItem.h" +#include "UBGraphicsPolygonItem.h" +#include "UBGraphicsVideoItem.h" +#include "UBGraphicsAudioItem.h" +#include "UBGraphicsWidgetItem.h" +#include "UBGraphicsPDFItem.h" +#include "UBGraphicsTextItem.h" + +#include "UBAppleWidget.h" +#include "UBW3CWidget.h" +#include "UBGraphicsStroke.h" + +#include "core/memcheck.h" + +qreal UBGraphicsScene::backgroundLayerStart = -20000000.0; +qreal UBGraphicsScene::objectLayerStart = -10000000.0; +qreal UBGraphicsScene::drawingLayerStart = 0.0; +qreal UBGraphicsScene::toolLayerStart = 10000000.0; + +qreal UBGraphicsScene::toolOffsetRuler = 100; +qreal UBGraphicsScene::toolOffsetProtractor = 100; +qreal UBGraphicsScene::toolOffsetTriangle = 100; +qreal UBGraphicsScene::toolOffsetCompass = 100; +qreal UBGraphicsScene::toolOffsetEraser = 200; + +qreal UBGraphicsScene::toolOffsetCurtain = 1000; +qreal UBGraphicsScene::toolOffsetPointer = 1100; + +qreal UBGraphicsScene::toolOffsetCache = 1000;//Didier please define offset you want + +UBGraphicsScene::UBGraphicsScene(UBDocumentProxy* parent) + : UBCoreGraphicsScene(parent) + , mEraser(0) + , mPointer(0) + , mDocument(parent) + , mDarkBackground(false) + , mCrossedBackground(false) + , mIsModified(true) + , mBackgroundObject(0) + , mPreviousWidth(0) + , mInputDeviceIsPressed(false) + , mArcPolygonItem(0) + , mRenderingContext(Screen) + , mCurrentStroke(0) + , mShouldUseOMP(true) + , mItemCount(0) + , enableUndoRedoStack(true) + , magniferControlViewWidget(0) + , magniferDisplayViewWidget(0) + +{ + +#ifdef __ppc__ + mShouldUseOMP = false; +#elif defined(Q_WS_MAC) + mShouldUseOMP = QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5; +#endif + + setDocument(parent); + + mDrawingZIndex = drawingLayerStart; + mObjectZIndex = objectLayerStart; + + mEraser = new QGraphicsEllipseItem(); // mem : owned and destroyed by the scene + mEraser->setRect(QRect(0, 0, 0, 0)); + mEraser->setVisible(false); + + mEraser->setZValue(/*toolLayerStart + toolOffsetEraser*/2); + mEraser->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Control)); + + mTools << mEraser; + addItem(mEraser); + + mPointer = new QGraphicsEllipseItem(); // mem : owned and destroyed by the scene + mPointer->setRect(QRect(0, 0, 20, 20)); + mPointer->setVisible(false); + + mPointer->setPen(Qt::NoPen); + mPointer->setBrush(QBrush(QColor(255, 0, 0, 186))); + + mPointer->setZValue( /*toolLayerStart + toolOffsetPointer*/ 2); + mPointer->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Tool)); + + mTools << mPointer; + addItem(mPointer); + + if (UBApplication::applicationController) + { + setViewState(SceneViewState(1, + UBApplication::applicationController->initialHScroll(), + UBApplication::applicationController->initialVScroll())); + } + + connect(this, SIGNAL(selectionChanged()), this, SLOT(selectionChangedProcessing())); +} + +UBGraphicsScene::~UBGraphicsScene() +{ + DisposeMagnifierQWidgets(); + + if (mCurrentStroke) + if (mCurrentStroke->polygons().empty()) + delete mCurrentStroke; +} + +void UBGraphicsScene::selectionChangedProcessing() +{ + if (selectedItems().count()) + UBApplication::showMessage("ZValue is " + QString::number(selectedItems().first()->zValue(), 'f')); + + + QList allItemsList = items(); + qreal maxZ = 0.; + for( int i = 0; i < allItemsList.size(); i++ ) { + QGraphicsItem *nextItem = allItemsList.at(i); + //Temporary stub. Due to ugly z-order implementation I need to do this (sankore 360) + //z-order behavior should be reimplemented and this stub should be deleted + if (nextItem == mBackgroundObject) + continue; + //Temporary stub end (sankore 360) + if (nextItem->zValue() > maxZ) + maxZ = nextItem->zValue(); + nextItem->setZValue(nextItem->data(UBGraphicsItemData::ItemOwnZValue).toReal()); +// nextItem->setZValue(qreal(1)); + } + QList selItemsList = selectedItems(); + for( int i = 0; i < selItemsList.size(); i++ ) { + QGraphicsItem *nextItem = selItemsList.at(i); + nextItem->setZValue(maxZ + 0.0001); + } +} + +// MARK: - +// MARK: Mouse/Tablet events handling + +bool UBGraphicsScene::inputDevicePress(const QPointF& scenePos, const qreal& pressure) +{ + //mMesure1Ms = 0; + //mMesure2Ms = 0; + + bool accepted = false; + + if (mInputDeviceIsPressed) + { + qWarning() << "scene received input device pressed, without input device release, muting event as input device move"; + accepted = inputDeviceMove(scenePos, pressure); + } + else + { + mInputDeviceIsPressed = true; + + UBStylusTool::Enum currentTool = (UBStylusTool::Enum)UBDrawingController::drawingController()->stylusTool(); + + if (UBDrawingController::drawingController()->isDrawingTool()) + { + qreal width = 0; + + // delete current stroke, if not assigned to any polygon + if (mCurrentStroke) + if (mCurrentStroke->polygons().empty()) + delete mCurrentStroke; + + mCurrentStroke = new UBGraphicsStroke(); + + if (currentTool != UBStylusTool::Line) + width = UBDrawingController::drawingController()->currentToolWidth() * pressure; + else + width = UBDrawingController::drawingController()->currentToolWidth(); //ignore pressure for line tool + + width /= UBApplication::boardController->systemScaleFactor(); + width /= UBApplication::boardController->currentZoom(); + + mAddedItems.clear(); + mRemovedItems.clear(); + + if (UBDrawingController::drawingController()->mActiveRuler) + { + UBDrawingController::drawingController()->mActiveRuler->StartLine( + scenePos, width); + } + else + { + moveTo(scenePos); + drawLineTo(scenePos, width, + UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Line); + } + accepted = true; + } + else if (currentTool == UBStylusTool::Eraser) + { + mAddedItems.clear(); + mRemovedItems.clear(); + moveTo(scenePos); + + qreal eraserWidth = UBSettings::settings()->currentEraserWidth(); + eraserWidth /= UBApplication::boardController->systemScaleFactor(); + eraserWidth /= UBApplication::boardController->currentZoom(); + + eraseLineTo(scenePos, eraserWidth); + drawEraser(scenePos, true); + + accepted = true; + } + else if (currentTool == UBStylusTool::Pointer) + { + drawPointer(scenePos, true); + accepted = true; + } + } + + return accepted; +} + + +bool UBGraphicsScene::inputDeviceMove(const QPointF& scenePos, const qreal& pressure) +{ + bool accepted = false; + + UBDrawingController *dc = UBDrawingController::drawingController(); + UBStylusTool::Enum currentTool = (UBStylusTool::Enum)dc->stylusTool(); + + QPointF position = QPointF(scenePos); + + if (currentTool == UBStylusTool::Eraser) + { + drawEraser(position); + accepted = true; + } + + if (mInputDeviceIsPressed) + { + if (dc->isDrawingTool()) + { + qreal width = 0; + + if (currentTool != UBStylusTool::Line) + width = dc->currentToolWidth() * pressure; + else + width = dc->currentToolWidth();//ignore pressure for line tool + + width /= UBApplication::boardController->systemScaleFactor(); + width /= UBApplication::boardController->currentZoom(); + + if (dc->mActiveRuler) + { + dc->mActiveRuler->DrawLine(position, width); + } + else + { + if (currentTool == UBStylusTool::Line) + { + // TODO: Verify this beautiful implementation and check if + // it is possible to optimize it + QLineF radius(mPreviousPoint, position); + qreal angle = radius.angle(); + angle = qRound(angle / 45) * 45; + qreal radiusLength = radius.length(); + QPointF newPosition( + mPreviousPoint.x() + radiusLength * cos((angle * PI) / 180), + mPreviousPoint.y() - radiusLength * sin((angle * PI) / 180)); + QLineF chord(position, newPosition); + if (chord.length() < qMin((int)16, (int)(radiusLength / 20))) + position = newPosition; + } + + drawLineTo(position, width, + UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Line); + } + } + else if (currentTool == UBStylusTool::Eraser) + { + qreal eraserWidth = UBSettings::settings()->currentEraserWidth(); + eraserWidth /= UBApplication::boardController->systemScaleFactor(); + eraserWidth /= UBApplication::boardController->currentZoom(); + + eraseLineTo(position, eraserWidth); + } + else if (currentTool == UBStylusTool::Pointer) + { + drawPointer(position); + } + + accepted = true; + } + + return accepted; +} + + +bool UBGraphicsScene::inputDeviceRelease() +{ + /* + if (mMesure1Ms > 0 || mMesure2Ms > 0) + { + qWarning() << "---------------------------"; + qWarning() << "mMesure1Ms: " << mMesure1Ms; + qWarning() << "mMesure2Ms: " << mMesure2Ms; + + mMesure1Ms = 0; + mMesure2Ms = 0; + } + */ + + bool accepted = false; + + + + if (mPointer) + { + mPointer->hide(); + accepted = true; + } + + UBDrawingController *dc = UBDrawingController::drawingController(); + if (dc->isDrawingTool()) + { + if (mCurrentStroke) + { + if (mCurrentStroke->polygons().empty()) + delete mCurrentStroke; + mCurrentStroke = 0; + } + } + + if (mRemovedItems.size() > 0 || mAddedItems.size() > 0) + { + + if (enableUndoRedoStack) { //should be deleted after scene own undo stack implemented + UBGraphicsItemUndoCommand* udcmd = new UBGraphicsItemUndoCommand(this, mRemovedItems, mAddedItems); //deleted by the undoStack + + if(UBApplication::undoStack) + UBApplication::undoStack->push(udcmd); + } + + mRemovedItems.clear(); + mAddedItems.clear(); + accepted = true; + } + + mInputDeviceIsPressed = false; + + setDocumentUpdated(); + + return accepted; +} + +// MARK: - + +void UBGraphicsScene::drawEraser(const QPointF &pPoint, bool isFirstDraw) +{ + qreal eraserWidth = UBSettings::settings()->currentEraserWidth(); + eraserWidth /= UBApplication::boardController->systemScaleFactor(); + eraserWidth /= UBApplication::boardController->currentZoom(); + + qreal eraserRadius = eraserWidth / 2; + + // TODO UB 4.x optimize - no need to do that every time we move it + if (mEraser) + { + mEraser->setRect(QRectF(pPoint.x() - eraserRadius, pPoint.y() - eraserRadius, eraserWidth, eraserWidth)); + + if(isFirstDraw) + { + qreal maxZ = 0.; + QList allItemsList = items(); + for( int i = 0; i < allItemsList.size(); i++ ) + { + QGraphicsItem *nextItem = allItemsList.at(i); + qreal zValue = nextItem->zValue(); + if (zValue > maxZ) + maxZ = zValue; + nextItem->setZValue(nextItem->data(UBGraphicsItemData::ItemOwnZValue).toReal()); + } + + mEraser->setZValue(maxZ + 0.0001); + mEraser->show(); + } + } +} + +void UBGraphicsScene::drawPointer(const QPointF &pPoint, bool isFirstDraw) +{ + qreal pointerDiameter = UBSettings::pointerDiameter / UBApplication::boardController->currentZoom(); + qreal pointerRadius = pointerDiameter / 2; + + // TODO UB 4.x optimize - no need to do that every time we move it + if (mPointer) + { + mPointer->setRect(QRectF(pPoint.x() - pointerRadius, + pPoint.y() - pointerRadius, + pointerDiameter, + pointerDiameter)); + + if(isFirstDraw) + { + qreal maxZ = 0.; + QList allItemsList = items(); + for( int i = 0; i < allItemsList.size(); i++ ) + { + QGraphicsItem *nextItem = allItemsList.at(i); + qreal zValue = nextItem->zValue(); + if (zValue > maxZ) + maxZ = zValue; + nextItem->setZValue(nextItem->data(UBGraphicsItemData::ItemOwnZValue).toReal()); + } + + mPointer->setZValue(maxZ + 0.0001); + mPointer->show(); + } + } +} + +// call this function when user release mouse button in Magnifier mode +void UBGraphicsScene::DisposeMagnifierQWidgets() +{ + if(magniferControlViewWidget) + { + magniferControlViewWidget->hide(); + magniferControlViewWidget->setParent(0); + delete magniferControlViewWidget; + magniferControlViewWidget = NULL; + } + + if(magniferDisplayViewWidget) + { + magniferDisplayViewWidget->hide(); + magniferDisplayViewWidget->setParent(0); + delete magniferDisplayViewWidget; + magniferDisplayViewWidget = NULL; + } + + // some time have crash here on access to app (when call from destructor when close sankore app) + // so i just add try/catch section here + try + { + UBApplication::app()->restoreOverrideCursor(); + } + catch (...) + { + } + +} + +void UBGraphicsScene::moveTo(const QPointF &pPoint) +{ + mPreviousPoint = pPoint; + mPreviousWidth = -1.0; + mPreviousPolygonItems.clear(); + mArcPolygonItem = 0; +} + + +void UBGraphicsScene::drawLineTo(const QPointF &pEndPoint, const qreal &pWidth, bool bLineStyle) +{ + if (mPreviousWidth == -1.0) + mPreviousWidth = pWidth; + + UBGraphicsPolygonItem *polygonItem = lineToPolygonItem(QLineF(mPreviousPoint, pEndPoint), pWidth); + + if (!polygonItem->brush().isOpaque()) + { + for (int i = 0; i < mPreviousPolygonItems.size(); i++) + { + UBGraphicsPolygonItem* previous = mPreviousPolygonItems.value(i); + polygonItem->subtract(previous); + } + } + + if (bLineStyle) + { + QSetIterator itItems(mAddedItems); + + while (itItems.hasNext()) + { + QGraphicsItem* item = itItems.next(); + removeItem(item); + } + mAddedItems.clear(); + } + + mAddedItems.insert(polygonItem); + + if (mCurrentStroke) + { + polygonItem->setStroke(mCurrentStroke); + } + + addItem(polygonItem); + + mPreviousPolygonItems.append(polygonItem); + + if (!bLineStyle) + { + mPreviousPoint = pEndPoint; + mPreviousWidth = pWidth; + } +} + + +void UBGraphicsScene::eraseLineTo(const QPointF &pEndPoint, const qreal &pWidth) +{ + const QLineF line(mPreviousPoint, pEndPoint); + + const QPolygonF eraserPolygon = UBGeometryUtils::lineToPolygon(line, pWidth); + const QRectF eraserBoundingRect = eraserPolygon.boundingRect(); + const QRectF eraserInnerRect = UBGeometryUtils::lineToInnerRect(line, pWidth); + + QPainterPath eraserPathVar; + eraserPathVar.addPolygon(eraserPolygon); + const QPainterPath eraserPath = eraserPathVar; + + QList collidItems = items(eraserBoundingRect, Qt::IntersectsItemBoundingRect); + + QSet toBeAddedItems; + QSet toBeRemovedItems; + + int collidItemsSize = collidItems.size(); + + toBeAddedItems.reserve(collidItemsSize); + toBeRemovedItems.reserve(collidItemsSize); + + if (mShouldUseOMP) + { +#pragma omp parallel for + for (int i = 0; i < collidItemsSize; i++) + { + UBGraphicsPolygonItem *collidingPolygonItem + = qgraphicsitem_cast (collidItems.at(i)); + + if (collidingPolygonItem) + { + if(eraserInnerRect.contains(collidingPolygonItem->boundingRect())) + { +#pragma omp critical + toBeRemovedItems << collidingPolygonItem; + } + else + { + QPolygonF collidingPolygon = collidingPolygonItem->polygon(); + QPainterPath collidingPath; + collidingPath.addPolygon(collidingPolygon); + + QPainterPath croppedPath = collidingPath.subtracted(eraserPath); + QPainterPath croppedPathSimplified = croppedPath.simplified(); + + if (croppedPath == collidingPath) + { + // NOOP + } + else if (croppedPathSimplified.isEmpty()) + { +#pragma omp critical + toBeRemovedItems << collidingPolygonItem; + } + else + { + foreach(const QPolygonF &pol, croppedPathSimplified.toFillPolygons()) + { + UBGraphicsPolygonItem* croppedPolygonItem = collidingPolygonItem->deepCopy(pol); +#pragma omp critical + toBeAddedItems << croppedPolygonItem; + } +#pragma omp critical + toBeRemovedItems << collidingPolygonItem; + } + } + } + } + } + else + { + for (int i = 0; i < collidItemsSize; i++) + { + UBGraphicsPolygonItem *collidingPolygonItem + = qgraphicsitem_cast (collidItems.at(i)); + + if (collidingPolygonItem) + { + if(eraserInnerRect.contains(collidingPolygonItem->boundingRect())) + { + toBeRemovedItems << collidingPolygonItem; + } + else + { + QPolygonF collidingPolygon = collidingPolygonItem->polygon(); + QPainterPath collidingPath; + collidingPath.addPolygon(collidingPolygon); + + QPainterPath croppedPath = collidingPath.subtracted(eraserPath); + QPainterPath croppedPathSimplified = croppedPath.simplified(); + + if (croppedPath == collidingPath) + { + // NOOP + } + else if (croppedPathSimplified.isEmpty()) + { + toBeRemovedItems << collidingPolygonItem; + } + else + { + foreach(const QPolygonF &pol, croppedPathSimplified.toFillPolygons()) + { + UBGraphicsPolygonItem* croppedPolygonItem = collidingPolygonItem->deepCopy(pol); + toBeAddedItems << croppedPolygonItem; + } + + toBeRemovedItems << collidingPolygonItem; + } + } + } + } + } + + addItems(toBeAddedItems); + mAddedItems += toBeAddedItems; + + removeItems(toBeRemovedItems); + mRemovedItems += toBeRemovedItems; + + mPreviousPoint = pEndPoint; +} + + +void UBGraphicsScene::drawArcTo(const QPointF& pCenterPoint, qreal pSpanAngle) +{ + if (mArcPolygonItem) + { + mAddedItems.remove(mArcPolygonItem); + removeItem(mArcPolygonItem); + mArcPolygonItem = 0; + } + qreal penWidth = UBSettings::settings()->currentPenWidth(); + penWidth /= UBApplication::boardController->systemScaleFactor(); + penWidth /= UBApplication::boardController->currentZoom(); + + mArcPolygonItem = arcToPolygonItem(QLineF(pCenterPoint, mPreviousPoint), pSpanAngle, penWidth); + mAddedItems.insert(mArcPolygonItem); + addItem(mArcPolygonItem); + + setDocumentUpdated(); +} + + +qreal UBGraphicsScene::getNextDrawingZIndex() +{ + mDrawingZIndex = mDrawingZIndex + 1.0; + return mDrawingZIndex; +} + + +qreal UBGraphicsScene::getNextObjectZIndex() +{ + mObjectZIndex = mObjectZIndex + 1.0; + return mObjectZIndex; +} + + +void UBGraphicsScene::setBackground(bool pIsDark, bool pIsCrossed) +{ + bool needRepaint = false; + + if (mDarkBackground != pIsDark) + { + mDarkBackground = pIsDark; + + if (mEraser) + { + if (mDarkBackground) + { + mEraser->setBrush(UBSettings::eraserBrushDarkBackground); + mEraser->setPen(UBSettings::eraserPenDarkBackground); + } + else + { + mEraser->setBrush(UBSettings::eraserBrushLightBackground); + mEraser->setPen(UBSettings::eraserPenLightBackground); + } + } + + recolorAllItems(); + + needRepaint = true; + setModified(true); + } + + if (mCrossedBackground != pIsCrossed) + { + mCrossedBackground = pIsCrossed; + needRepaint = true; + setModified(true); + } + + if (needRepaint) + { + foreach(QGraphicsView* view, views()) + { + view->resetCachedContent(); + } + } +} + + +void UBGraphicsScene::recolorAllItems() +{ + QMap previousUpdateModes; + foreach(QGraphicsView* view, views()) + { + previousUpdateModes.insert(view, view->viewportUpdateMode()); + view->setViewportUpdateMode(QGraphicsView::NoViewportUpdate); + } + + for(int i = 0; i < mFastAccessItems.size(); i++) + { + UBGraphicsPolygonItem *polygonItem = qgraphicsitem_cast (mFastAccessItems.at(i)); + + if (polygonItem) + { + QColor color; + + if (mDarkBackground) + { + color = polygonItem->colorOnDarkBackground(); + } + else + { + color = polygonItem->colorOnLightBackground(); + } + + polygonItem->setColor(color); + continue; + } + } + + foreach(QGraphicsView* view, views()) + { + view->setViewportUpdateMode(previousUpdateModes.value(view)); + } +} + + +UBGraphicsPolygonItem* UBGraphicsScene::lineToPolygonItem(const QLineF &pLine, const qreal &pWidth) +{ + UBGraphicsPolygonItem *polygonItem = new UBGraphicsPolygonItem(pLine, pWidth); + + initPolygonItem(polygonItem); + + return polygonItem; +} + + +void UBGraphicsScene::initPolygonItem(UBGraphicsPolygonItem* polygonItem) +{ + QColor colorOnDarkBG; + QColor colorOnLightBG; + + if (UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Marker) + { + colorOnDarkBG = UBApplication::boardController->markerColorOnDarkBackground(); + colorOnLightBG = UBApplication::boardController->markerColorOnLightBackground(); + } + else // settings->stylusTool() == UBStylusTool::Pen + failsafe + { + colorOnDarkBG = UBApplication::boardController->penColorOnDarkBackground(); + colorOnLightBG = UBApplication::boardController->penColorOnLightBackground(); + } + + if (mDarkBackground) + { + polygonItem->setColor(colorOnDarkBG); + } + else + { + polygonItem->setColor(colorOnLightBG); + } + + polygonItem->setColorOnDarkBackground(colorOnDarkBG); + polygonItem->setColorOnLightBackground(colorOnLightBG); + + polygonItem->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Graphic)); + +// polygonItem->setZValue(getNextDrawingZIndex()); + UBGraphicsItem::assignZValue(polygonItem, getNextDrawingZIndex()); +} + + +UBGraphicsPolygonItem* UBGraphicsScene::arcToPolygonItem(const QLineF& pStartRadius, qreal pSpanAngle, qreal pWidth) +{ + QPolygonF polygon = UBGeometryUtils::arcToPolygon(pStartRadius, pSpanAngle, pWidth); + + return polygonToPolygonItem(polygon); +} + + +UBGraphicsPolygonItem* UBGraphicsScene::polygonToPolygonItem(const QPolygonF pPolygon) +{ + UBGraphicsPolygonItem *polygonItem = new UBGraphicsPolygonItem(pPolygon); + + initPolygonItem(polygonItem); + + return polygonItem; +} + + +void UBGraphicsScene::hideEraser() +{ + if (mEraser) + mEraser->hide(); +} + + +void UBGraphicsScene::leaveEvent(QEvent * event) +{ + Q_UNUSED(event); + hideEraser(); +} + + +UBGraphicsScene* UBGraphicsScene::sceneDeepCopy() const +{ + UBGraphicsScene* copy = new UBGraphicsScene(this->document()); + + copy->setBackground(this->isDarkBackground(), this->isCrossedBackground()); + + copy->mDrawingZIndex = this->mDrawingZIndex; + copy->mObjectZIndex = this->mObjectZIndex; + copy->setSceneRect(this->sceneRect()); + + if (this->mNominalSize.isValid()) + copy->setNominalSize(this->mNominalSize); + + QListIterator itItems(this->mFastAccessItems); + + QMap groupClone; + + while (itItems.hasNext()) + { + QGraphicsItem* item = itItems.next(); + QGraphicsItem* cloneItem = 0; + + UBItem* ubItem = dynamic_cast(item); + UBGraphicsStroke* stroke = dynamic_cast(item); + + if (ubItem && !stroke) + { + cloneItem = dynamic_cast(ubItem->deepCopy()); + } + + if (cloneItem) + { + copy->addItem(cloneItem); + + if (isBackgroundObject(item)) + { + copy->setAsBackgroundObject(cloneItem); + } + + if (this->mTools.contains(item)) + { + copy->mTools << cloneItem; + } + + UBGraphicsPolygonItem* polygon = dynamic_cast(item); + + if(polygon) + { + UBGraphicsStroke* stroke = dynamic_cast(item->parentItem()); + + if (stroke) + { + UBGraphicsStroke* cloneStroke = groupClone.value(stroke); + + if (!cloneStroke) + { + cloneStroke = stroke->deepCopy(); + groupClone.insert(stroke, cloneStroke); + } + + polygon->setStroke(cloneStroke); + } + } + } + } + + // TODO UB 4.7 ... complete all members ? + + return copy; +} + + +UBItem* UBGraphicsScene::deepCopy() const +{ + return sceneDeepCopy(); +} + + +void UBGraphicsScene::clearItemsAndAnnotations() +{ + deselectAllItems(); + + QSet emptyList; + QSet removedItems; + + QListIterator itItems(mFastAccessItems); + + while (itItems.hasNext()) + { + QGraphicsItem* item = itItems.next(); + + if(!mTools.contains(item) && !isBackgroundObject(item)) + { + removeItem(item); + removedItems << item; + } + } + + // force refresh, QT is a bit lazy and take a lot of time (nb item ^2 ?) to trigger repaint + update(sceneRect()); + + if (enableUndoRedoStack) { //should be deleted after scene own undo stack implemented + UBGraphicsItemUndoCommand* uc = new UBGraphicsItemUndoCommand(this, removedItems, emptyList); + UBApplication::undoStack->push(uc); + } + + setDocumentUpdated(); +} + + +void UBGraphicsScene::clearItems() +{ + deselectAllItems(); + + QSet emptyList; + QSet removedItems; + + QListIterator itItems(mFastAccessItems); + + while (itItems.hasNext()) + { + QGraphicsItem* item = itItems.next(); + + if (!item->parentItem()) + { + UBGraphicsPolygonItem* pi = qgraphicsitem_cast(item); + + if(!pi && !mTools.contains(item) && !isBackgroundObject(item)) + { + removeItem(item); + removedItems << item; + } + } + } + + // force refresh, QT is a bit lazy and take a lot of time (nb item ^2 ?) to trigger repaint + update(sceneRect()); + + + if (enableUndoRedoStack) { //should be deleted after scene own undo stack implemented + UBGraphicsItemUndoCommand* uc = new UBGraphicsItemUndoCommand(this, removedItems, emptyList); + UBApplication::undoStack->push(uc); + } + + setDocumentUpdated(); +} + + +void UBGraphicsScene::clearAnnotations() +{ + QSet emptyList; + QSet removedItems; + + QListIterator itItems(mFastAccessItems); + + while (itItems.hasNext()) + { + QGraphicsItem* item = itItems.next(); + UBGraphicsPolygonItem* pi = qgraphicsitem_cast(item); + if (pi) + { + removeItem(item); + removedItems << item; + } + } + + // force refresh, QT is a bit lazy and take a lot of time (nb item ^2 ?) to trigger repaint + update(sceneRect()); + + + if (enableUndoRedoStack) { //should be deleted after scene own undo stack implemented + UBGraphicsItemUndoCommand* uc = new UBGraphicsItemUndoCommand(this, removedItems, emptyList); + UBApplication::undoStack->push(uc); + } + + setDocumentUpdated(); +} + + +UBGraphicsPixmapItem* UBGraphicsScene::addPixmap(const QPixmap& pPixmap, const QPointF& pPos, qreal pScaleFactor, bool pUseAnimation) +{ + UBGraphicsPixmapItem* pixmapItem = new UBGraphicsPixmapItem(); + + pixmapItem->setFlag(QGraphicsItem::ItemIsMovable, true); + pixmapItem->setFlag(QGraphicsItem::ItemIsSelectable, true); +// pixmapItem->setZValue(getNextObjectZIndex()); + UBGraphicsItem::assignZValue(pixmapItem, getNextObjectZIndex()); + + pixmapItem->setPixmap(pPixmap); + + QPointF half(pPixmap.width() * pScaleFactor / 2, pPixmap.height() * pScaleFactor / 2); + pixmapItem->setPos(pPos - half); + + addItem(pixmapItem); + + if (enableUndoRedoStack) { //should be deleted after scene own undo stack implemented + UBGraphicsItemUndoCommand* uc = new UBGraphicsItemUndoCommand(this, 0, pixmapItem); + UBApplication::undoStack->push(uc); + } + + pixmapItem->scale(pScaleFactor, pScaleFactor); + + if (pUseAnimation) + { + pixmapItem->setOpacity(0); + + QPropertyAnimation *animation = new QPropertyAnimation(pixmapItem, "opacity"); + animation->setDuration(1000); + animation->setStartValue(0.0); + animation->setEndValue(1.0); + + animation->start(); + } + + pixmapItem->show(); + setDocumentUpdated(); + + return pixmapItem; +} + + +void UBGraphicsScene::textUndoCommandAdded(UBGraphicsTextItem *textItem) +{ + if (enableUndoRedoStack) { //should be deleted after scene own undo stack implemented + UBGraphicsTextItemUndoCommand* uc = new UBGraphicsTextItemUndoCommand(textItem); + UBApplication::undoStack->push(uc); + } +} + + +UBGraphicsVideoItem* UBGraphicsScene::addVideo(const QUrl& pVideoFileUrl, bool shouldPlayAsap, const QPointF& pPos) +{ + UBGraphicsVideoItem* videoItem = new UBGraphicsVideoItem(pVideoFileUrl); + + videoItem->setPos(pPos); + + videoItem->setFlag(QGraphicsItem::ItemIsMovable, true); + videoItem->setFlag(QGraphicsItem::ItemIsSelectable, true); +// videoItem->setZValue(getNextObjectZIndex()); + UBGraphicsItem::assignZValue(videoItem, getNextObjectZIndex()); + + addItem(videoItem); + + videoItem->show(); + + if (enableUndoRedoStack) { //should be deleted after scene own undo stack implemented + UBGraphicsItemUndoCommand* uc = new UBGraphicsItemUndoCommand(this, 0, videoItem); + UBApplication::undoStack->push(uc); + } + + videoItem->mediaObject()->play(); + + if (!shouldPlayAsap) + { + videoItem->mediaObject()->pause(); + videoItem->mediaObject()->seek(0); + } + + setDocumentUpdated(); + + return videoItem; +} + +UBGraphicsAudioItem* UBGraphicsScene::addAudio(const QUrl& pAudioFileUrl, bool shouldPlayAsap, const QPointF& pPos) +{ + UBGraphicsAudioItem* audioItem = new UBGraphicsAudioItem(pAudioFileUrl); + + audioItem->setPos(pPos); + + audioItem->setFlag(QGraphicsItem::ItemIsMovable, true); + audioItem->setFlag(QGraphicsItem::ItemIsSelectable, true); +// audioItem->setZValue(getNextObjectZIndex()); + UBGraphicsItem::assignZValue(audioItem, getNextObjectZIndex()); + + addItem(audioItem); + + audioItem->show(); + + if (enableUndoRedoStack) { //should be deleted after scene own undo stack implemented + UBGraphicsItemUndoCommand* uc = new UBGraphicsItemUndoCommand(this, 0, audioItem); + UBApplication::undoStack->push(uc); + } + + audioItem->mediaObject()->play(); + + if (!shouldPlayAsap) + { + audioItem->mediaObject()->pause(); + audioItem->mediaObject()->seek(0); + } + + setDocumentUpdated(); + + return audioItem; +} + + +UBGraphicsWidgetItem* UBGraphicsScene::addWidget(const QUrl& pWidgetUrl, const QPointF& pPos) +{ + int widgetType = UBAbstractWidget::widgetType(pWidgetUrl); + + if(widgetType == UBWidgetType::Apple) + { + return addAppleWidget(pWidgetUrl, pPos); + } + else if(widgetType == UBWidgetType::W3C) + { + return addW3CWidget(pWidgetUrl, pPos); + } + else + { + qDebug() << "UBGraphicsScene::addWidget: Unknown widget Type"; + return 0; + } +} + + +UBGraphicsAppleWidgetItem* UBGraphicsScene::addAppleWidget(const QUrl& pWidgetUrl, const QPointF& pPos) +{ + UBGraphicsAppleWidgetItem *appleWidget = new UBGraphicsAppleWidgetItem(pWidgetUrl); + + addGraphicsWidget(appleWidget, pPos); + + return appleWidget; +} + + +UBGraphicsW3CWidgetItem* UBGraphicsScene::addW3CWidget(const QUrl& pWidgetUrl, const QPointF& pPos, int widgetType) +{ + UBGraphicsW3CWidgetItem *w3CWidget = new UBGraphicsW3CWidgetItem(pWidgetUrl, 0, widgetType); + + addGraphicsWidget(w3CWidget, pPos); + + return w3CWidget; +} + +void UBGraphicsScene::addGraphicsWidget(UBGraphicsWidgetItem* graphicsWidget, const QPointF& pPos) +{ + graphicsWidget->setFlag(QGraphicsItem::ItemIsSelectable, true); +// graphicsWidget->setZValue(getNextObjectZIndex()); + UBGraphicsItem::assignZValue(graphicsWidget, getNextObjectZIndex()); + + addItem(graphicsWidget); + + qreal ssf = 1 / UBApplication::boardController->systemScaleFactor(); + + graphicsWidget->scale(ssf, ssf); + + graphicsWidget->setPos(QPointF(pPos.x() - graphicsWidget->boundingRect().width() / 2, + pPos.y() - graphicsWidget->boundingRect().height() / 2)); + + if (graphicsWidget->widgetWebView()->canBeContent()) + { +// graphicsWidget->widgetWebView()->loadMainHtml(); + + graphicsWidget->setSelected(true); + if (enableUndoRedoStack) { //should be deleted after scene own undo stack implemented + UBGraphicsItemUndoCommand* uc = new UBGraphicsItemUndoCommand(this, 0, graphicsWidget); + UBApplication::undoStack->push(uc); + } + + setDocumentUpdated(); + } + else + { + UBApplication::boardController->moveGraphicsWidgetToControlView(graphicsWidget); + } +} + + +UBGraphicsW3CWidgetItem* UBGraphicsScene::addOEmbed(const QUrl& pContentUrl, const QPointF& pPos) +{ + QStringList widgetPaths = UBPersistenceManager::persistenceManager()->allWidgets(UBSettings::settings()->applicationApplicationsLibraryDirectory()); + + UBGraphicsW3CWidgetItem *widget = 0; + + foreach(QString widgetPath, widgetPaths) + { + if (widgetPath.contains("VideoPicker")) + { + widget = addW3CWidget(QUrl::fromLocalFile(widgetPath), pPos); + + if (widget) + { + widget->setPreference("oembedUrl", pContentUrl.toString()); + setDocumentUpdated(); + break; + } + } + } + + return widget; +} + +UBGraphicsSvgItem* UBGraphicsScene::addSvg(const QUrl& pSvgFileUrl, const QPointF& pPos) +{ + QString path = pSvgFileUrl.toLocalFile(); + + UBGraphicsSvgItem *svgItem = new UBGraphicsSvgItem(path); + + svgItem->setFlag(QGraphicsItem::ItemIsMovable, true); + svgItem->setFlag(QGraphicsItem::ItemIsSelectable, true); +// svgItem->setZValue(getNextObjectZIndex()); + UBGraphicsItem::assignZValue(svgItem, getNextObjectZIndex()); + + qreal sscale = 1 / UBApplication::boardController->systemScaleFactor(); + svgItem->scale(sscale, sscale); + + QPointF half(svgItem->boundingRect().width() / 2, svgItem->boundingRect().height() / 2); + svgItem->setPos(pPos - half); + svgItem->show(); + + addItem(svgItem); + + if (enableUndoRedoStack) { //should be deleted after scene own undo stack implemented + UBGraphicsItemUndoCommand* uc = new UBGraphicsItemUndoCommand(this, 0, svgItem); + UBApplication::undoStack->push(uc); + } + + setDocumentUpdated(); + + return svgItem; +} + + +UBGraphicsTextItem* UBGraphicsScene::addText(const QString& pString, const QPointF& pTopLeft) +{ + return addTextWithFont(pString, pTopLeft, UBSettings::settings()->fontPixelSize() + , UBSettings::settings()->fontFamily(), UBSettings::settings()->isBoldFont() + , UBSettings::settings()->isItalicFont()); +} + + +UBGraphicsTextItem* UBGraphicsScene::addTextWithFont(const QString& pString, const QPointF& pTopLeft + , int pointSize, const QString& fontFamily, bool bold, bool italic) +{ + UBGraphicsTextItem *textItem = new UBGraphicsTextItem(); + textItem->setPlainText(pString); +// textItem->setZValue(getNextObjectZIndex()); + UBGraphicsItem::assignZValue(textItem, getNextObjectZIndex()); + + QFont font = textItem->font(); + + if (fontFamily == "") + { + font = QFont(UBSettings::settings()->fontFamily()); + } + else + { + font = QFont(fontFamily); + } + + if (pointSize < 1) + { + font.setPixelSize(UBSettings::settings()->fontPixelSize()); + } + else + { + font.setPointSize(pointSize); + } + + font.setBold(bold); + font.setItalic(italic); + textItem->setFont(font); + + QFontMetrics fi(font); + QRect br = fi.boundingRect(pString); + + textItem->setTextWidth(qMax((qreal)br.width() + 50, (qreal)200)); + textItem->setTextHeight(br.height()); + + addItem(textItem); + + textItem->setPos(pTopLeft); + + textItem->show(); + + if (enableUndoRedoStack) { //should be deleted after scene own undo stack implemented + UBGraphicsItemUndoCommand* uc = new UBGraphicsItemUndoCommand(this, 0, textItem); + UBApplication::undoStack->push(uc); + } + + connect(textItem, SIGNAL(textUndoCommandAdded(UBGraphicsTextItem *)), this, SLOT(textUndoCommandAdded(UBGraphicsTextItem *))); + + textItem->setSelected(true); + textItem->setFocus(); + + setDocumentUpdated(); + + return textItem; +} +UBGraphicsTextItem *UBGraphicsScene::addTextHtml(const QString &pString, const QPointF& pTopLeft) +{ + UBGraphicsTextItem *textItem = new UBGraphicsTextItem(); + textItem->setPlainText(""); + textItem->setHtml(pString); +// textItem->setZValue(getNextObjectZIndex()); + UBGraphicsItem::assignZValue(textItem, getNextObjectZIndex()); + + addItem(textItem); + textItem->show(); + + if (enableUndoRedoStack) { //should be deleted after scene own undo stack implemented + UBGraphicsItemUndoCommand* uc = new UBGraphicsItemUndoCommand(this, 0, textItem); + UBApplication::undoStack->push(uc); + } + + connect(textItem, SIGNAL(textUndoCommandAdded(UBGraphicsTextItem *)), + this, SLOT(textUndoCommandAdded(UBGraphicsTextItem *))); + + textItem->setFocus(); + + setDocumentUpdated(); + textItem->setPos(pTopLeft); + + return textItem; +} + +void UBGraphicsScene::addItem(QGraphicsItem* item) +{ + setModified(true); + UBCoreGraphicsScene::addItem(item); + + if (!mTools.contains(item)) + ++mItemCount; + + mFastAccessItems << item; +} + +void UBGraphicsScene::addItems(const QSet& items) +{ + setModified(true); + + foreach(QGraphicsItem* item, items) + UBCoreGraphicsScene::addItem(item); + + mItemCount += items.size(); + + mFastAccessItems += items.toList(); +} + +void UBGraphicsScene::removeItem(QGraphicsItem* item) +{ + setModified(true); + UBCoreGraphicsScene::removeItem(item); + + if (!mTools.contains(item)) + --mItemCount; + + mFastAccessItems.removeAll(item); +} + + +void UBGraphicsScene::removeItems(const QSet& items) +{ + setModified(true); + + foreach(QGraphicsItem* item, items) + UBCoreGraphicsScene::removeItem(item); + + mItemCount -= items.size(); + + foreach(QGraphicsItem* item, items) + mFastAccessItems.removeAll(item); +} + + +void UBGraphicsScene::deselectAllItems() +{ + foreach(QGraphicsItem *gi, selectedItems ()) + { + gi->setSelected(false); + } +} + +bool UBGraphicsScene::isEmpty() const +{ + return mItemCount == 0; +} + +QGraphicsItem* UBGraphicsScene::setAsBackgroundObject(QGraphicsItem* item, bool pAdaptTransformation, bool pExpand) +{ + if (mBackgroundObject) + { + removeItem(mBackgroundObject); + mBackgroundObject = 0; + } + + if (item) + { + item->setFlag(QGraphicsItem::ItemIsSelectable, false); + item->setFlag(QGraphicsItem::ItemIsMovable, false); + item->setAcceptedMouseButtons(Qt::NoButton); + item->setData(UBGraphicsItemData::ItemLayerType, UBItemLayerType::FixedBackground); + +// item->setZValue(backgroundLayerStart); + UBGraphicsItem::assignZValue(item, backgroundLayerStart); + + if (pAdaptTransformation) + { + item = scaleToFitDocumentSize(item, true, 0, pExpand); + } + + if (item->scene() != this) + addItem(item); + + mBackgroundObject = item; + + } + + return item; +} + + +QRectF UBGraphicsScene::normalizedSceneRect(qreal ratio) +{ + + QRectF normalizedRect(nominalSize().width() / -2, nominalSize().height() / -2, + nominalSize().width(), nominalSize().height()); + + foreach(QGraphicsItem* gi, mFastAccessItems) + { + if(gi && gi->isVisible() && !mTools.contains(gi)) + { + normalizedRect = normalizedRect.united(gi->sceneBoundingRect()); + } + } + + if (ratio > 0.0) + { + qreal normalizedRectRatio = normalizedRect.width() / normalizedRect.height(); + + if (normalizedRectRatio > ratio) + { + //the normalized rect is too wide, we increase height + qreal newHeight = normalizedRect.width() / ratio; + qreal offset = (newHeight - normalizedRect.height()) / 2; + normalizedRect.setY(normalizedRect.y() - offset); + normalizedRect.setHeight(newHeight); + } + else if (normalizedRectRatio < ratio) + { + //the normalized rect is too high, we increase the width + qreal newWidth = normalizedRect.height() * ratio; + qreal offset = (newWidth - normalizedRect.width()) / 2; + normalizedRect.setX(normalizedRect.x() - offset); + normalizedRect.setWidth(newWidth); + } + } + + return normalizedRect; +} + + +void UBGraphicsScene::setDocument(UBDocumentProxy* pDocument) +{ + if (pDocument != mDocument) + { + if (mDocument) + { + setModified(true); + } + + mDocument = pDocument; + setParent(pDocument); + } +} + + +QGraphicsItem* UBGraphicsScene::scaleToFitDocumentSize(QGraphicsItem* item, bool center, int margin, bool expand) +{ + int maxWidth = mNominalSize.width() - (margin * 2); + int maxHeight = mNominalSize.height() - (margin * 2); + + QRectF size = item->sceneBoundingRect(); + + if (expand || size.width() > maxWidth || size.height() > maxHeight) + { + qreal ratio = qMin(maxWidth / size.width(), maxHeight / size.height()); + + item->scale(ratio, ratio); + + if(center) + { + item->setPos(item->sceneBoundingRect().width() / -2.0, + item->sceneBoundingRect().height() / -2.0); + } + } + + return item; +} + + +void UBGraphicsScene::addRuler(QPointF center) +{ + UBGraphicsRuler* ruler = new UBGraphicsRuler(); // mem : owned and destroyed by the scene + mTools << ruler; + QRectF rect = ruler->rect(); + ruler->setRect(center.x() - rect.width()/2, center.y() - rect.height()/2, rect.width(), rect.height()); + +// ruler->setZValue(toolLayerStart + toolOffsetRuler); + UBGraphicsItem::assignZValue(ruler, toolLayerStart + toolOffsetRuler); + + ruler->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Tool)); + + addItem(ruler); + + ruler->setVisible(true); + setModified(true); +} + + +void UBGraphicsScene::addProtractor(QPointF center) +{ + // Protractor + + UBGraphicsProtractor* protractor = new UBGraphicsProtractor(); // mem : owned and destroyed by the scene + mTools << protractor; + +// protractor->setZValue(toolLayerStart + toolOffsetProtractor); + UBGraphicsItem::assignZValue(protractor, toolLayerStart + toolOffsetProtractor); + + protractor->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Tool)); + + addItem(protractor); + + QPointF itemSceneCenter = protractor->sceneBoundingRect().center(); + protractor->moveBy(center.x() - itemSceneCenter.x(), center.y() - itemSceneCenter.y()); + + protractor->setVisible(true); + setModified(true); +} + +void UBGraphicsScene::addTriangle(QPointF center) +{ + // Triangle + + UBGraphicsTriangle* triangle = new UBGraphicsTriangle(); // mem : owned and destroyed by the scene + mTools << triangle; + +// triangle->setZValue(toolLayerStart + toolOffsetProtractor); + UBGraphicsItem::assignZValue(triangle, toolLayerStart + toolOffsetTriangle); + + triangle->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Tool)); + + addItem(triangle); + + QPointF itemSceneCenter = triangle->sceneBoundingRect().center(); + triangle->moveBy(center.x() - itemSceneCenter.x(), center.y() - itemSceneCenter.y()); + + triangle->setVisible(true); + setModified(true); +} + +void UBGraphicsScene::addMagnifier(UBMagnifierParams params) +{ + // can have only one magnifier at one time + if(magniferControlViewWidget) return; + + QWidget *cContainer = (QWidget*)(UBApplication::boardController->controlContainer()); + QGraphicsView *cView = (QGraphicsView*)UBApplication::boardController->controlView(); + QGraphicsView *dView = (QGraphicsView*)UBApplication::boardController->displayView(); + + QPoint dvZeroPoint = dView->mapToGlobal(QPoint(0,0)); + + int cvW = cView->width(); + int dvW = dView->width(); + qreal wCoeff = (qreal)dvW / (qreal)cvW; + + int cvH = cView->height(); + int dvH = dView->height(); + qreal hCoeff = (qreal)dvH / (qreal)cvH; + + QPoint ccPoint(params.x,params.y); + QPoint globalPoint = cContainer->mapToGlobal(ccPoint); + QPoint cvPoint = cView->mapFromGlobal(globalPoint); + QPoint dvPoint( cvPoint.x() * wCoeff + dvZeroPoint.x(), cvPoint.y() * hCoeff + dvZeroPoint.y()); + + magniferControlViewWidget = new UBMagnifier((QWidget*)(UBApplication::boardController->controlContainer()), true); + magniferControlViewWidget->setGrabView((QGraphicsView*)UBApplication::boardController->controlView()); + magniferControlViewWidget->setMoveView((QWidget*)(UBApplication::boardController->controlContainer())); + magniferControlViewWidget->setSize(params.sizePercentFromScene); + magniferControlViewWidget->setZoom(params.zoom); + + magniferDisplayViewWidget = new UBMagnifier((QWidget*)(UBApplication::boardController->displayView()), false); + magniferDisplayViewWidget->setGrabView((QGraphicsView*)UBApplication::boardController->controlView()); + magniferDisplayViewWidget->setMoveView((QGraphicsView*)UBApplication::boardController->displayView()); + magniferDisplayViewWidget->setSize(params.sizePercentFromScene); + magniferDisplayViewWidget->setZoom(params.zoom); + + magniferControlViewWidget->grabNMove(globalPoint, globalPoint, true); + magniferDisplayViewWidget->grabNMove(globalPoint, dvPoint, true); + magniferControlViewWidget->show(); + magniferDisplayViewWidget->show(); + + connect(magniferControlViewWidget, SIGNAL(magnifierMoved_Signal(QPoint)), this, SLOT(moveMagnifier(QPoint))); + connect(magniferControlViewWidget, SIGNAL(magnifierClose_Signal()), this, SLOT(closeMagnifier())); + connect(magniferControlViewWidget, SIGNAL(magnifierZoomIn_Signal()), this, SLOT(zoomInMagnifier())); + connect(magniferControlViewWidget, SIGNAL(magnifierZoomOut_Signal()), this, SLOT(zoomOutMagnifier())); + connect(magniferControlViewWidget, SIGNAL(magnifierResized_Signal(qreal)), this, SLOT(resizedMagnifier(qreal))); + + setModified(true); +} + +void UBGraphicsScene::moveMagnifier(QPoint newPos) +{ + QWidget *cContainer = (QWidget*)(UBApplication::boardController->controlContainer()); + QGraphicsView *cView = (QGraphicsView*)UBApplication::boardController->controlView(); + QGraphicsView *dView = (QGraphicsView*)UBApplication::boardController->displayView(); + + QPoint dvZeroPoint = dView->mapToGlobal(QPoint(0,0)); + + int cvW = cView->width(); + int dvW = dView->width(); + qreal wCoeff = (qreal)dvW / (qreal)cvW; + + int cvH = cView->height(); + int dvH = dView->height(); + qreal hCoeff = (qreal)dvH / (qreal)cvH; + + QPoint globalPoint = cContainer->mapToGlobal(newPos); + QPoint cvPoint = cView->mapFromGlobal(globalPoint); + QPoint dvPoint( cvPoint.x() * wCoeff + dvZeroPoint.x(), cvPoint.y() * hCoeff + dvZeroPoint.y()); + + magniferControlViewWidget->grabNMove(globalPoint, globalPoint, false, false); + magniferDisplayViewWidget->grabNMove(globalPoint, dvPoint, false, true); + + setModified(true); +} + +void UBGraphicsScene::closeMagnifier() +{ + DisposeMagnifierQWidgets(); +} + +void UBGraphicsScene::zoomInMagnifier() +{ + if(magniferControlViewWidget->params.zoom < 8) + { + magniferControlViewWidget->setZoom(magniferControlViewWidget->params.zoom + 0.5); + magniferDisplayViewWidget->setZoom(magniferDisplayViewWidget->params.zoom + 0.5); + } +} + +void UBGraphicsScene::zoomOutMagnifier() +{ + if(magniferControlViewWidget->params.zoom > 1) + { + magniferControlViewWidget->setZoom(magniferControlViewWidget->params.zoom - 0.5); + magniferDisplayViewWidget->setZoom(magniferDisplayViewWidget->params.zoom - 0.5); + } +} + +void UBGraphicsScene::resizedMagnifier(qreal newPercent) +{ + if(newPercent > 18 && newPercent < 50) + { + magniferControlViewWidget->setSize(newPercent); + magniferControlViewWidget->grabPoint(); + magniferDisplayViewWidget->setSize(newPercent); + magniferDisplayViewWidget->grabPoint(); + } +} + +void UBGraphicsScene::addCompass(QPointF center) +{ + UBGraphicsCompass* compass = new UBGraphicsCompass(); // mem : owned and destroyed by the scene + mTools << compass; + addItem(compass); + + QRectF rect = compass->rect(); + compass->setRect(center.x() - rect.width() / 2, center.y() - rect.height() / 2, rect.width(), rect.height()); + +// compass->setZValue(toolLayerStart + toolOffsetCompass); + UBGraphicsItem::assignZValue(compass, toolLayerStart + toolOffsetCompass); + + compass->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Tool)); + + compass->setVisible(true); + setModified(true); +} + +void UBGraphicsScene::addCache() +{ + UBGraphicsCache* cache = new UBGraphicsCache(); + mTools << cache; + + addItem(cache); + + cache->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Tool)); + + cache->setVisible(true); + cache->setSelected(true); + UBApplication::boardController->notifyCache(true); + UBApplication::boardController->notifyPageChanged(); +} + +void UBGraphicsScene::addMask(const QPointF ¢er) +{ + UBGraphicsCurtainItem* curtain = new UBGraphicsCurtainItem(); // mem : owned and destroyed by the scene + mTools << curtain; + + addItem(curtain); + + QRectF rect = UBApplication::boardController->activeScene()->normalizedSceneRect(); + rect.setRect(center.x() - rect.width()/4, center.y() - rect.height()/4, rect.width()/2 , rect.height()/2); + curtain->setRect(rect); + UBGraphicsItem::assignZValue(curtain, toolLayerStart + toolOffsetCurtain); + + curtain->setVisible(true); + curtain->setSelected(true); + setModified(true); +} + + +void UBGraphicsScene::setRenderingQuality(UBItem::RenderingQuality pRenderingQuality) +{ + QListIterator itItems(mFastAccessItems); + + while (itItems.hasNext()) + { + QGraphicsItem *gItem = itItems.next(); + + UBItem *ubItem = dynamic_cast(gItem); + + if (ubItem) + { + ubItem->setRenderingQuality(pRenderingQuality); + } + } +} + + +QList UBGraphicsScene::relativeDependencies() const +{ + QList relativePathes; + + QListIterator itItems(mFastAccessItems); + + while (itItems.hasNext()) + { + UBGraphicsVideoItem *videoItem = qgraphicsitem_cast (itItems.next()); + + if (videoItem && videoItem->mediaFileUrl().isRelative()) + { + relativePathes << videoItem->mediaFileUrl(); + } + } + + return relativePathes; +} + + +QSize UBGraphicsScene::nominalSize() +{ + if (mDocument && !mNominalSize.isValid()) + { + mNominalSize = mDocument->defaultDocumentSize(); + } + + return mNominalSize; +} + + +void UBGraphicsScene::setNominalSize(const QSize& pSize) +{ + if (nominalSize() != pSize) + { + mNominalSize = pSize; + emit pageSizeChanged(); + + if(mDocument) + mDocument->setDefaultDocumentSize(pSize); + + } +} + + +void UBGraphicsScene::setNominalSize(int pWidth, int pHeight) +{ + setNominalSize(QSize(pWidth, pHeight)); +} + + +QGraphicsItem* UBGraphicsScene::rootItem(QGraphicsItem* item) const +{ + QGraphicsItem* root = item; + + while (root->parentItem()) + { + root = root->parentItem(); + } + + return root; +} + + +void UBGraphicsScene::drawItems (QPainter * painter, int numItems, + QGraphicsItem * items[], const QStyleOptionGraphicsItem options[], QWidget * widget) +{ + if (mRenderingContext == NonScreen || mRenderingContext == PdfExport) + { + int count = 0; + + QGraphicsItem** itemsFiltered = new QGraphicsItem*[numItems]; + QStyleOptionGraphicsItem *optionsFiltered = new QStyleOptionGraphicsItem[numItems]; + + for (int i = 0; i < numItems; i++) + { + if (!mTools.contains(rootItem(items[i]))) + { + UBGraphicsPDFItem *pdfItem = qgraphicsitem_cast (items[i]); + if(!pdfItem || mRenderingContext == NonScreen) + { + itemsFiltered[count] = items[i]; + optionsFiltered[count] = options[i]; + count++; + } + } + } + + QGraphicsScene::drawItems(painter, count, itemsFiltered, optionsFiltered, widget); + + delete[] optionsFiltered; + delete[] itemsFiltered; + + } + else if (mRenderingContext == Podcast) + { + int count = 0; + + QGraphicsItem** itemsFiltered = new QGraphicsItem*[numItems]; + QStyleOptionGraphicsItem *optionsFiltered = new QStyleOptionGraphicsItem[numItems]; + + for (int i = 0; i < numItems; i++) + { + bool ok; + int itemLayerType = items[i]->data(UBGraphicsItemData::ItemLayerType).toInt(&ok); + if (ok && (itemLayerType >= UBItemLayerType::FixedBackground && itemLayerType <= UBItemLayerType::Tool)) + { + itemsFiltered[count] = items[i]; + optionsFiltered[count] = options[i]; + count++; + } + } + + QGraphicsScene::drawItems(painter, count, itemsFiltered, optionsFiltered, widget); + + delete[] optionsFiltered; + delete[] itemsFiltered; + + } + else + { + QGraphicsScene::drawItems(painter, numItems, items, options, widget); + } +} + + +void UBGraphicsScene::keyReleaseEvent(QKeyEvent * keyEvent) +{ + + QList si = selectedItems(); + + if ((si.size() > 0) && (keyEvent->isAccepted())) + { +#ifdef Q_OS_MAC + if (keyEvent->key() == Qt::Key_Backspace) +#else + if (keyEvent->matches(QKeySequence::Delete)) +#endif + { + foreach(QGraphicsItem* item, si) + { + switch (item->type()) + { + case UBGraphicsW3CWidgetItem::Type: + { + UBGraphicsW3CWidgetItem *wc3_widget = dynamic_cast(item); + if (0 != wc3_widget) + if (!wc3_widget->hasFocus()) + wc3_widget->remove(); + break; + } + case UBGraphicsAppleWidgetItem::Type: + { + UBGraphicsAppleWidgetItem *Apple_widget = dynamic_cast(item); + if (0 !=Apple_widget) + if (!Apple_widget->hasFocus()) + Apple_widget->remove(); + break; + } + case UBGraphicsTextItem::Type: + { + UBGraphicsTextItem *text_item = dynamic_cast(item); + if (0 != text_item) + if (!text_item->hasFocus()) + text_item->remove(); + break; + } + + default: + { + UBGraphicsItem *ubgi = dynamic_cast(item); + if (0 != ubgi) + ubgi->remove(); + else + UBCoreGraphicsScene::removeItem(item); + } + } + } + } + + keyEvent->accept(); + } + + QGraphicsScene::keyReleaseEvent(keyEvent); +} + + +void UBGraphicsScene::setDocumentUpdated() +{ + if (document()) + document()->setMetaData(UBSettings::documentUpdatedAt + , UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); +} + + +void UBGraphicsScene::setToolCursor(int tool) +{ + if (tool != (int)UBStylusTool::Selector + && tool != (int)UBStylusTool::Text) + { + deselectAllItems(); + } + + if (tool != (int)UBStylusTool::Eraser) + { + hideEraser(); + } +} diff --git a/src/domain/UBGraphicsScene.h b/src/domain/UBGraphicsScene.h index 26f8355c..446bfb93 100644 --- a/src/domain/UBGraphicsScene.h +++ b/src/domain/UBGraphicsScene.h @@ -1,377 +1,382 @@ -/* - * 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 UBGRAPHICSSCENE_H_ -#define UBGRAPHICSSCENE_H_ - -#include - -#include "frameworks/UBCoreGraphicsScene.h" - -#include "core/UB.h" - -#include "UBItem.h" -#include "tools/UBGraphicsCurtainItem.h" - - -class UBGraphicsPixmapItem; -class UBGraphicsProxyWidget; -class UBGraphicsSvgItem; -class UBGraphicsPolygonItem; -class UBGraphicsVideoItem; -class UBGraphicsAudioItem; -class UBGraphicsWidgetItem; -class UBGraphicsW3CWidgetItem; -class UBGraphicsAppleWidgetItem; -class UBGraphicsPDFItem; -class UBGraphicsTextItem; -class UBGraphicsRuler; -class UBGraphicsProtractor; -class UBGraphicsCompass; -class UBAbstractWidget; -class UBDocumentProxy; -class UBGraphicsCurtainItem; -class UBGraphicsStroke; -class UBMagnifierParams; -class UBMagnifier; -class UBGraphicsCache; - -const double PI = 4.0 * atan(1.0); - -class UBGraphicsScene: public UBCoreGraphicsScene, public UBItem -{ - Q_OBJECT - - public: - // tmp stub for divide addings scene objects from undo mechanism implementation - void setURStackEnable(bool set = true) {enableUndoRedoStack = set;} - - UBGraphicsScene(UBDocumentProxy *parent); - virtual ~UBGraphicsScene(); - - virtual UBItem* deepCopy() const; - - UBGraphicsScene* sceneDeepCopy() const; - - void clearItemsAndAnnotations(); - void clearItems(); - void clearAnnotations(); - - bool inputDevicePress(const QPointF& scenePos, const qreal& pressure = 1.0); - bool inputDeviceMove(const QPointF& scenePos, const qreal& pressure = 1.0); - bool inputDeviceRelease(); - - void leaveEvent (QEvent* event); - - void addItem(QGraphicsItem* item); - void removeItem(QGraphicsItem* item); - - void addItems(const QSet& item); - void removeItems(const QSet& item); - - UBGraphicsWidgetItem* addWidget(const QUrl& pWidgetUrl, const QPointF& pPos = QPointF(0, 0)); - UBGraphicsAppleWidgetItem* addAppleWidget(const QUrl& pWidgetUrl, const QPointF& pPos = QPointF(0, 0)); - UBGraphicsW3CWidgetItem* addW3CWidget(const QUrl& pWidgetUrl, const QPointF& pPos = QPointF(0, 0),int widgetType = UBGraphicsItemType::W3CWidgetItemType); - void addGraphicsWidget(UBGraphicsWidgetItem* graphicsWidget, const QPointF& pPos = QPointF(0, 0)); - - UBGraphicsVideoItem* addVideo(const QUrl& pVideoFileUrl, bool shouldPlayAsap, const QPointF& pPos = QPointF(0, 0)); - UBGraphicsAudioItem* addAudio(const QUrl& pAudioFileUrl, bool shouldPlayAsap, const QPointF& pPos = QPointF(0, 0)); - UBGraphicsSvgItem* addSvg(const QUrl& pSvgFileUrl, const QPointF& pPos = QPointF(0, 0)); - UBGraphicsTextItem* addText(const QString& pString, const QPointF& pTopLeft = QPointF(0, 0)); - - UBGraphicsTextItem* addTextWithFont(const QString& pString, const QPointF& pTopLeft = QPointF(0, 0) - , int pointSize = -1, const QString& fontFamily = "", bool bold = false, bool italic = false); - UBGraphicsTextItem* addTextHtml(const QString &pString = QString(), const QPointF& pTopLeft = QPointF(0, 0)); - - UBGraphicsW3CWidgetItem* addOEmbed(const QUrl& pContentUrl, const QPointF& pPos = QPointF(0, 0)); - - QGraphicsItem* setAsBackgroundObject(QGraphicsItem* item, bool pAdaptTransformation = false, bool expand = false); - - QGraphicsItem* backgroundObject() const - { - return mBackgroundObject; - } - - bool isBackgroundObject(const QGraphicsItem* item) const - { - return item == mBackgroundObject; - } - - QGraphicsItem* scaleToFitDocumentSize(QGraphicsItem* item, bool center = false, int margin = 0, bool expand = false); - - QRectF normalizedSceneRect(qreal ratio = -1.0); - - void moveTo(const QPointF& pPoint); - void drawLineTo(const QPointF& pEndPoint, const qreal& pWidth, bool bLineStyle); - void eraseLineTo(const QPointF& pEndPoint, const qreal& pWidth); - void drawArcTo(const QPointF& pCenterPoint, qreal pSpanAngle); - - bool isEmpty() const; - - bool isModified() const - { - return mIsModified; - } - - void setModified(bool pModified) - { - mIsModified = pModified; - } - - void setDocument(UBDocumentProxy* pDocument); - - UBDocumentProxy* document() const - { - return mDocument; - } - - bool isDarkBackground() const - { - return mDarkBackground; - } - - bool isLightBackground() const - { - return !mDarkBackground; - } - - bool isCrossedBackground() const - { - return mCrossedBackground; - } - - void setDrawingZIndex(qreal pDrawingZIndex) - { - mDrawingZIndex = pDrawingZIndex; - } - - void setObjectZIndex(qreal pObjectZIndex) - { - mObjectZIndex = pObjectZIndex; - } - - bool hasBackground() - { - return (mBackgroundObject != 0); - } - - qreal getNextObjectZIndex(); - - void addRuler(QPointF center); - void addProtractor(QPointF center); - void addCompass(QPointF center); - void addTriangle(QPointF center); - void addMagnifier(UBMagnifierParams params); - - void addMask(const QPointF ¢er = QPointF()); - void addCache(); - - class SceneViewState - { - public: - SceneViewState() - { - zoomFactor = 1; - horizontalPosition = 0; - verticalPostition = 0; - } - - SceneViewState(qreal pZoomFactor, int pHorizontalPosition, int pVerticalPostition) - { - zoomFactor = pZoomFactor; - horizontalPosition = pHorizontalPosition; - verticalPostition = pVerticalPostition; - } - - qreal zoomFactor; - int horizontalPosition; - int verticalPostition; - }; - - SceneViewState viewState() const - { - return mViewState; - } - - void setViewState(const SceneViewState& pViewState) - { - mViewState = pViewState; - } - - virtual void setRenderingQuality(UBItem::RenderingQuality pRenderingQuality); - - QList relativeDependencies() const; - - QSize nominalSize(); - - void setNominalSize(const QSize& pSize); - - void setNominalSize(int pWidth, int pHeight); - - qreal currentObjectZIndex() - { - return mObjectZIndex; - } - - enum RenderingContext - { - Screen = 0, NonScreen, PdfExport, Podcast - }; - - void setRenderingContext(RenderingContext pRenderingContext) - { - mRenderingContext = pRenderingContext; - } - - RenderingContext renderingContext() const - { - return mRenderingContext; - } - - static qreal backgroundLayerStart; - static qreal objectLayerStart; - static qreal drawingLayerStart; - static qreal toolLayerStart; - - static qreal toolOffsetEraser; - static qreal toolOffsetPointer; - static qreal toolOffsetRuler; - static qreal toolOffsetProtractor; - static qreal toolOffsetCompass; - static qreal toolOffsetCurtain; - static qreal toolOffsetTriangle; - static qreal toolOffsetCache; - - QSet tools(){ return mTools;} - - void registerTool(QGraphicsItem* item) - { - mTools << item; - } - - const QPointF& previousPoint() - { - return mPreviousPoint; - } - - public slots: - - void hideEraser(); - - void setBackground(bool pIsDark, bool pIsCrossed); - - void deselectAllItems(); - - UBGraphicsPixmapItem* addPixmap(const QPixmap& pPixmap, const QPointF& pPos = QPointF(0,0), qreal scaleFactor = 1.0, bool pUseAnimation = false); - - void textUndoCommandAdded(UBGraphicsTextItem *textItem); - - void setToolCursor(int tool); - - void selectionChangedProcessing(); - - void moveMagnifier(QPoint newPos); - void closeMagnifier(); - void zoomInMagnifier(); - void zoomOutMagnifier(); - void resizedMagnifier(qreal newPercent); - - signals: - - void pageSizeChanged(); - - protected: - - UBGraphicsPolygonItem* lineToPolygonItem(const QLineF& pLine, const qreal& pWidth); - UBGraphicsPolygonItem* arcToPolygonItem(const QLineF& pStartRadius, qreal pSpanAngle, qreal pWidth); - UBGraphicsPolygonItem* polygonToPolygonItem(const QPolygonF pPolygon); - - void initPolygonItem(UBGraphicsPolygonItem*); - - void drawEraser(const QPointF& pEndPoint, bool isFirstDraw = false); - void drawPointer(const QPointF& pEndPoint, bool isFirstDraw = false); - void DisposeMagnifierQWidgets(); - - - virtual void keyReleaseEvent(QKeyEvent * keyEvent); - - void recolorAllItems(); - - qreal getNextDrawingZIndex(); - - virtual void drawItems (QPainter * painter, int numItems, - QGraphicsItem * items[], const QStyleOptionGraphicsItem options[], QWidget * widget = 0); - - QGraphicsItem* rootItem(QGraphicsItem* item) const; - - private: - void setDocumentUpdated(); - - qreal mDrawingZIndex; - qreal mObjectZIndex; - - QGraphicsEllipseItem* mEraser; - QGraphicsEllipseItem* mPointer; - - QSet mAddedItems; - QSet mRemovedItems; - - UBDocumentProxy* mDocument; - - bool mDarkBackground; - bool mCrossedBackground; - - bool mIsModified; - - QGraphicsItem* mBackgroundObject; - - QPointF mPreviousPoint; - qreal mPreviousWidth; - - QList mPreviousPolygonItems; - - SceneViewState mViewState; - - bool mInputDeviceIsPressed; - - QSet mTools; - - UBGraphicsPolygonItem *mArcPolygonItem; - - QSize mNominalSize; - - RenderingContext mRenderingContext; - - UBGraphicsStroke* mCurrentStroke; - - bool mShouldUseOMP; - - int mItemCount; - - QList mFastAccessItems; // a local copy as QGraphicsScene::items() is very slow in Qt 4.6 - - //int mMesure1Ms, mMesure2Ms; - - bool mHasCache; - // tmp stub for divide addings scene objects from undo mechanism implementation - bool enableUndoRedoStack; - - UBMagnifier *magniferControlViewWidget; - UBMagnifier *magniferDisplayViewWidget; - - -}; - -#endif /* UBGRAPHICSSCENE_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 UBGRAPHICSSCENE_H_ +#define UBGRAPHICSSCENE_H_ + +#include + +#include "frameworks/UBCoreGraphicsScene.h" + +#include "core/UB.h" + +#include "UBItem.h" +#include "tools/UBGraphicsCurtainItem.h" + + +class UBGraphicsPixmapItem; +class UBGraphicsProxyWidget; +class UBGraphicsSvgItem; +class UBGraphicsPolygonItem; +class UBGraphicsVideoItem; +class UBGraphicsAudioItem; +class UBGraphicsWidgetItem; +class UBGraphicsW3CWidgetItem; +class UBGraphicsAppleWidgetItem; +class UBGraphicsPDFItem; +class UBGraphicsTextItem; +class UBGraphicsRuler; +class UBGraphicsProtractor; +class UBGraphicsCompass; +class UBAbstractWidget; +class UBDocumentProxy; +class UBGraphicsCurtainItem; +class UBGraphicsStroke; +class UBMagnifierParams; +class UBMagnifier; +class UBGraphicsCache; + +const double PI = 4.0 * atan(1.0); + +class UBGraphicsScene: public UBCoreGraphicsScene, public UBItem +{ + Q_OBJECT + + public: + // tmp stub for divide addings scene objects from undo mechanism implementation + void setURStackEnable(bool set = true) {enableUndoRedoStack = set;} + + UBGraphicsScene(UBDocumentProxy *parent); + virtual ~UBGraphicsScene(); + + virtual UBItem* deepCopy() const; + + UBGraphicsScene* sceneDeepCopy() const; + + void clearItemsAndAnnotations(); + void clearItems(); + void clearAnnotations(); + + bool inputDevicePress(const QPointF& scenePos, const qreal& pressure = 1.0); + bool inputDeviceMove(const QPointF& scenePos, const qreal& pressure = 1.0); + bool inputDeviceRelease(); + + void leaveEvent (QEvent* event); + + void addItem(QGraphicsItem* item); + void removeItem(QGraphicsItem* item); + + void addItems(const QSet& item); + void removeItems(const QSet& item); + + UBGraphicsWidgetItem* addWidget(const QUrl& pWidgetUrl, const QPointF& pPos = QPointF(0, 0)); + UBGraphicsAppleWidgetItem* addAppleWidget(const QUrl& pWidgetUrl, const QPointF& pPos = QPointF(0, 0)); + UBGraphicsW3CWidgetItem* addW3CWidget(const QUrl& pWidgetUrl, const QPointF& pPos = QPointF(0, 0),int widgetType = UBGraphicsItemType::W3CWidgetItemType); + void addGraphicsWidget(UBGraphicsWidgetItem* graphicsWidget, const QPointF& pPos = QPointF(0, 0)); + + UBGraphicsVideoItem* addVideo(const QUrl& pVideoFileUrl, bool shouldPlayAsap, const QPointF& pPos = QPointF(0, 0)); + UBGraphicsAudioItem* addAudio(const QUrl& pAudioFileUrl, bool shouldPlayAsap, const QPointF& pPos = QPointF(0, 0)); + UBGraphicsSvgItem* addSvg(const QUrl& pSvgFileUrl, const QPointF& pPos = QPointF(0, 0)); + UBGraphicsTextItem* addText(const QString& pString, const QPointF& pTopLeft = QPointF(0, 0)); + + UBGraphicsTextItem* addTextWithFont(const QString& pString, const QPointF& pTopLeft = QPointF(0, 0) + , int pointSize = -1, const QString& fontFamily = "", bool bold = false, bool italic = false); + UBGraphicsTextItem* addTextHtml(const QString &pString = QString(), const QPointF& pTopLeft = QPointF(0, 0)); + + UBGraphicsW3CWidgetItem* addOEmbed(const QUrl& pContentUrl, const QPointF& pPos = QPointF(0, 0)); + + QGraphicsItem* setAsBackgroundObject(QGraphicsItem* item, bool pAdaptTransformation = false, bool expand = false); + + QGraphicsItem* backgroundObject() const + { + return mBackgroundObject; + } + + bool isBackgroundObject(const QGraphicsItem* item) const + { + return item == mBackgroundObject; + } + + QGraphicsItem* scaleToFitDocumentSize(QGraphicsItem* item, bool center = false, int margin = 0, bool expand = false); + + QRectF normalizedSceneRect(qreal ratio = -1.0); + + void moveTo(const QPointF& pPoint); + void drawLineTo(const QPointF& pEndPoint, const qreal& pWidth, bool bLineStyle); + void eraseLineTo(const QPointF& pEndPoint, const qreal& pWidth); + void drawArcTo(const QPointF& pCenterPoint, qreal pSpanAngle); + + bool isEmpty() const; + + bool isModified() const + { + return mIsModified; + } + + void setModified(bool pModified) + { + mIsModified = pModified; + } + + void setDocument(UBDocumentProxy* pDocument); + + UBDocumentProxy* document() const + { + return mDocument; + } + + bool isDarkBackground() const + { + return mDarkBackground; + } + + bool isLightBackground() const + { + return !mDarkBackground; + } + + bool isCrossedBackground() const + { + return mCrossedBackground; + } + + void setDrawingZIndex(qreal pDrawingZIndex) + { + mDrawingZIndex = pDrawingZIndex; + } + + void setObjectZIndex(qreal pObjectZIndex) + { + mObjectZIndex = pObjectZIndex; + } + + bool hasBackground() + { + return (mBackgroundObject != 0); + } + + qreal getNextObjectZIndex(); + + void addRuler(QPointF center); + void addProtractor(QPointF center); + void addCompass(QPointF center); + void addTriangle(QPointF center); + void addMagnifier(UBMagnifierParams params); + + void addMask(const QPointF ¢er = QPointF()); + void addCache(); + + QList getFastAccessItems() + { + return mFastAccessItems; + } + + class SceneViewState + { + public: + SceneViewState() + { + zoomFactor = 1; + horizontalPosition = 0; + verticalPostition = 0; + } + + SceneViewState(qreal pZoomFactor, int pHorizontalPosition, int pVerticalPostition) + { + zoomFactor = pZoomFactor; + horizontalPosition = pHorizontalPosition; + verticalPostition = pVerticalPostition; + } + + qreal zoomFactor; + int horizontalPosition; + int verticalPostition; + }; + + SceneViewState viewState() const + { + return mViewState; + } + + void setViewState(const SceneViewState& pViewState) + { + mViewState = pViewState; + } + + virtual void setRenderingQuality(UBItem::RenderingQuality pRenderingQuality); + + QList relativeDependencies() const; + + QSize nominalSize(); + + void setNominalSize(const QSize& pSize); + + void setNominalSize(int pWidth, int pHeight); + + qreal currentObjectZIndex() + { + return mObjectZIndex; + } + + enum RenderingContext + { + Screen = 0, NonScreen, PdfExport, Podcast + }; + + void setRenderingContext(RenderingContext pRenderingContext) + { + mRenderingContext = pRenderingContext; + } + + RenderingContext renderingContext() const + { + return mRenderingContext; + } + + static qreal backgroundLayerStart; + static qreal objectLayerStart; + static qreal drawingLayerStart; + static qreal toolLayerStart; + + static qreal toolOffsetEraser; + static qreal toolOffsetPointer; + static qreal toolOffsetRuler; + static qreal toolOffsetProtractor; + static qreal toolOffsetCompass; + static qreal toolOffsetCurtain; + static qreal toolOffsetTriangle; + static qreal toolOffsetCache; + + QSet tools(){ return mTools;} + + void registerTool(QGraphicsItem* item) + { + mTools << item; + } + + const QPointF& previousPoint() + { + return mPreviousPoint; + } + + public slots: + + void hideEraser(); + + void setBackground(bool pIsDark, bool pIsCrossed); + + void deselectAllItems(); + + UBGraphicsPixmapItem* addPixmap(const QPixmap& pPixmap, const QPointF& pPos = QPointF(0,0), qreal scaleFactor = 1.0, bool pUseAnimation = false); + + void textUndoCommandAdded(UBGraphicsTextItem *textItem); + + void setToolCursor(int tool); + + void selectionChangedProcessing(); + + void moveMagnifier(QPoint newPos); + void closeMagnifier(); + void zoomInMagnifier(); + void zoomOutMagnifier(); + void resizedMagnifier(qreal newPercent); + + signals: + + void pageSizeChanged(); + + protected: + + UBGraphicsPolygonItem* lineToPolygonItem(const QLineF& pLine, const qreal& pWidth); + UBGraphicsPolygonItem* arcToPolygonItem(const QLineF& pStartRadius, qreal pSpanAngle, qreal pWidth); + UBGraphicsPolygonItem* polygonToPolygonItem(const QPolygonF pPolygon); + + void initPolygonItem(UBGraphicsPolygonItem*); + + void drawEraser(const QPointF& pEndPoint, bool isFirstDraw = false); + void drawPointer(const QPointF& pEndPoint, bool isFirstDraw = false); + void DisposeMagnifierQWidgets(); + + + virtual void keyReleaseEvent(QKeyEvent * keyEvent); + + void recolorAllItems(); + + qreal getNextDrawingZIndex(); + + virtual void drawItems (QPainter * painter, int numItems, + QGraphicsItem * items[], const QStyleOptionGraphicsItem options[], QWidget * widget = 0); + + QGraphicsItem* rootItem(QGraphicsItem* item) const; + + private: + void setDocumentUpdated(); + + qreal mDrawingZIndex; + qreal mObjectZIndex; + + QGraphicsEllipseItem* mEraser; + QGraphicsEllipseItem* mPointer; + + QSet mAddedItems; + QSet mRemovedItems; + + UBDocumentProxy* mDocument; + + bool mDarkBackground; + bool mCrossedBackground; + + bool mIsModified; + + QGraphicsItem* mBackgroundObject; + + QPointF mPreviousPoint; + qreal mPreviousWidth; + + QList mPreviousPolygonItems; + + SceneViewState mViewState; + + bool mInputDeviceIsPressed; + + QSet mTools; + + UBGraphicsPolygonItem *mArcPolygonItem; + + QSize mNominalSize; + + RenderingContext mRenderingContext; + + UBGraphicsStroke* mCurrentStroke; + + bool mShouldUseOMP; + + int mItemCount; + + QList mFastAccessItems; // a local copy as QGraphicsScene::items() is very slow in Qt 4.6 + + //int mMesure1Ms, mMesure2Ms; + + bool mHasCache; + // tmp stub for divide addings scene objects from undo mechanism implementation + bool enableUndoRedoStack; + + UBMagnifier *magniferControlViewWidget; + UBMagnifier *magniferDisplayViewWidget; + + +}; + +#endif /* UBGRAPHICSSCENE_H_ */