diff --git a/OpenBoard.pro b/OpenBoard.pro index e0c661ac..8973cae4 100644 --- a/OpenBoard.pro +++ b/OpenBoard.pro @@ -40,6 +40,7 @@ QT += webkitwidgets QT += multimediawidgets QT += printsupport QT += core +QT += concurrent INCLUDEPATH += src diff --git a/release_scripts/linux/package.sh b/release_scripts/linux/package.sh index ce2e8f70..25d07230 100755 --- a/release_scripts/linux/package.sh +++ b/release_scripts/linux/package.sh @@ -215,6 +215,7 @@ if $BUNDLE_QT; then notifyProgress "Copying and stripping Qt libraries" mkdir -p $QT_LIBRARY_DEST_PATH + copyQtLibrary libQt5Concurrent copyQtLibrary libQt5Core copyQtLibrary libQt5DBus copyQtLibrary libQt5Gui diff --git a/src/core/UBApplicationController.cpp b/src/core/UBApplicationController.cpp index 27f558c5..27c5d75b 100644 --- a/src/core/UBApplicationController.cpp +++ b/src/core/UBApplicationController.cpp @@ -465,6 +465,7 @@ void UBApplicationController::showDesktop(bool dontSwitchFrontProcess) if (mMirror) { QRect rect = qApp->desktop()->screenGeometry(desktopWidgetIndex); + rect.moveTo(0, 0); mMirror->setSourceRect(rect); } diff --git a/src/core/UBDisplayManager.cpp b/src/core/UBDisplayManager.cpp index f24e9211..4256379d 100644 --- a/src/core/UBDisplayManager.cpp +++ b/src/core/UBDisplayManager.cpp @@ -236,7 +236,7 @@ void UBDisplayManager::positionScreens() if (mDisplayWidget && mDisplayScreenIndex > -1) { - mDisplayWidget->hide(); + mDisplayWidget->showNormal(); mDisplayWidget->setGeometry(mDesktop->screenGeometry(mDisplayScreenIndex)); UBPlatformUtils::showFullScreen(mDisplayWidget); } diff --git a/src/core/UBDocumentManager.cpp b/src/core/UBDocumentManager.cpp index 40ab420c..f451e519 100644 --- a/src/core/UBDocumentManager.cpp +++ b/src/core/UBDocumentManager.cpp @@ -286,8 +286,6 @@ int UBDocumentManager::addFilesToDocument(UBDocumentProxy* document, QStringList UBGraphicsScene* scene = UBPersistenceManager::persistenceManager()->createDocumentSceneAt(document, pageIndex); importAdaptor->placeImportedItemToScene(scene, page); UBPersistenceManager::persistenceManager()->persistDocumentScene(document, scene, pageIndex); - if (UBApplication::documentController->selectedDocument() == UBApplication::boardController->selectedDocument()) - UBApplication::boardController->insertThumbPage(pageIndex); } UBPersistenceManager::persistenceManager()->persistDocumentMetadata(document); diff --git a/src/core/UBPersistenceManager.cpp b/src/core/UBPersistenceManager.cpp index b2e26cca..e826a7ba 100644 --- a/src/core/UBPersistenceManager.cpp +++ b/src/core/UBPersistenceManager.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include "frameworks/UBPlatformUtils.h" #include "frameworks/UBFileSystemUtils.h" @@ -98,7 +99,6 @@ UBPersistenceManager::UBPersistenceManager(QObject *pParent) mDocumentTreeStructureModel = new UBDocumentTreeModel(this); createDocumentProxiesStructure(); - emit proxyListChanged(); } @@ -123,6 +123,50 @@ UBPersistenceManager::~UBPersistenceManager() { } +void UBPersistenceManager::createDocumentProxiesStructure(const QFileInfoList &contentInfoList, bool interactive) +{ + // Create a QFutureWatcher and connect signals and slots. + QFutureWatcher futureWatcher; + QObject::connect(&futureWatcher, &QFutureWatcher::finished, &mProgress, &QProgressDialog::reset); + QObject::connect(&futureWatcher, &QFutureWatcher::progressRangeChanged, &mProgress, &QProgressDialog::setRange); + QObject::connect(&futureWatcher, &QFutureWatcher::progressValueChanged, &mProgress, &QProgressDialog::setValue); + + // Start the computation. + std::function createDocumentProxyLambda = [=](QFileInfo contentInfo) { + return createDocumentProxyStructure(contentInfo); + }; + + QFuture proxiesFuture = QtConcurrent::mapped(contentInfoList, createDocumentProxyLambda); + futureWatcher.setFuture(proxiesFuture); + + // Display the dialog and start the event loop. + mProgress.exec(); + + futureWatcher.waitForFinished(); + + QList proxies = futureWatcher.future().results(); + + for (auto&& proxy : qAsConst(proxies)) + { + if (proxy) + { + QString docGroupName = proxy->metaData(UBSettings::documentGroupName).toString(); + QModelIndex parentIndex = mDocumentTreeStructureModel->goTo(docGroupName); + if (parentIndex.isValid()) + { + if (!interactive) + mDocumentTreeStructureModel->addDocument(proxy, parentIndex); + else + processInteractiveReplacementDialog(proxy); + } + else + { + qDebug() << "something went wrong"; + } + } + } +} + void UBPersistenceManager::createDocumentProxiesStructure(bool interactive) { mDocumentRepositoryPath = UBSettings::userDocumentDirectory(); @@ -130,8 +174,13 @@ void UBPersistenceManager::createDocumentProxiesStructure(bool interactive) QDir rootDir(mDocumentRepositoryPath); rootDir.mkpath(rootDir.path()); - QFileInfoList contentList = rootDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Time | QDir::Reversed); - createDocumentProxiesStructure(contentList, interactive); + QFileInfoList contentInfoList = rootDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Time | QDir::Reversed); + + mProgress.setWindowFlags(Qt::Window | Qt::WindowTitleHint | Qt::CustomizeWindowHint); + mProgress.setLabelText(QString("retrieving all your documents (found %1)").arg(contentInfoList.size())); + mProgress.setCancelButton(nullptr); + + createDocumentProxiesStructure(contentInfoList, interactive); if (QFileInfo(mFoldersXmlStorageName).exists()) { QDomDocument xmlDom; @@ -158,44 +207,36 @@ void UBPersistenceManager::createDocumentProxiesStructure(bool interactive) } } -void UBPersistenceManager::createDocumentProxiesStructure(const QFileInfoList &contentInfo, bool interactive) +UBDocumentProxy* UBPersistenceManager::createDocumentProxyStructure(QFileInfo& contentInfo) { - foreach(QFileInfo path, contentInfo) - { - QString fullPath = path.absoluteFilePath(); + QString fullPath = contentInfo.absoluteFilePath(); + QDir dir(fullPath); - QDir dir(fullPath); - - if (dir.entryList(QDir::Files | QDir::NoDotAndDotDot).size() > 0) - { - QMap metadatas = UBMetadataDcSubsetAdaptor::load(fullPath); - QString docGroupName = metadatas.value(UBSettings::documentGroupName, QString()).toString(); - QString docName = metadatas.value(UBSettings::documentName, QString()).toString(); + if (dir.entryList(QDir::Files | QDir::NoDotAndDotDot).size() > 0) + { + QMap metadatas = UBMetadataDcSubsetAdaptor::load(fullPath); + QString docGroupName = metadatas.value(UBSettings::documentGroupName, QString()).toString(); + QString docName = metadatas.value(UBSettings::documentName, QString()).toString(); - if (docName.isEmpty()) { - qDebug() << "Group name and document name are empty in UBPersistenceManager::createDocumentProxiesStructure()"; - continue; - } + if (docName.isEmpty()) { + qDebug() << "Group name and document name are empty in UBPersistenceManager::createDocumentProxiesStructure()"; + return nullptr; + } - QModelIndex parentIndex = mDocumentTreeStructureModel->goTo(docGroupName); - if (!parentIndex.isValid()) { - return; - } + UBDocumentProxy* docProxy = new UBDocumentProxy(fullPath); // managed in UBDocumentTreeNode + foreach(QString key, metadatas.keys()) { + docProxy->setMetaData(key, metadatas.value(key)); + } - UBDocumentProxy* docProxy = new UBDocumentProxy(fullPath); // managed in UBDocumentTreeNode - foreach(QString key, metadatas.keys()) { - docProxy->setMetaData(key, metadatas.value(key)); - } + docProxy->setPageCount(sceneCount(docProxy)); - docProxy->setPageCount(sceneCount(docProxy)); + docProxy->moveToThread(UBApplication::instance()->thread()); - if (!interactive) - mDocumentTreeStructureModel->addDocument(docProxy, parentIndex); - else - processInteractiveReplacementDialog(docProxy); - } + return docProxy; } -} + + return nullptr; +}; QDialog::DialogCode UBPersistenceManager::processInteractiveReplacementDialog(UBDocumentProxy *pProxy) { diff --git a/src/core/UBPersistenceManager.h b/src/core/UBPersistenceManager.h index 8a1462ce..18353b0b 100644 --- a/src/core/UBPersistenceManager.h +++ b/src/core/UBPersistenceManager.h @@ -131,7 +131,8 @@ class UBPersistenceManager : public QObject bool addDirectoryContentToDocument(const QString& documentRootFolder, UBDocumentProxy* pDocument); void createDocumentProxiesStructure(bool interactive = false); - void createDocumentProxiesStructure(const QFileInfoList &contentInfo, bool interactive = false); + void createDocumentProxiesStructure(const QFileInfoList &contentInfoList, bool interactive = false); + UBDocumentProxy* createDocumentProxyStructure(QFileInfo &contentInfo); QDialog::DialogCode processInteractiveReplacementDialog(UBDocumentProxy *pProxy); QStringList documentSubDirectories() @@ -187,6 +188,8 @@ private: bool mHasPurgedDocuments; QString mDocumentRepositoryPath; QString mFoldersXmlStorageName; + QProgressDialog mProgress; + QFutureWatcher futureWatcher; private slots: void documentRepositoryChanged(const QString& path); diff --git a/src/desktop/UBCustomCaptureWindow.cpp b/src/desktop/UBCustomCaptureWindow.cpp index dc26abad..1a319738 100644 --- a/src/desktop/UBCustomCaptureWindow.cpp +++ b/src/desktop/UBCustomCaptureWindow.cpp @@ -79,6 +79,8 @@ int UBCustomCaptureWindow::execute(const QPixmap &pScreenPixmap) QDesktopWidget *desktop = QApplication::desktop(); int currentScreen = desktop->screenNumber(QCursor::pos()); + // necessary so that changing geometry really affects the widget + showNormal(); setGeometry(desktop->screenGeometry(currentScreen)); this->show(); setWindowOpacity(1.0); diff --git a/src/desktop/UBDesktopAnnotationController.cpp b/src/desktop/UBDesktopAnnotationController.cpp index 138d0fb4..f63560e6 100644 --- a/src/desktop/UBDesktopAnnotationController.cpp +++ b/src/desktop/UBDesktopAnnotationController.cpp @@ -516,6 +516,7 @@ QPixmap UBDesktopAnnotationController::getScreenPixmap() QScreen * screen = UBApplication::controlScreen(); QRect rect = desktop->screenGeometry(QCursor::pos()); + rect.moveTo(0, 0); return screen->grabWindow(desktop->effectiveWinId(), rect.x(), rect.y(), rect.width(), rect.height()); @@ -556,7 +557,7 @@ void UBDesktopAnnotationController::penActionPressed() // Check if the mouse cursor is on the little arrow QPoint cursorPos = QCursor::pos(); - QPoint palettePos = mDesktopPalette->pos(); + QPoint palettePos = mDesktopPalette->mapToGlobal(QPoint(0, 0)); // global coordinates of palette QPoint buttonPos = mDesktopPalette->buttonPos(UBApplication::mainWindow->actionPen); int iX = cursorPos.x() - (palettePos.x() + buttonPos.x()); // x position of the cursor in the palette @@ -610,7 +611,7 @@ void UBDesktopAnnotationController::eraserActionPressed() // Check if the mouse cursor is on the little arrow QPoint cursorPos = QCursor::pos(); - QPoint palettePos = mDesktopPalette->pos(); + QPoint palettePos = mDesktopPalette->mapToGlobal(QPoint(0, 0)); QPoint buttonPos = mDesktopPalette->buttonPos(UBApplication::mainWindow->actionEraser); int iX = cursorPos.x() - (palettePos.x() + buttonPos.x()); // x position of the cursor in the palette @@ -665,7 +666,7 @@ void UBDesktopAnnotationController::markerActionPressed() // Check if the mouse cursor is on the little arrow QPoint cursorPos = QCursor::pos(); - QPoint palettePos = mDesktopPalette->pos(); + QPoint palettePos = mDesktopPalette->mapToGlobal(QPoint(0, 0)); QPoint buttonPos = mDesktopPalette->buttonPos(UBApplication::mainWindow->actionMarker); int iX = cursorPos.x() - (palettePos.x() + buttonPos.x()); // x position of the cursor in the palette @@ -967,7 +968,7 @@ void UBDesktopAnnotationController::updateMask(bool bTransparent) p.setPen(Qt::red); p.setBrush(QBrush(Qt::red)); - p.drawRect(mTransparentDrawingView->geometry().x(), mTransparentDrawingView->geometry().y(), mTransparentDrawingView->width(), mTransparentDrawingView->height()); + p.drawRect(0, 0, mTransparentDrawingView->width(), mTransparentDrawingView->height()); p.end(); mTransparentDrawingView->setMask(mMask.mask()); diff --git a/src/document/UBDocumentController.cpp b/src/document/UBDocumentController.cpp index 24371875..e76c7ecd 100644 --- a/src/document/UBDocumentController.cpp +++ b/src/document/UBDocumentController.cpp @@ -2393,8 +2393,11 @@ void UBDocumentController::duplicateSelectedItem() int sceneCount = selectedSceneIndexes.count(); showMessage(tr("duplicated %1 page","duplicated %1 pages",sceneCount).arg(sceneCount), false); - mBoardController->setActiveDocumentScene(selectedThumbnail); - mBoardController->reloadThumbnails(); + if (selectedDocument() == mBoardController->selectedDocument()) + { + mBoardController->setActiveDocumentScene(selectedThumbnail); + mBoardController->reloadThumbnails(); + } } } else @@ -2999,6 +3002,8 @@ void UBDocumentController::addFolderOfImages() document->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); UBMetadataDcSubsetAdaptor::persist(document); reloadThumbnails(); + if (selectedDocument() == UBApplication::boardController->selectedDocument()) + UBApplication::boardController->reloadThumbnails(); } } } @@ -3012,11 +3017,6 @@ void UBDocumentController::addFileToDocument() if (document) { addFileToDocument(document); - reloadThumbnails(); - if (UBApplication::boardController->selectedDocument() == selectedDocument()) - { - UBApplication::boardController->reloadThumbnails(); - } } } @@ -3050,6 +3050,8 @@ bool UBDocumentController::addFileToDocument(UBDocumentProxy* document) document->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); UBMetadataDcSubsetAdaptor::persist(document); reloadThumbnails(); + if (selectedDocument() == UBApplication::boardController->selectedDocument()) + UBApplication::boardController->reloadThumbnails(); } else { @@ -3328,6 +3330,8 @@ void UBDocumentController::addImages() document->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); UBMetadataDcSubsetAdaptor::persist(document); reloadThumbnails(); + if (selectedDocument() == UBApplication::boardController->selectedDocument()) + UBApplication::boardController->reloadThumbnails(); } } } @@ -3777,6 +3781,8 @@ void UBDocumentController:: refreshDocumentThumbnailsView(UBDocumentContainer* s , QList() , QStringList() , UBApplication::mimeTypeUniboardPage); + + QApplication::restoreOverrideCursor(); return; } diff --git a/src/frameworks/UBFileSystemUtils.cpp b/src/frameworks/UBFileSystemUtils.cpp index 6c5ae6d6..42915957 100644 --- a/src/frameworks/UBFileSystemUtils.cpp +++ b/src/frameworks/UBFileSystemUtils.cpp @@ -105,6 +105,11 @@ bool UBFileSystemUtils::copyFile(const QString &source, const QString &destinati if (QFileInfo(normalizedDestination).isFile() && overwrite) { QFile::remove(normalizedDestination); } + else + { + if (!overwrite) + return true; // don't try to copy an existing file if overwrite is false + } } else { normalizedDestination = normalizedDestination.replace(QString("\\"), QString("/")); int pos = normalizedDestination.lastIndexOf("/"); @@ -300,7 +305,7 @@ bool UBFileSystemUtils::copyDir(const QString& pSourceDirPath, const QString& pT { if (dirContent.isDir()) { - successSoFar = copyDir(pSourceDirPath + "/" + dirContent.fileName(), pTargetDirPath + "/" + dirContent.fileName()); + successSoFar = copyDir(pSourceDirPath + "/" + dirContent.fileName(), pTargetDirPath + "/" + dirContent.fileName(), overwite); } else { diff --git a/src/gui/UBBoardThumbnailsView.cpp b/src/gui/UBBoardThumbnailsView.cpp index fe10ecca..a6f9ba4e 100644 --- a/src/gui/UBBoardThumbnailsView.cpp +++ b/src/gui/UBBoardThumbnailsView.cpp @@ -307,7 +307,7 @@ void UBBoardThumbnailsView::dragMoveEvent(QDragMoveEvent *event) { y = item->pos().y() - UBSettings::thumbnailSpacing / 2; if (mDropBar->y() != y) - mDropBar->setRect(QRectF(item->pos().x(), y, mThumbnailWidth-verticalScrollBar()->width(), 3)); + mDropBar->setRect(QRectF(item->pos().x(), y, (item->boundingRect().width()-verticalScrollBar()->width())*scale, 3)); } } else @@ -316,7 +316,7 @@ void UBBoardThumbnailsView::dragMoveEvent(QDragMoveEvent *event) { y = item->pos().y() + item->boundingRect().height() * scale + UBSettings::thumbnailSpacing / 2; if (mDropBar->y() != y) - mDropBar->setRect(QRectF(item->pos().x(), y, mThumbnailWidth-verticalScrollBar()->width(), 3)); + mDropBar->setRect(QRectF(item->pos().x(), y, (item->boundingRect().width()-verticalScrollBar()->width())*scale, 3)); } } }