From 1de820dc4bbc8cd815ae740456a3c28e71097300 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 4 Mar 2017 16:55:57 -0500 Subject: [PATCH 01/14] Fix/re-enable checking for updates We can (again) check for updates and, if an update is available, send the user to the site to download them. The old format (a .json specifying a version number and download URL) was kept. The address for this file is now specified in the settings. --- src/core/UBApplicationController.cpp | 140 ++++++++++++--------------- src/core/UBApplicationController.h | 15 +-- src/core/UBSettings.cpp | 1 + src/core/UBSettings.h | 1 + src/frameworks/UBVersion.cpp | 25 +++-- 5 files changed, 86 insertions(+), 96 deletions(-) diff --git a/src/core/UBApplicationController.cpp b/src/core/UBApplicationController.cpp index 36ae40ca..8b22b47c 100644 --- a/src/core/UBApplicationController.cpp +++ b/src/core/UBApplicationController.cpp @@ -90,7 +90,6 @@ UBApplicationController::UBApplicationController(UBBoardView *pControlView, , mAutomaticCheckForUpdates(false) , mCheckingForUpdates(false) , mIsShowingDesktop(false) - , mHttp(0) { mDisplayManager = new UBDisplayManager(this); @@ -121,7 +120,7 @@ UBApplicationController::UBApplicationController(UBBoardView *pControlView, connect(UBApplication::webController, SIGNAL(imageCaptured(const QPixmap &, bool, const QUrl&)) , this, SLOT(addCapturedPixmap(const QPixmap &, bool, const QUrl&))); - networkAccessManager = new QNetworkAccessManager (this); + mNetworkAccessManager = new QNetworkAccessManager (this); QTimer::singleShot (1000, this, SLOT (checkAtLaunch())); } @@ -136,8 +135,6 @@ UBApplicationController::~UBApplicationController() delete mBlackScene; delete mMirror; - if (mHttp) delete mHttp; - delete(mOpenSankoreImporter); mOpenSankoreImporter = NULL; } @@ -478,85 +475,71 @@ void UBApplicationController::showDesktop(bool dontSwitchFrontProcess) } -void UBApplicationController::checkUpdate(QString urlString) +void UBApplicationController::checkUpdate(const QUrl& url) { + QUrl jsonUrl = url; + if (url.isEmpty()) + jsonUrl = UBSettings::settings()->appSoftwareUpdateURL->get().toUrl(); + qDebug() << "Checking for update at url: " << jsonUrl.toString(); - #if defined(QT_NO_DEBUG) - /* - if(mHttp) - mHttp->deleteLater(); - QUrl url(urlString); - mHttp = new QHttpPart(url.host()); - connect(mHttp, SIGNAL(requestFinished(int,bool)), this, SLOT(updateRequestFinished(int,bool))); - connect(mHttp, SIGNAL(responseHeaderReceived(QHttpResponseHeader)), this, SLOT(updateHeaderReceived(QHttpResponseHeader))); - - mHttp->get(url.path()); - - */ - -#else - if(mHttpreply) - mHttpreply->deleteLater(); - QUrl url(urlString); - mHttpreply = qnam.get(QNetworkRequest(url)); - connect(mHttpreply, SIGNAL(requestFinished(int,bool)), this, SLOT(updateRequestFinished(int,bool))); - connect(mHttpreply, SIGNAL(responseHeaderReceived(QHttpResponseHeader)), this, SLOT(updateHeaderReceived(QHttpResponseHeader))); - // mHttpreply->setUrl(url.path()); - //mHttp->get(url.path()); + connect(mNetworkAccessManager, SIGNAL(finished(QNetworkReply*)), + this, SLOT(updateRequestFinished(QNetworkReply*))); + + mNetworkAccessManager->get(QNetworkRequest(jsonUrl)); -#endif } -/* -void UBApplicationController::updateHeaderReceived(QHttpResponseHeader header) + + +void UBApplicationController::updateRequestFinished(QNetworkReply * reply) { - if(header.statusCode() == 302 && header.hasKey("Location")){ - mHttp->close(); - checkUpdate(header.value("Location")); + if (reply->error()) { + qWarning() << "Error downloading update file: " << reply->errorString(); + return; } -} -*/ -void UBApplicationController::updateHeaderReceived(QNetworkRequest header ) -{ - //if(header.attribute(QNetworkRequest::HttpStatusCodeAttribute) == 302 && header.header(QNetworkRequest::LocationHeader)){ - // mHttp->close(); - mHttpreply->close(); - //checkUpdate(header.value("Location")); - // } -} + // Check if we are being redirected. If so, call checkUpdate again -void UBApplicationController::updateRequestFinished(int id, bool error) -{ - if (error){ - qWarning() << "http command id" << id << "return an error"; - } - else{ - /* QString responseString = QString(mHttp->readAll()); - qDebug() << responseString; - if (!responseString.isEmpty() && responseString.contains("version") && responseString.contains("url")){ - mHttp->close(); - mHttp->deleteLater(); - mHttp = 0; - downloadJsonFinished(responseString); - } - */ - QString responseString = QString(mHttpreply->readAll()); - qDebug() << responseString; - if (!responseString.isEmpty() && responseString.contains("version") && responseString.contains("url")){ - mHttpreply->close(); - mHttpreply->deleteLater(); - mHttpreply = 0; - downloadJsonFinished(responseString); - } - } -} + QVariant redirect_target = reply->attribute(QNetworkRequest::RedirectionTargetAttribute); + if (!redirect_target.isNull()) { + // The returned URL might be relative. resolved() creates an absolute url from it + QUrl redirect_url(reply->url().resolved(redirect_target.toUrl())); + checkUpdate(redirect_url); + return; + } + + // No error and no redirect => we read the whole response + + QString responseString = QString(reply->readAll()); + + if (!responseString.isEmpty() && + responseString.contains("version") && + responseString.contains("url")) { + + reply->close(); + reply->deleteLater(); + + downloadJsonFinished(responseString); + } +} void UBApplicationController::downloadJsonFinished(QString currentJson) { + /* + The .json files simply specify the latest version number available, and + the URL to send the user to, so they can download it. + + They look like: + + { + "version": "1.3.5", + "url": "http://openboard.ch" + } + */ + QScriptValue scriptValue; QScriptEngine scriptEngine; scriptValue = scriptEngine.evaluate ("(" + currentJson + ")"); @@ -564,17 +547,18 @@ void UBApplicationController::downloadJsonFinished(QString currentJson) UBVersion installedVersion (qApp->applicationVersion()); UBVersion jsonVersion (scriptValue.property("version").toString()); + qDebug() << "json version: " << jsonVersion.toUInt(); + qDebug() << "installed version: " << installedVersion.toUInt(); + if (jsonVersion > installedVersion) { - if (UBApplication::mainWindow->yesNoQuestion(tr("Update available"), tr ("New update available, would you go to the web page ?"))){ - QUrl url(scriptValue.property ("url").toString()); - QDesktopServices::openUrl (url); - } - } - else { - if (isNoUpdateDisplayed) { - mMainWindow->information(tr("Update"), tr("No update available")); + if (UBApplication::mainWindow->yesNoQuestion(tr("Update available"), tr ("New update available, would you go to the web page ?"))){ + QUrl url(scriptValue.property("url").toString()); + QDesktopServices::openUrl(url); } } + else if (isNoUpdateDisplayed) { + mMainWindow->information(tr("Update"), tr("No update available")); + } } void UBApplicationController::checkAtLaunch() @@ -583,14 +567,14 @@ void UBApplicationController::checkAtLaunch() if(UBSettings::settings()->appEnableAutomaticSoftwareUpdates->get().toBool()){ isNoUpdateDisplayed = false; - //checkUpdate (); + checkUpdate(); } } void UBApplicationController::checkUpdateRequest() { isNoUpdateDisplayed = true; - //checkUpdate (); + checkUpdate(); } void UBApplicationController::hideDesktop() diff --git a/src/core/UBApplicationController.h b/src/core/UBApplicationController.h index 03ace3a9..c3cfb40d 100644 --- a/src/core/UBApplicationController.h +++ b/src/core/UBApplicationController.h @@ -53,12 +53,8 @@ class UBVersion; class UBSoftwareUpdate; class QNetworkAccessManager; class QNetworkReply; -class QHttpPart; class UBRightPalette; class UBOpenSankoreImporter; -class QScriptValue; -class QScriptEngine; -class QNetworkReply; class UBApplicationController : public QObject { @@ -158,8 +154,8 @@ class UBApplicationController : public QObject void checkAtLaunch(); private slots: - void updateRequestFinished(int id, bool error); - void updateHeaderReceived(QNetworkRequest header ); + void updateRequestFinished(QNetworkReply * reply); + protected: @@ -193,13 +189,10 @@ class UBApplicationController : public QObject bool mIsShowingDesktop; bool isNoUpdateDisplayed; - void checkUpdate (QString urlString = "http://get.openboard.org/update.json"); - QNetworkAccessManager *networkAccessManager; + void checkUpdate(const QUrl &url = QUrl()); + QNetworkAccessManager * mNetworkAccessManager; void downloadJsonFinished(QString updateString); - QHttpPart* mHttp; - QNetworkAccessManager qnam; - QNetworkReply *mHttpreply; }; #endif /* UBAPPLICATIONCONTROLLER_H_ */ diff --git a/src/core/UBSettings.cpp b/src/core/UBSettings.cpp index cccf87b7..aba5d8ce 100644 --- a/src/core/UBSettings.cpp +++ b/src/core/UBSettings.cpp @@ -226,6 +226,7 @@ void UBSettings::init() appToolBarDisplayText = new UBSetting(this, "App", "ToolBarDisplayText", true); appEnableAutomaticSoftwareUpdates = new UBSetting(this, "App", "EnableAutomaticSoftwareUpdates", false); appEnableSoftwareUpdates = new UBSetting(this, "App", "EnableSoftwareUpdates", true); + appSoftwareUpdateURL = new UBSetting(this, "App", "SoftwareUpdateURL", "http://www.openboard.ch/update.json"); appToolBarOrientationVertical = new UBSetting(this, "App", "ToolBarOrientationVertical", false); appPreferredLanguage = new UBSetting(this,"App","PreferredLanguage", ""); diff --git a/src/core/UBSettings.h b/src/core/UBSettings.h index 9f024d57..44757652 100644 --- a/src/core/UBSettings.h +++ b/src/core/UBSettings.h @@ -240,6 +240,7 @@ class UBSettings : public QObject UBSetting* appToolBarDisplayText; UBSetting* appEnableAutomaticSoftwareUpdates; UBSetting* appEnableSoftwareUpdates; + UBSetting* appSoftwareUpdateURL; UBSetting* appToolBarOrientationVertical; UBSetting* appPreferredLanguage; diff --git a/src/frameworks/UBVersion.cpp b/src/frameworks/UBVersion.cpp index a08c4fc7..b8916152 100644 --- a/src/frameworks/UBVersion.cpp +++ b/src/frameworks/UBVersion.cpp @@ -42,21 +42,32 @@ UBVersion::UBVersion(const QString &string) uint UBVersion::toUInt() const { + /* Based on semantic versioning, version numbers look like: + * Major.Minor.Patch-Type.Build + * + * To compare version numbers, the string is split into each part, and they are multiplied + * to give a number where the first two digits are the Major version, the next two are the + * Minor version, and so on. + * + * i.e if Major, Minor etc. are named A, B, C, D, E, the number will look like: + * AABBCCDDEE + */ + uint result = 0; - QStringList list = mString.split("."); + QStringList list = mString.split(QRegExp("[-\\.]")); switch (list.count()) { case 2: //short version 1.0 - result = (list.at(0).toUInt() * 1000000) + (list.at(1).toUInt() * 10000) + (Release * 100); + result = (list.at(0).toUInt() * 100000000) + (list.at(1).toUInt() * 1000000) + (Release * 100); break; case 3: //release version 1.0.0 - result = (list.at(0).toUInt() * 1000000) + (list.at(1).toUInt() * 10000) + (Release * 100) + list.at(2).toUInt(); + result = (list.at(0).toUInt() * 100000000) + (list.at(1).toUInt() * 1000000) + list.at(2).toUInt()*10000 + (Release * 100); break; - case 4:{ - //standard version 1.0.a/b/r.0 - uint releaseStage = list.at(2).startsWith("a") ? Alpha :(list.at(2).startsWith("b") ? Beta : ReleaseCandidate); - result = (list.at(0).toUInt() * 1000000) + (list.at(1).toUInt() * 10000) + (releaseStage * 100) + list.at(3).toUInt(); + case 5:{ + //standard version 1.0.0.a/b/rc.0 + uint releaseStage = list.at(3).startsWith("a") ? Alpha :(list.at(3).startsWith("b") ? Beta : ReleaseCandidate); + result = (list.at(0).toUInt() * 100000000) + (list.at(1).toUInt() * 1000000) + (list.at(2).toUInt() * 10000) + (releaseStage * 100) + list.at(4).toUInt(); break; } default: From 1d953738329ae226a8ea4069249abe071d69d3ef Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 11 Mar 2017 09:57:46 -0500 Subject: [PATCH 02/14] Slightly better default color for grid on dark backgrounds --- src/core/UBSettings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/UBSettings.cpp b/src/core/UBSettings.cpp index aba5d8ce..337ed250 100644 --- a/src/core/UBSettings.cpp +++ b/src/core/UBSettings.cpp @@ -271,7 +271,7 @@ void UBSettings::init() pageSize = new UBSetting(this, "Board", "DefaultPageSize", documentSizes.value(DocumentSizeRatio::Ratio4_3)); - boardCrossColorDarkBackground = new UBSetting(this, "Board", "CrossColorDarkBackground", "#C82C2C2C"); + boardCrossColorDarkBackground = new UBSetting(this, "Board", "CrossColorDarkBackground", "#C8C0C0C0"); boardCrossColorLightBackground = new UBSetting(this, "Board", "CrossColorLightBackground", "#A5E1FF"); QStringList penLightBackgroundColors; From 7346bb81827472ddca1ff9231050ce288f6bc5d2 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 11 Mar 2017 11:28:09 -0500 Subject: [PATCH 03/14] Allow mask to be scaled non-proportionally --- src/tools/UBGraphicsCurtainItemDelegate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/UBGraphicsCurtainItemDelegate.cpp b/src/tools/UBGraphicsCurtainItemDelegate.cpp index 0209cd74..9e4071fb 100644 --- a/src/tools/UBGraphicsCurtainItemDelegate.cpp +++ b/src/tools/UBGraphicsCurtainItemDelegate.cpp @@ -38,7 +38,7 @@ #include "core/memcheck.h" UBGraphicsCurtainItemDelegate::UBGraphicsCurtainItemDelegate(UBGraphicsCurtainItem* pDelegated, QObject * parent) - : UBGraphicsItemDelegate(pDelegated, parent, GF_SCALABLE_ALL_AXIS | GF_MENU_SPECIFIED) + : UBGraphicsItemDelegate(pDelegated, parent, GF_MENU_SPECIFIED) { //NOOP } From 3a3a936916d3989d362b683f19785e1a70fa5e26 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 11 Mar 2017 16:11:10 -0500 Subject: [PATCH 04/14] Fix undo/redo messing up item transforms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This code was lifted from Open-Sankoré 2.10. This fixes an issue where erasing part of a stroke that had been moved or rotated, then clicking "undo" then "redo" would place part of the stroke in the wrong place. --- src/domain/UBGraphicsItemUndoCommand.cpp | 43 ++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/domain/UBGraphicsItemUndoCommand.cpp b/src/domain/UBGraphicsItemUndoCommand.cpp index ee23a7bb..aae00f2b 100644 --- a/src/domain/UBGraphicsItemUndoCommand.cpp +++ b/src/domain/UBGraphicsItemUndoCommand.cpp @@ -98,7 +98,28 @@ void UBGraphicsItemUndoCommand::undo() UBApplication::boardController->freezeW3CWidget(item, true); item->setSelected(false); + + QTransform t; + bool bApplyTransform = false; + UBGraphicsPolygonItem *polygonItem = qgraphicsitem_cast(item); + if (polygonItem){ + if (polygonItem->strokesGroup() + && polygonItem->strokesGroup()->parentItem() + && UBGraphicsGroupContainerItem::Type == polygonItem->strokesGroup()->parentItem()->type()) + { + bApplyTransform = true; + t = polygonItem->sceneTransform(); + } + else if (polygonItem->strokesGroup()) + polygonItem->resetTransform(); + + polygonItem->strokesGroup()->removeFromGroup(polygonItem); + } mScene->removeItem(item); + + if (bApplyTransform) + polygonItem->setTransform(t); + } QSetIterator itRemoved(mRemovedItems); @@ -207,7 +228,29 @@ void UBGraphicsItemUndoCommand::redo() { QGraphicsItem* item = itRemoved.next(); item->setSelected(false); + + QTransform t; + bool bApplyTransform = false; + UBGraphicsPolygonItem *polygonItem = qgraphicsitem_cast(item); + + if (polygonItem){ + if(polygonItem->strokesGroup() + && polygonItem->strokesGroup()->parentItem() + && UBGraphicsGroupContainerItem::Type == polygonItem->strokesGroup()->parentItem()->type()) + { + bApplyTransform = true; + t = polygonItem->sceneTransform(); + } + else if (polygonItem->strokesGroup()) + polygonItem->resetTransform(); + + polygonItem->strokesGroup()->removeFromGroup(polygonItem); + } mScene->removeItem(item); + + if (bApplyTransform) + item->setTransform(t); + UBApplication::boardController->freezeW3CWidget(item, true); } From 6b90a8f33379adc2622391110c5eee25cb722d8e Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 11 Mar 2017 16:12:48 -0500 Subject: [PATCH 05/14] Fix for trashed items being set as current document When deleting a document that was in the trash, the following item was selected but also set as current document. This is now fixed. --- src/document/UBDocumentController.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/document/UBDocumentController.cpp b/src/document/UBDocumentController.cpp index ebce0117..2910e785 100644 --- a/src/document/UBDocumentController.cpp +++ b/src/document/UBDocumentController.cpp @@ -809,7 +809,7 @@ void UBDocumentController::deleteTreeItem(QTreeWidgetItem * item, bool showConfi if (mTrashTi->childCount()==0) selectDocument(NULL); else - selectDocument(((UBDocumentProxyTreeItem*)mTrashTi->child(0))->proxy()); + selectDocument(((UBDocumentProxyTreeItem*)mTrashTi->child(0))->proxy(), false); } reloadThumbnails(); From 5d48d55c7fc004c7496a96d6d9987a1110623c76 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 11 Mar 2017 17:15:39 -0500 Subject: [PATCH 06/14] Fix for duplicated strokes being positioned badly Bug likely surfaced when fixing positioning of saved strokes. Quick tests show that positioning now works both for duplication and saving/loading --- src/board/UBBoardController.cpp | 3 --- src/domain/UBGraphicsStrokesGroup.cpp | 5 +++++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/board/UBBoardController.cpp b/src/board/UBBoardController.cpp index 04ea0d22..7ff7a9ca 100644 --- a/src/board/UBBoardController.cpp +++ b/src/board/UBBoardController.cpp @@ -593,9 +593,6 @@ UBGraphicsItem *UBBoardController::duplicateItem(UBItem *item) itemSize = commonItem->boundingRect().size(); commonItem->setSelected(false); - UBGraphicsStrokesGroup *stroke = dynamic_cast(commonItem); - if (stroke) - itemPos = QPointF(shifting, shifting); } UBMimeType::Enum itemMimeType; diff --git a/src/domain/UBGraphicsStrokesGroup.cpp b/src/domain/UBGraphicsStrokesGroup.cpp index 5d418d01..da2c4deb 100644 --- a/src/domain/UBGraphicsStrokesGroup.cpp +++ b/src/domain/UBGraphicsStrokesGroup.cpp @@ -148,12 +148,15 @@ void UBGraphicsStrokesGroup::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) UBItem* UBGraphicsStrokesGroup::deepCopy() const { QTransform groupTransform = transform(); + QPointF groupPos = pos(); UBGraphicsStrokesGroup* copy = new UBGraphicsStrokesGroup(); copyItemParameters(copy); copy->resetTransform(); + copy->setPos(0,0); const_cast(this)->resetTransform(); + const_cast(this)->setPos(0,0); QList chl = childItems(); @@ -175,7 +178,9 @@ UBItem* UBGraphicsStrokesGroup::deepCopy() const } } const_cast(this)->setTransform(groupTransform); + const_cast(this)->setPos(groupPos); copy->setTransform(groupTransform); + copy->setPos(groupPos); return copy; } From b7f5cc27140907d888811fdcf925150315243db9 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 8 Apr 2017 20:09:11 -0400 Subject: [PATCH 07/14] Added sceneSize function to UBGraphicsScene --- src/domain/UBGraphicsScene.cpp | 18 ++++++++++++++++++ src/domain/UBGraphicsScene.h | 2 ++ 2 files changed, 20 insertions(+) diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index fe0cdcc7..f36984b9 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -2257,6 +2257,24 @@ QSize UBGraphicsScene::nominalSize() return mNominalSize; } +/** + * @brief Return the scene's boundary size, including any background item + * + * If no background item is present, this returns nominalSize() + */ +QSize UBGraphicsScene::sceneSize() +{ + UBGraphicsPDFItem *pdfItem = qgraphicsitem_cast(backgroundObject()); + + if (pdfItem) { + QRectF targetRect = pdfItem->sceneBoundingRect(); + return targetRect.size().toSize(); + } + + else + return nominalSize(); +} + void UBGraphicsScene::setNominalSize(const QSize& pSize) { if (nominalSize() != pSize) diff --git a/src/domain/UBGraphicsScene.h b/src/domain/UBGraphicsScene.h index 29966f6d..43a29836 100644 --- a/src/domain/UBGraphicsScene.h +++ b/src/domain/UBGraphicsScene.h @@ -277,6 +277,8 @@ class UBGraphicsScene: public UBCoreGraphicsScene, public UBItem QSize nominalSize(); + QSize sceneSize(); + void setNominalSize(const QSize& pSize); void setNominalSize(int pWidth, int pHeight); From 716314fe7350efc8e02ca9d24d0a81bbee035dc6 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 8 Apr 2017 20:10:46 -0400 Subject: [PATCH 08/14] Fixed PDF export page size In some cases, export of a document containing a PDF background to PDF caused the contents to be truncated. The "simple" PDF exporter will now set the output page size to be equal either to the document nominal size or, if the document has a background PDF item, to the size of this item. --- src/adaptors/UBExportPDF.cpp | 49 +++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/src/adaptors/UBExportPDF.cpp b/src/adaptors/UBExportPDF.cpp index ad9aaa5a..65db6e63 100644 --- a/src/adaptors/UBExportPDF.cpp +++ b/src/adaptors/UBExportPDF.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include "core/UBApplication.h" #include "core/UBSettings.h" @@ -40,6 +41,7 @@ #include "domain/UBGraphicsScene.h" #include "domain/UBGraphicsSvgItem.h" +#include "domain/UBGraphicsPDFItem.h" #include "document/UBDocumentProxy.h" @@ -66,56 +68,67 @@ void UBExportPDF::persist(UBDocumentProxy* pDocumentProxy) bool UBExportPDF::persistsDocument(UBDocumentProxy* pDocumentProxy, const QString& filename) { - QPrinter pdfPrinter; + QPdfWriter pdfWriter(filename); qDebug() << "exporting document to PDF" << filename; - pdfPrinter.setOutputFormat(QPrinter::PdfFormat); - pdfPrinter.setResolution(UBSettings::settings()->pdfResolution->get().toInt()); - pdfPrinter.setOutputFileName(filename); - pdfPrinter.setFullPage(true); + pdfWriter.setResolution(UBSettings::settings()->pdfResolution->get().toInt()); + pdfWriter.setPageMargins(QMarginsF()); + pdfWriter.setTitle(pDocumentProxy->name()); + pdfWriter.setCreator("OpenBoard PDF export"); //need to calculate screen resolution QDesktopWidget* desktop = UBApplication::desktop(); int dpiCommon = (desktop->physicalDpiX() + desktop->physicalDpiY()) / 2; float scaleFactor = 72.0f / dpiCommon; - + QPainter pdfPainter; bool painterNeedsBegin = true; int existingPageCount = pDocumentProxy->pageCount(); - for(int pageIndex = 0 ; pageIndex < existingPageCount; pageIndex++) - { + for(int pageIndex = 0 ; pageIndex < existingPageCount; pageIndex++) { + UBGraphicsScene* scene = UBPersistenceManager::persistenceManager()->loadDocumentScene(pDocumentProxy, pageIndex); UBApplication::showMessage(tr("Exporting page %1 of %2").arg(pageIndex + 1).arg(existingPageCount)); + // set background to white, no crossing for PDF output bool isDark = scene->isDarkBackground(); bool isCrossed = scene->isCrossedBackground(); scene->setBackground(false, false); - QSize pageSize = scene->nominalSize(); + // pageSize is the output PDF page size; it is set to equal the scene's boundary size; if the contents + // of the scene overflow from the boundaries, they will be scaled down. + QSize pageSize = scene->sceneSize(); // set high res rendering scene->setRenderingQuality(UBItem::RenderingQualityHigh); scene->setRenderingContext(UBGraphicsScene::NonScreen); - //setting page size to appropriate value - pdfPrinter.setPaperSize(QSizeF(pageSize.width()*scaleFactor, pageSize.height()*scaleFactor), QPrinter::Point); - if(painterNeedsBegin) painterNeedsBegin = !pdfPainter.begin(&pdfPrinter); - //render to PDF - scene->render(&pdfPainter, QRectF(), scene->normalizedSceneRect()); + // Setting output page size + QPageSize outputPageSize = QPageSize(QSizeF(pageSize.width()*scaleFactor, pageSize.height()*scaleFactor), QPageSize::Point); + pdfWriter.setPageSize(outputPageSize); - if (pageIndex < existingPageCount - 1) pdfPrinter.newPage(); + // Call begin only once + if(painterNeedsBegin) + painterNeedsBegin = !pdfPainter.begin(&pdfWriter); - //restore screen rendering quality + else if (pageIndex < existingPageCount) + pdfWriter.newPage(); + + // Render the scene + scene->render(&pdfPainter, QRectF(), scene->normalizedSceneRect()); + + // Restore screen rendering quality scene->setRenderingContext(UBGraphicsScene::Screen); scene->setRenderingQuality(UBItem::RenderingQualityNormal); - //restore background state + // Restore background state scene->setBackground(isDark, isCrossed); } - if(!painterNeedsBegin) pdfPainter.end(); + + if(!painterNeedsBegin) + pdfPainter.end(); return true; } From fc81e27b9faa0fba44a653317d43f7b482c91bc4 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sun, 23 Apr 2017 10:40:10 -0400 Subject: [PATCH 09/14] Fix for copy/paste issues This fixes two related issues: 1) When taking a partial screenshot of the desktop, then copying it (Ctrl-C) and pasting it in a new document, it was not saved 2) When a page of one document was copied into another (in document mode, by dragging the page onto another document), media files disappeared from the new page. --- src/board/UBBoardController.cpp | 2 +- src/board/UBBoardPaletteManager.cpp | 7 ++++++- src/domain/UBGraphicsScene.cpp | 22 +++++++++++++--------- src/gui/UBDocumentTreeWidget.cpp | 7 +++++-- 4 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/board/UBBoardController.cpp b/src/board/UBBoardController.cpp index 7ff7a9ca..3d25bba1 100644 --- a/src/board/UBBoardController.cpp +++ b/src/board/UBBoardController.cpp @@ -651,7 +651,7 @@ UBGraphicsItem *UBBoardController::duplicateItem(UBItem *item) { QBuffer buffer(&pData); buffer.open(QIODevice::WriteOnly); - QString format = UBFileSystemUtils::extension(item->sourceUrl().toLocalFile()); + QString format = UBFileSystemUtils::extension(item->sourceUrl().toString(QUrl::DecodeReserved)); pixitem->pixmap().save(&buffer, format.toLatin1()); } }break; diff --git a/src/board/UBBoardPaletteManager.cpp b/src/board/UBBoardPaletteManager.cpp index eff776c5..b5dc37b0 100644 --- a/src/board/UBBoardPaletteManager.cpp +++ b/src/board/UBBoardPaletteManager.cpp @@ -73,6 +73,7 @@ #include "document/UBDocumentController.h" +#include "core/UBPersistenceManager.h" #include "core/memcheck.h" UBBoardPaletteManager::UBBoardPaletteManager(QWidget* container, UBBoardController* pBoardController) @@ -846,7 +847,11 @@ void UBBoardPaletteManager::addItemToCurrentPage() { UBGraphicsPixmapItem* item = UBApplication::boardController->activeScene()->addPixmap(mPixmap, NULL, mPos, mScaleFactor); - item->setSourceUrl(mItemUrl); + QString documentPath = UBApplication::boardController->selectedDocument()->persistencePath(); + QString fileName = UBPersistenceManager::imageDirectory + "/" + item->uuid().toString() + ".png"; + QString path = documentPath + "/" + fileName; + + item->setSourceUrl(QUrl(path)); item->setSelected(true); UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index f36984b9..0ee33c5c 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -2209,15 +2209,19 @@ QList UBGraphicsScene::relativeDependencies() const while (itItems.hasNext()) { QGraphicsItem* item = itItems.next(); - UBGraphicsMediaItem *mediaItem = qgraphicsitem_cast (item); - - if (mediaItem){ - QString completeFileName = QFileInfo(mediaItem->mediaFileUrl().toLocalFile()).fileName(); - QString path; - if(mediaItem->getMediaType() == UBGraphicsMediaItem::mediaType_Video) - path = UBPersistenceManager::videoDirectory + "/"; - else - path = UBPersistenceManager::audioDirectory + "/"; + + UBGraphicsVideoItem *videoItem = qgraphicsitem_cast (item); + if (videoItem){ + QString completeFileName = QFileInfo(videoItem->mediaFileUrl().toLocalFile()).fileName(); + QString path = UBPersistenceManager::videoDirectory + "/"; + relativePathes << QUrl(path + completeFileName); + continue; + } + + UBGraphicsAudioItem *audioItem = qgraphicsitem_cast (item); + if (audioItem){ + QString completeFileName = QFileInfo(audioItem->mediaFileUrl().toLocalFile()).fileName(); + QString path = UBPersistenceManager::audioDirectory + "/"; relativePathes << QUrl(path + completeFileName); continue; } diff --git a/src/gui/UBDocumentTreeWidget.cpp b/src/gui/UBDocumentTreeWidget.cpp index b6728e4c..2339e120 100644 --- a/src/gui/UBDocumentTreeWidget.cpp +++ b/src/gui/UBDocumentTreeWidget.cpp @@ -285,13 +285,16 @@ void UBDocumentTreeWidget::dropEvent(QDropEvent *event) QString source = scene->document()->persistencePath() + "/" + relativeFile.toString(); QString target = targetDocProxy->persistencePath() + "/" + relativeFile.toString(); + QString sourceDecoded = scene->document()->persistencePath() + "/" + relativeFile.toString(QUrl::DecodeReserved); + QString targetDecoded = targetDocProxy->persistencePath() + "/" + relativeFile.toString(QUrl::DecodeReserved); + if(QFileInfo(source).isDir()) UBFileSystemUtils::copyDir(source,target); else{ - QFileInfo fi(target); + QFileInfo fi(targetDecoded); QDir d = fi.dir(); d.mkpath(d.absolutePath()); - QFile::copy(source, target); + QFile::copy(sourceDecoded, targetDecoded); } } From 83874ddb086814c4cda1325ec8a65ece0768a2e3 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sun, 23 Apr 2017 22:01:58 -0400 Subject: [PATCH 10/14] Clean up update checking --- resources/etc/OpenBoard.config | 1 - src/core/UBApplication.cpp | 8 +------- src/core/UBPreferencesController.cpp | 2 -- src/core/UBSettings.cpp | 1 - src/core/UBSettings.h | 1 - 5 files changed, 1 insertion(+), 12 deletions(-) diff --git a/resources/etc/OpenBoard.config b/resources/etc/OpenBoard.config index cdef9239..c332d35a 100644 --- a/resources/etc/OpenBoard.config +++ b/resources/etc/OpenBoard.config @@ -1,7 +1,6 @@ [App] AngleTolerance=4 EnableAutomaticSoftwareUpdates=false -EnableSoftwareUpdates=true EnableStartupHints=true FavoriteToolURIs=openboardtool://openboard/mask, openboardtool://ruler, openboardtool://compass, openboardtool://protractor, openboardtool://triangle, openboardtool://magnifier, openboardtool://cache IsInSoftwareUpdateProcess=false diff --git a/src/core/UBApplication.cpp b/src/core/UBApplication.cpp index e364027d..c1ebd477 100644 --- a/src/core/UBApplication.cpp +++ b/src/core/UBApplication.cpp @@ -511,13 +511,7 @@ void UBApplication::decorateActionMenu(QAction* action) menu->addSeparator(); menu->addAction(mainWindow->actionPreferences); menu->addAction(mainWindow->actionMultiScreen); - // SANKORE-48: Hide the check update action if the setting - // EnableAutomaticSoftwareUpdates is false in Uniboard.config - if(UBSettings::settings()->appEnableAutomaticSoftwareUpdates->get().toBool()) - menu->addAction(mainWindow->actionCheckUpdate); - else - mainWindow->actionCheckUpdate->setEnabled(false); - + menu->addAction(mainWindow->actionCheckUpdate); menu->addSeparator(); #ifndef Q_OS_LINUX // No Podcast on Linux yet diff --git a/src/core/UBPreferencesController.cpp b/src/core/UBPreferencesController.cpp index 9fef16a1..8e787e56 100644 --- a/src/core/UBPreferencesController.cpp +++ b/src/core/UBPreferencesController.cpp @@ -186,8 +186,6 @@ void UBPreferencesController::wire() // about tab connect(mPreferencesUI->checkSoftwareUpdateAtLaunchCheckBox, SIGNAL(clicked(bool)), settings->appEnableAutomaticSoftwareUpdates, SLOT(setBool(bool))); - // As we (hopefully temporarily) don't have a website to check updates at, this setting is hidden for now - mPreferencesUI->softwareUpdateGroupBox->setVisible(false); connect(mPreferencesUI->checkOpenSankoreAtStartup, SIGNAL(clicked(bool)), settings->appLookForOpenSankoreInstall, SLOT(setBool(bool))); } diff --git a/src/core/UBSettings.cpp b/src/core/UBSettings.cpp index 337ed250..bea6dd66 100644 --- a/src/core/UBSettings.cpp +++ b/src/core/UBSettings.cpp @@ -225,7 +225,6 @@ void UBSettings::init() appToolBarPositionedAtTop = new UBSetting(this, "App", "ToolBarPositionedAtTop", true); appToolBarDisplayText = new UBSetting(this, "App", "ToolBarDisplayText", true); appEnableAutomaticSoftwareUpdates = new UBSetting(this, "App", "EnableAutomaticSoftwareUpdates", false); - appEnableSoftwareUpdates = new UBSetting(this, "App", "EnableSoftwareUpdates", true); appSoftwareUpdateURL = new UBSetting(this, "App", "SoftwareUpdateURL", "http://www.openboard.ch/update.json"); appToolBarOrientationVertical = new UBSetting(this, "App", "ToolBarOrientationVertical", false); appPreferredLanguage = new UBSetting(this,"App","PreferredLanguage", ""); diff --git a/src/core/UBSettings.h b/src/core/UBSettings.h index 44757652..c191a4cd 100644 --- a/src/core/UBSettings.h +++ b/src/core/UBSettings.h @@ -239,7 +239,6 @@ class UBSettings : public QObject UBSetting* appToolBarPositionedAtTop; UBSetting* appToolBarDisplayText; UBSetting* appEnableAutomaticSoftwareUpdates; - UBSetting* appEnableSoftwareUpdates; UBSetting* appSoftwareUpdateURL; UBSetting* appToolBarOrientationVertical; UBSetting* appPreferredLanguage; From 5416e6d834e199d6a61d6bc33b09efdf9b0803a8 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 29 Apr 2017 21:05:06 -0400 Subject: [PATCH 11/14] Fix for video-related crashing on Windows Issue observed was that OpenBoard would crash on some Windows systems when a video was on the page and that page was saved (due to switching to document mode, auto saving, or duplicating the page), or when cutting the video with Ctrl-X. This was due to QTBUG-32522, where setting the video output for a QMediaPlayer that is hidden results in a crash. This commit is a work-around for this Qt issue, and so should be reverted if and when the upstream issue is fixed. --- src/domain/UBGraphicsMediaItem.cpp | 39 ++++++++++++++++++++++++++++-- src/domain/UBGraphicsMediaItem.h | 3 +++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/domain/UBGraphicsMediaItem.cpp b/src/domain/UBGraphicsMediaItem.cpp index 4185fe40..851e38f7 100644 --- a/src/domain/UBGraphicsMediaItem.cpp +++ b/src/domain/UBGraphicsMediaItem.cpp @@ -130,7 +130,14 @@ UBGraphicsVideoItem::UBGraphicsVideoItem(const QUrl &pMediaFileUrl, QGraphicsIte mVideoItem->setData(UBGraphicsItemData::ItemLayerType, UBItemLayerType::Object); mVideoItem->setFlag(ItemStacksBehindParent, true); - mMediaObject->setVideoOutput(mVideoItem); + /* setVideoOutput has to be called only when the video item is visible on the screen, + * due to a Qt bug (QTBUG-32522). So instead of calling it here, it is called when the + * active scene has changed, or when the item is first created. + * If and when Qt fix this issue, this should be changed back. + * */ + //mMediaObject->setVideoOutput(mVideoItem); + mHasVideoOutput = false; + mMediaObject->setNotifyInterval(50); setMinimumSize(QSize(320, 240)); @@ -155,8 +162,10 @@ UBGraphicsVideoItem::UBGraphicsVideoItem(const QUrl &pMediaFileUrl, QGraphicsIte UBGraphicsMediaItem::~UBGraphicsMediaItem() { - if (mMediaObject) + if (mMediaObject) { mMediaObject->stop(); + delete mMediaObject; + } } QVariant UBGraphicsMediaItem::itemChange(GraphicsItemChange change, const QVariant &value) @@ -569,6 +578,22 @@ void UBGraphicsVideoItem::paint(QPainter *painter, const QStyleOptionGraphicsIte } +QVariant UBGraphicsVideoItem::itemChange(GraphicsItemChange change, const QVariant &value) { + if (change == QGraphicsItem::ItemVisibleChange + && value.toBool() + && !mHasVideoOutput + && UBApplication::app()->boardController + && UBApplication::app()->boardController->activeScene() == scene()) + { + //qDebug() << "Item change, setting video output"; + + mMediaObject->setVideoOutput(mVideoItem); + mHasVideoOutput = true; + } + + return UBGraphicsMediaItem::itemChange(change, value); +} + void UBGraphicsVideoItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event) { // Display the seek bar @@ -610,9 +635,19 @@ void UBGraphicsVideoItem::mediaStateChanged(QMediaPlayer::State state) void UBGraphicsVideoItem::activeSceneChanged() { + //qDebug() << "Active scene changed"; + // Update the visibility of the placeholder, to prevent it being hidden when switching pages setPlaceholderVisible(!mErrorString.isEmpty()); + // Call setVideoOutput, if the video is visible and if it hasn't been called already + if (!mHasVideoOutput && UBApplication::boardController->activeScene() == scene()) { + //qDebug() << "setting video output"; + mMediaObject->setMedia(mMediaFileUrl); + mMediaObject->setVideoOutput(mVideoItem); + mHasVideoOutput = true; + } + UBGraphicsMediaItem::activeSceneChanged(); } diff --git a/src/domain/UBGraphicsMediaItem.h b/src/domain/UBGraphicsMediaItem.h index dd5ed396..4af649da 100644 --- a/src/domain/UBGraphicsMediaItem.h +++ b/src/domain/UBGraphicsMediaItem.h @@ -207,11 +207,14 @@ protected: QGraphicsVideoItem *mVideoItem; + virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value); virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event); virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event); virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); void setPlaceholderVisible(bool visible); + + bool mHasVideoOutput; }; From 7b4b59c378f9154ed144b97ac47652158af363a7 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 29 Apr 2017 21:58:32 -0400 Subject: [PATCH 12/14] Bumped version to 1.3.6-b.1 --- OpenBoard.pro | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenBoard.pro b/OpenBoard.pro index 64955fb9..feaa9f12 100644 --- a/OpenBoard.pro +++ b/OpenBoard.pro @@ -10,9 +10,9 @@ CONFIG += debug_and_release \ VERSION_MAJ = 1 VERSION_MIN = 3 -VERSION_PATCH = 5 -VERSION_TYPE = r # a = alpha, b = beta, rc = release candidate, r = release, other => error -VERSION_BUILD = 0 +VERSION_PATCH = 6 +VERSION_TYPE = b # a = alpha, b = beta, rc = release candidate, r = release, other => error +VERSION_BUILD = 1 VERSION = "$${VERSION_MAJ}.$${VERSION_MIN}.$${VERSION_PATCH}-$${VERSION_TYPE}.$${VERSION_BUILD}" From 750de4dbfd7bf68e53ddea4261bf96af8ecd25b6 Mon Sep 17 00:00:00 2001 From: Marco Ciampa Date: Mon, 27 Mar 2017 20:07:43 +0200 Subject: [PATCH 13/14] Updated Italian translation Credit: ciampix --- resources/i18n/OpenBoard_it.ts | 112 ++++++++++++++++----------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/resources/i18n/OpenBoard_it.ts b/resources/i18n/OpenBoard_it.ts index 3786d465..a65aef29 100644 --- a/resources/i18n/OpenBoard_it.ts +++ b/resources/i18n/OpenBoard_it.ts @@ -1,6 +1,6 @@ - + BlackoutWidget @@ -793,11 +793,11 @@ Open Tutorial - + Apri tutorial Open the tutorial web page - + Apri la pagina web del tutorial @@ -842,11 +842,11 @@ QObject Element ID = - Elemento ID = + Elemento ID = Content is not supported in destination format. - Il contenuto non è supportato nel formato di destinazione. + Il contenuto non è supportato nel formato di destinazione. Remove Page @@ -939,11 +939,11 @@ Saving document... - + Salvataggio documento... Document has just been saved... - + Il documento è stato appena salvato... @@ -1004,7 +1004,7 @@ Show OpenBoard - + Mostra OpenBoard @@ -1123,9 +1123,9 @@ Are you sure you want to remove %n page(s) from the selected document '%1'? - - Sei sicuro di voler rimuovere %n pagine dal documento '%1' selezionato? - + + Sei sicuro di voler rimuovere %n pagina dal documento '%1' selezionato? + Sei sicuro di voler rimuovere %n pagine dal documento '%1' selezionato? @@ -1138,15 +1138,15 @@ The document '%1' has been generated with a newer version of OpenBoard (%2). By opening it, you may lose some information. Do you want to proceed? - + Il documento "%1" è stato generato con una più recente versione di OpenBoard (%2). Aprendolo, si possono perdere alcune informazioni. Procedere ugualmente? Are you sure you want to remove all selected documents? - + Sicuri di voler rimuovere tutti i documenti selezionati? Remove multiple documents - + Rimuovi documenti multipli @@ -1212,8 +1212,8 @@ %1 pages copied - %1 pagine copiate - + %1 pagina copiata + %1 pagine copiate @@ -1239,23 +1239,23 @@ UBExportCFF Export to IWB - Esporta in IWB + Esporta in IWB Export as IWB File - Esporta come file IWB + Esporta come file IWB Exporting document... - Esportazione documento in corso... + Esportazione documento in corso... Export successful. - Esportazione conclusa con successo. + Esportazione conclusa con successo. Export failed. - Esportazione fallita. + Esportazione fallita. @@ -1282,19 +1282,19 @@ Export to OpenBoard Format - + Esporta nel formato OpenBoard Export failed: location not writable - + Exportazione fallita: posizione non scrivibile Export failed - + Esportazione fallita Unable to export to the selected location. You do not have the permissions necessary to save the file. - + Impossibile esportare nella posizione selezionata. Non possiedi i permessi necessari a salvare il file. @@ -1317,15 +1317,15 @@ Export failed: location not writable - + Esportazione fallita: posizione non scrivibile Export failed - + Esportazione fallita Unable to export to the selected location. You do not have the permissions necessary to save the file. - + Impossibile esportare alla posizione selezionata. Non possiedi i permessi necessari a salvare il file. @@ -1531,19 +1531,19 @@ UBGraphicsMediaItem Media resource couldn't be resolved - + La risorsa multimediale non può essere gestita Unsupported media format - + Formato multimediale non supportato Media playback service not found - + Servizio di esecuzione multimediale non trovato Media error: - + Errore multimediale: @@ -1593,23 +1593,23 @@ UBImportCFF Common File Format ( - Common File Format ( + Common File Format ( Importing file %1... - Importazione del file %1 in corso... + Importazione del file %1 in corso... Import of file %1 failed. - L'importazione del file %1 è fallita. + L'importazione del file %1 è fallita. Import successful. - Importazione completata con successo. + Importazione completata con successo. Import failed. - Importazione fallita. + Importazione fallita. @@ -1628,7 +1628,7 @@ OpenBoard (*.ubz) - + OpenBoard (*.ubz) @@ -1739,27 +1739,27 @@ Vuoi ignorare gli errori per questo host? UBOpenSankoreImporterWidget Open-Sankore Documents Detected - + Rilevati documenti Open-Sankore Show this panel next time - + Mostra questo pannello la prossima volta You can always access the OpenBoard Document Importer through the Preferences panel in the About tab. Warning, if you have already imported your Open-Sankore datas, you might loose your current OpenBoard documents. - + È sempre possibile accedere all'importatore di documenti OpenBoard tramite il pannello delle preferenze nella scheda delle informazioni su OpenBoard. Attenzione, se si è già importato dati Open-Sankore, è possibile perdere i documenti OpenBoard correnti. Cancel - Annulla + Annulla Proceed - + Procedi Open-Sankoré documents are present on your computer. It is possible to import them to OpenBoard by pressing the “Proceed” button to launch the importer application. - + Documenti Open-Sankoré sono presenti nel computer. È possibile importarli in OpenBoard premendo il pulsante “Procedi” per avviare l'applicazione di importazione. @@ -1774,7 +1774,7 @@ Vuoi ignorare gli errori per questo host? has lost access to the document repository '%1'. Unfortunately the application must shut down to avoid data corruption. Latest changes may be lost as well. - + ha perso l'accesso al repository documenti "%1". Sfortunatamente l'applicazione deve essere chiusa per evitare di rivinare i dati. Gli ultimi cambiamenti potrebbero andare persi. @@ -1860,7 +1860,7 @@ Vuoi ignorare gli errori per questo host? OpenBoard Cast - + OpenBoard Cast @@ -1919,7 +1919,7 @@ Vuoi ignorare gli errori per questo host? UBStartupHintsPalette Visible next time - + Visibile la prossima volta @@ -2319,7 +2319,7 @@ Si prega di riavviare l'applicazione per accedere ai documenti aggiornati.< Download PDF Document: would you prefer to download the PDF file or add it to the current OpenBoard document? - + Scarica il documento PDF: preferisci scaricare il file PDF o aggiungerlo al documento OpenBoard corrente? @@ -2373,11 +2373,11 @@ p, li { white-space: pre-wrap; } Restore credentials on reboot - + Ripristina le credenziali al riavvio OpenBoard - OpenBoard + OpenBoard @@ -2442,7 +2442,7 @@ p, li { white-space: pre-wrap; } documents OpenBoard Documents - + Documenti OpenBoard @@ -2485,7 +2485,7 @@ p, li { white-space: pre-wrap; } Keyboard button size: - Dimensione pulsanti tastiera: + Dimensione pulsanti tastiera: Toolbar @@ -2585,19 +2585,19 @@ p, li { white-space: pre-wrap; } Open-Sankoré Importer - + Apri l'importatore Open-Sankoré Check if Open-Sankoré data could be imported at launch - + Controlla se i dati Open-Sankoré possono venir importati all'avvio Use system keyboard (recommended) - + Usa la tastiera di sistema (raccomandato) Built-in virtual keyboard button size: - + Dimensione pulsanti tastiera virtuale incorporata: From 425129ff2f18d3dd97045eed8d376ad31980014a Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sun, 14 May 2017 12:07:56 -0400 Subject: [PATCH 14/14] Document mode: improved doc. selection after deleting documents This mainly changes document mode behaviour in two ways: 1) When deleting 2+ items, a new document was selected in the list. Now, the current document is selected, or if it has been deleted, a the first document in the list is set as current document. 2) When deleting the last item in the trash, no document was selected. Now, the current document is selected instead. --- src/document/UBDocumentController.cpp | 70 ++++++++++++++++++++------- src/document/UBDocumentController.h | 3 +- 2 files changed, 55 insertions(+), 18 deletions(-) diff --git a/src/document/UBDocumentController.cpp b/src/document/UBDocumentController.cpp index 2910e785..088544f8 100644 --- a/src/document/UBDocumentController.cpp +++ b/src/document/UBDocumentController.cpp @@ -546,37 +546,66 @@ void UBDocumentController::duplicateSelectedItem() } /** - * @brief When deleting multiple documents, find a new document and select it + * @brief Set the first document in the list as current document * - * This method simply selects the first un-selected document + * If there are no documents, a new one is created. */ -void UBDocumentController::selectADocumentOnMultipleTrashing() +void UBDocumentController::selectFirstDocumentInList() { - // Loop through all folders, and each document in those folders, until we find - // a document that is not in the current selection (which is being deleted) + // Loop through all folders until we find one that is not the trash and not empty, + // and select the first document in that folder for (int i(0); i < mDocumentUI->documentTreeWidget->topLevelItemCount(); ++i) { QTreeWidgetItem* item = mDocumentUI->documentTreeWidget->topLevelItem(i); UBDocumentGroupTreeItem* groupItem = dynamic_cast(item); - if (!groupItem->isTrashFolder()) { - for (int j(0); j < groupItem->childCount(); ++j) { - if (!mCurrentSelection.contains( groupItem->child(j) )) { - selectDocument(((UBDocumentProxyTreeItem*)groupItem->child(j))->proxy(), true); - return; - } - } + if (!groupItem->isTrashFolder() && groupItem->childCount() > 0) { + selectDocument(((UBDocumentProxyTreeItem*)groupItem->child(0))->proxy(), true); + groupItem->child(0)->setSelected(true); + return; } } - - // No document found => create a new one UBDocumentGroupTreeItem* topFolder = dynamic_cast(mDocumentUI->documentTreeWidget->topLevelItem(0)); UBDocumentProxy* document = UBPersistenceManager::persistenceManager()->createDocument(topFolder->groupName()); selectDocument(document, true); +} + +/** + * @brief Find the current document, and select it in the list + * + * If selectNewCurrentDocument is true, the first document in the list is selected and set as + * current document. + */ +void UBDocumentController::selectATreeItemOnMultipleTrashing(bool selectNewCurrentDocument) +{ + mCurrentSelection.clear(); + + if (selectNewCurrentDocument) { + selectFirstDocumentInList(); + return; + } + + // Find the currently selected document, and select its corresponding tree item + // If it isn't found, then the first document in the list is selected and set as current document + + for (int i(0); i < mDocumentUI->documentTreeWidget->topLevelItemCount(); i++) { + QTreeWidgetItem* item = mDocumentUI->documentTreeWidget->topLevelItem(i); + UBDocumentGroupTreeItem* groupItem = dynamic_cast(item); + if (!groupItem->isTrashFolder()) { + for (int j(0); j < groupItem->childCount(); j++) { + if (((UBDocumentProxyTreeItem*)groupItem->child(j))->proxy() == mBoardController->selectedDocument()) { + ((UBDocumentProxyTreeItem*)groupItem->child(j))->setSelected(true); + return; + } + } + } + } + + selectFirstDocumentInList(); } void UBDocumentController::selectADocumentOnTrashingSelectedOne(UBDocumentGroupTreeItem* groupTi,UBDocumentProxyTreeItem *proxyTi) @@ -807,7 +836,7 @@ void UBDocumentController::deleteTreeItem(QTreeWidgetItem * item, bool showConfi if (selectNewDocument) { if (mTrashTi->childCount()==0) - selectDocument(NULL); + selectATreeItemOnMultipleTrashing(false); else selectDocument(((UBDocumentProxyTreeItem*)mTrashTi->child(0))->proxy(), false); } @@ -849,11 +878,18 @@ void UBDocumentController::deleteSelectedItem() QList foldersToDelete; + bool currentDocumentDeleted = false; + foreach (QTreeWidgetItem * item, mCurrentSelection) { LastSelectedElementType type = itemType(item); - if (type == Document) + if (type == Document) { deleteTreeItem(item, false, false); + UBDocumentProxyTreeItem* proxyItem = dynamic_cast(item); + if (proxyItem && proxyItem->proxy() && (proxyItem->proxy() == mBoardController->selectedDocument())) + currentDocumentDeleted = true; + } + else if (type == Folder) // Delete folders later, to avoid deleting a document twice foldersToDelete << item; @@ -863,7 +899,7 @@ void UBDocumentController::deleteSelectedItem() deleteTreeItem(item, false, false); } - selectADocumentOnMultipleTrashing(); + selectATreeItemOnMultipleTrashing(currentDocumentDeleted); } else if (mSelectionType == Document || mSelectionType == Folder) { diff --git a/src/document/UBDocumentController.h b/src/document/UBDocumentController.h index 39e5f635..62160800 100644 --- a/src/document/UBDocumentController.h +++ b/src/document/UBDocumentController.h @@ -130,7 +130,8 @@ class UBDocumentController : public UBDocumentContainer QString mDefaultDocumentGroupName; void selectADocumentOnTrashingSelectedOne(UBDocumentGroupTreeItem* groupTi,UBDocumentProxyTreeItem *proxyTi); - void selectADocumentOnMultipleTrashing(); + void selectFirstDocumentInList(); + void selectATreeItemOnMultipleTrashing(bool selectNewCurrentDocument = false); void moveDocumentToTrash(UBDocumentGroupTreeItem* groupTi, UBDocumentProxyTreeItem *proxyTi, bool selectNewDocument); void moveFolderToTrash(UBDocumentGroupTreeItem* groupTi); void emptyTrash(bool showConfirmationDialog);