/*
* 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();
mActiveScene->setBackgroundZoomFactor(mControlView->transform().m11());
}
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);
mActiveScene->setBackgroundZoomFactor(mControlView->transform().m11());
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);
mActiveScene->setBackgroundZoomFactor(mControlView->transform().m11());}
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)
{
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)
{
UBGraphicsW3CWidgetItem* item_casted = dynamic_cast(item);
if (0 == item_casted)
return;
if (freeze) {
item_casted->widgetWebView()->page()->mainFrame()->setContent(UBW3CWidget::freezedWidgetPage().toAscii());
} else
item_casted->widgetWebView()->loadMainHtml();
}
}