diff --git a/.gitignore b/.gitignore
index 6de0441e..46f6fb9f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -55,6 +55,7 @@ Makefile.Sankore*
# Build files #
###############
+.qmake.stash
build
install
Makefile
diff --git a/OpenBoard.pro b/OpenBoard.pro
index 2de5b263..ef132b74 100644
--- a/OpenBoard.pro
+++ b/OpenBoard.pro
@@ -1,7 +1,7 @@
TARGET = "OpenBoard"
TEMPLATE = app
-CONFIG += c++14
+CONFIG += c++17
CONFIG -= flat
CONFIG += debug_and_release \
no_include_pwd
@@ -9,9 +9,9 @@ CONFIG += debug_and_release \
VERSION_MAJ = 1
VERSION_MIN = 6
-VERSION_PATCH = 1
-VERSION_TYPE = r # a = alpha, b = beta, rc = release candidate, r = release, other => error
-VERSION_BUILD = 0309
+VERSION_PATCH = 2
+VERSION_TYPE = rc # a = alpha, b = beta, rc = release candidate, r = release, other => error
+VERSION_BUILD = 0408
VERSION = "$${VERSION_MAJ}.$${VERSION_MIN}.$${VERSION_PATCH}-$${VERSION_TYPE}.$${VERSION_BUILD}"
@@ -40,6 +40,7 @@ QT += webkitwidgets
QT += multimediawidgets
QT += printsupport
QT += core
+QT += concurrent
INCLUDEPATH += src
@@ -57,7 +58,8 @@ include(src/podcast/podcast.pri)
include(src/tools/tools.pri)
include(src/desktop/desktop.pri)
include(src/web/web.pri)
-include(src/qtsingleapplication/src/qtsingleapplication.pri)
+include(src/singleapplication/singleapplication.pri)
+DEFINES += QAPPLICATION_CLASS=QApplication
DEPENDPATH += src/pdf-merger
INCLUDEPATH += src/pdf-merger
@@ -177,26 +179,25 @@ macx {
equals(QT_MAJOR_VERSION, 5):lessThan(QT_MINOR_VERSION, 14) {
LIBS += "-L../OpenBoard-ThirdParty/quazip/lib/macx" "-lquazip"
} else {
- LIBS += -L/usr/local/opt/quazip/lib -lquazip
+ LIBS += -L/usr/local/opt/quazip/lib -lquazip1-qt5
}
- LIBS += -L/usr/local/opt/ffmpeg/lib
+ LIBS += -L/opt/local/lib
INCLUDEPATH += /usr/local/opt/openssl/include
- INCLUDEPATH += /usr/local/opt/ffmpeg/include
+ INCLUDEPATH += /opt/local/include
equals(QT_MAJOR_VERSION, 5):lessThan(QT_MINOR_VERSION, 14) {
INCLUDEPATH += ../OpenBoard-ThirdParty/quazip/quazip-0.7.1
} else {
INCLUDEPATH += /usr/local/opt/quazip/include/quazip
}
- LIBS += -L/usr/local/opt/poppler/lib -lpoppler
- INCLUDEPATH += /usr/local/opt/poppler/include
- INCLUDEPATH += /usr/local/opt/poppler/include/poppler
+ LIBS += -L/opt/local/lib -lpoppler
+ INCLUDEPATH += /opt/local/include/poppler
CONFIG(release, debug|release):CONFIG += x86_64
CONFIG(debug, debug|release):CONFIG += x86_64
QMAKE_MAC_SDK = macosx
- QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.10
+ QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.13
QMAKE_CXXFLAGS += -Wno-overloaded-virtual
#VERSION_RC_PATH = "$$BUILD_DIR/version_rc"
@@ -451,7 +452,7 @@ linux-g++* {
#LIBS += -lprofiler
LIBS += -lX11
LIBS += -lquazip5
- INCLUDEPATH += "/usr/include/quazip"
+ INCLUDEPATH += "/usr/include/quazip5"
LIBS += -lpoppler
INCLUDEPATH += "/usr/include/poppler"
diff --git a/README.md b/README.md
index 35623702..d90a97d3 100644
--- a/README.md
+++ b/README.md
@@ -1,38 +1,14 @@
# OpenBoard
OpenBoard is an open source cross-platform interactive white board application designed primarily for use in schools. It was originally forked from Open-Sankoré, which was itself based on Uniboard.
-Supported platforms are Windows (7+), OS X (10.9+) and Linux (tested on Ubuntu 16.04).
-
+Supported platforms are Windows (10+), OS X (10.13+) and Linux (Ubuntu 20.04 is the only officially maintained platform, but many others are reported by the community to work).
## Installing
-Installers are available for Windows, OS X and Ubuntu on the [wiki](https://github.com/DIP-SEM/OpenBoard/wiki/Downloads).
+Installers are available for Windows, OS X and Ubuntu on the [wiki](https://github.com/OpenBoard-org/OpenBoard/wiki/Downloads).
## Building from source
-First, obtain the third party libraries from the OpenBoard-ThirdParty repository, and build them (instructions are provided for each library).
-
-Then, you may use the build (and packaging) scripts which are provided for all three platforms. These take care of compiling OpenBoard, including the translations (for OpenBoard and for Qt), stripping the debug symbols, creating the installers etc.
-Minor modification to those scripts may be necessary depending on your configuration, to set the correct Qt path for example.
-
-Alternatively, you can easily build OpenBoard with qmake and make:
-
- qmake OpenBoard.pro -spec linux-g++-64 # replace linux-g++-64 by macx or win32 for other platforms
- make
-
-Compilers used are gcc (Linux), clang (OS X) and MSVC 2010 (Windows). Make sure that your version of Qt matches this, as it is not possible e.g to build OpenBoard with clang if Qt was built with gcc.
+Please follow instructions available on the [wiki](https://github.com/OpenBoard-org/OpenBoard/wiki/Build-from-source)
## Dependencies
-The latest version (1.5) requires Qt 5.5. (While it has been shown to mostly work with Qt 5.2, we cannot guarantee compatibility with Qt versions other than 5.5.)
-
-### Qt 5.5 on Linux
-
-Due to a shared library conflict within Qt 5 in some distributions / some Qt versions (the Multimedia and Webkit modules were built against different versions of gstreamer by default), a specific installation of Qt5.5 may be needed for all of OpenBoard's features to work correctly.
-
-It can either be built from source, with the configure flag `-gstreamer 1.0` (see [here](http://doc.qt.io/qt-5/linux-building.html)), or installed from Stephan Binner's PPAs on Ubuntu.
-In the latter case, simply add the repositories and install Qt 5.5.1 like so (example provided for Ubuntu 14.04, aka "Trusty"):
-
- sudo add-apt-repository ppa:beineri/opt-qt551-trusty
- sudo apt-get update
- sudo apt-get install qt-latest
-
-Some distributions, such as Ubuntu 16.04, provide Qt 5.5.1 packages that work perfectly with OpenBoard, so you can simply install Qt from the official repository.
+The latest version (1.6.1) can be compiled with the latest open source binaries of Qt 5.15. While it has been shown to work with Qt 5.9 or any other version in between, we recommend that you use the latest version you can.
diff --git a/release_scripts/linux/build.sh b/release_scripts/linux/build.sh
index 3918fc43..e882f622 100755
--- a/release_scripts/linux/build.sh
+++ b/release_scripts/linux/build.sh
@@ -17,7 +17,7 @@
initializeVariables()
{
APPLICATION_NAME="OpenBoard"
- STANDARD_QT_USED=false
+ STANDARD_QT_USED=true
# Root directory
SCRIPT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
@@ -26,7 +26,7 @@ initializeVariables()
PRODUCT_PATH="$BUILD_DIR/product"
# Qt installation path. This may vary across machines
- QT_PATH="/home/dev/Qt/5.15.0/gcc_64"
+ QT_PATH="/usr/lib/x86_64-linux-gnu/qt5"
PLUGINS_PATH="$QT_PATH/plugins"
GUI_TRANSLATIONS_DIRECTORY_PATH="/usr/share/qt5/translations"
QMAKE_PATH="$QT_PATH/bin/qmake"
@@ -39,6 +39,9 @@ initializeVariables()
ARCHITECTURE=`uname -m`
if [ $ARCHITECTURE == "x86_64" ]; then
ARCHITECTURE="amd64"
+ elif [$ARCHITECTURE == "armv7l" ]; then
+ $ARCHITECTURE="armhf"
+ QT_PATH="/usr/lib/arm-linux-gnueabihf/qt5"
fi
fi
}
diff --git a/release_scripts/linux/package.sh b/release_scripts/linux/package.sh
index c53e3081..2014c3c7 100755
--- a/release_scripts/linux/package.sh
+++ b/release_scripts/linux/package.sh
@@ -85,13 +85,13 @@ initializeVariables()
# Include Qt libraries and plugins in the package, or not
# (this is necessary if the target system doesn't provide Qt 5.5.1)
- BUNDLE_QT=true
+ BUNDLE_QT=false
# Qt installation path. This may vary across machines
- QT_PATH="/home/dev/Qt/5.15.0/gcc_64"
+ QT_PATH="/usr/lib/x86_64-linux-gnu/qt5"
QT_PLUGINS_SOURCE_PATH="$QT_PATH/plugins"
GUI_TRANSLATIONS_DIRECTORY_PATH="/usr/share/qt5/translations"
- QT_LIBRARY_SOURCE_PATH="$QT_PATH/lib"
+ QT_LIBRARY_SOURCE_PATH="$QT_PATH/.."
NOTIFY_CMD=`which notify-send`
ZIP_PATH=`which zip`
@@ -180,6 +180,7 @@ chown -R root:root $PACKAGE_DIRECTORY
cp -R resources/customizations $PACKAGE_DIRECTORY/
cp resources/linux/openboard-ubz.xml $PACKAGE_DIRECTORY/etc/
+cp resources/linux/application-ubz.png $PACKAGE_DIRECTORY/etc/
if $BUNDLE_QT; then
cp -R resources/linux/run.sh $PACKAGE_DIRECTORY/
@@ -214,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
@@ -287,6 +289,7 @@ cat > "$BASE_WORKING_DIR/DEBIAN/postinst" << EOF
xdg-desktop-menu install --novendor /usr/share/applications/${APPLICATION_CODE}.desktop
xdg-mime install --mode system /$APPLICATION_PATH/$APPLICATION_CODE/etc/openboard-ubz.xml
xdg-mime default /usr/share/applications/${APPLICATION_CODE}.desktop application/ubz
+xdg-icon-resource install --context mimetypes --size 48 /$APPLICATION_PATH/$APPLICATION_CODE/etc/application-ubz.png application-ubz
ln -s $SYMLINK_TARGET /usr/bin/$APPLICATION_CODE
@@ -400,8 +403,6 @@ echo "MimeType=application/ubz" >> $APPLICATION_SHORTCUT
echo "Categories=Education;" >> $APPLICATION_SHORTCUT
cp "resources/images/${APPLICATION_NAME}.png" "$PACKAGE_DIRECTORY/${APPLICATION_NAME}.png"
-
-
# ----------------------------------------------------------------------------
# Building the package
# ----------------------------------------------------------------------------
diff --git a/release_scripts/osx/release.macx.sh b/release_scripts/osx/release.macx.sh
index 376fdb68..456b3e90 100755
--- a/release_scripts/osx/release.macx.sh
+++ b/release_scripts/osx/release.macx.sh
@@ -19,7 +19,7 @@ PROJECT_ROOT="$SCRIPT_PATH/../.."
APPLICATION_NAME="OpenBoard"
-BASE_QT_DIR=~/Qt/5.15.0/clang_64
+BASE_QT_DIR=~/Qt/5.15.2/clang_64
# Executables
QMAKE=$BASE_QT_DIR/bin/qmake
MACDEPLOYQT=$BASE_QT_DIR/bin/macdeployqt
@@ -99,7 +99,7 @@ function addImporter {
rm MakeFile*
rm -rf release
rm -rf debug
- $QMAKE ${importerName}.pro
+ $QMAKE ${importerName}.pro -spec macx-clang
make -j4 release
$MACDEPLOYQT ${importerName}.app
cd -
@@ -143,9 +143,9 @@ notify "Generating Makefile ..."
if [ "$1" == "1010" ]; then
- QMAKE_CMD="$QMAKE \"DEFINES+=OS_NEWER_THAN_OR_EQUAL_TO_1010\" $APPLICATION_NAME.pro -spec macx-g++"
+ QMAKE_CMD="$QMAKE \"DEFINES+=OS_NEWER_THAN_OR_EQUAL_TO_1010\" $APPLICATION_NAME.pro -spec macx-clang"
else
- QMAKE_CMD="$QMAKE $APPLICATION_NAME.pro -spec macx-g++"
+ QMAKE_CMD="$QMAKE $APPLICATION_NAME.pro -spec macx-clang"
fi
$QMAKE_CMD
@@ -192,7 +192,7 @@ rm -f "$APP/Contents/Resources/empty.lproj"
# set various version infomration in Info.plist
$PLISTBUDDY -c "Set :CFBundleVersion $VERSION" "$INFO_PLIST"
$PLISTBUDDY -c "Set :CFBundleShortVersionString $VERSION" "$INFO_PLIST"
-$PLISTBUDDY -c "Set :CFBundleGetInfoString $APPLICATION_NAME" "$INFO_PLIST"
+$PLISTBUDDY -c "Set :CFBundleGetInfoString $VERSION" "$INFO_PLIST"
# bundle Qt Frameworks into the app bundle
notify "Bulding frameworks ..."
@@ -200,32 +200,6 @@ cd "`pwd`/build/macx/release/product/"
$MACDEPLOYQT "`pwd`/$APPLICATION_NAME.app"
cd -
-# make sure libs installed via homebrew 2.0 refer to in-app libs
- notify "relinking libs ..."
-# libavformat
-install_name_tool "$APP/Contents/Frameworks/libavformat.58.dylib" -change /usr/local/Cellar/ffmpeg/4.3.1_1/lib/libavcodec.58.dylib @executable_path/../Frameworks/libavcodec.58.dylib
-install_name_tool "$APP/Contents/Frameworks/libavformat.58.dylib" -change /usr/local/Cellar/ffmpeg/4.3.1_1/lib/libswresample.3.dylib @executable_path/../Frameworks/libswresample.3.dylib
-install_name_tool "$APP/Contents/Frameworks/libavformat.58.dylib" -change /usr/local/Cellar/ffmpeg/4.3.1_1/lib/libavutil.56.dylib @executable_path/../Frameworks/libavutil.56.dylib
-
-# libavcodec
-install_name_tool "$APP/Contents/Frameworks/libavcodec.58.dylib" -change /usr/local/Cellar/ffmpeg/4.3.1_1/lib/libswresample.3.dylib @executable_path/../Frameworks/libswresample.3.dylib
-install_name_tool "$APP/Contents/Frameworks/libavcodec.58.dylib" -change /usr/local/Cellar/ffmpeg/4.3.1_1/lib/libavutil.56.dylib @executable_path/../Frameworks/libavutil.56.dylib
-
-#libswresample
-install_name_tool "$APP/Contents/Frameworks/libswresample.3.dylib" -change /usr/local/Cellar/ffmpeg/4.3.1_1/lib/libavutil.56.dylib @executable_path/../Frameworks/libavutil.56.dylib
-
-#libswscale
-install_name_tool "$APP/Contents/Frameworks/libswscale.5.dylib" -change /usr/local/Cellar/ffmpeg/4.3.1_1/lib/libavutil.56.dylib @executable_path/../Frameworks/libavutil.56.dylib
-
-# libhogweed
-install_name_tool "$APP/Contents/Frameworks/libhogweed.6.dylib" -change /usr/local/Cellar/nettle/3.6/lib/libnettle.8.dylib @executable_path/../Frameworks/libnettle.8.dylib
-
-# libssl
-install_name_tool "$APP/Contents/Frameworks/libssl.1.1.dylib" -change /usr/local/Cellar/openssl@1.1/1.1.1h/lib/libcrypto.1.1.dylib @executable_path/../Frameworks/libcrypto.1.1.dylib
-
-# libvorbis
-install_name_tool "$APP/Contents/Frameworks/libvorbisenc.2.dylib" -change /usr/local/Cellar/libvorbis/1.3.6/lib/libvorbis.0.dylib @executable_path/../Frameworks/libvorbis.0.dylib
-
notify "Extracting debug information ..."
$DSYMUTIL "$APP/Contents/MacOS/$APPLICATION_NAME" -o "$DSYM"
$STRIP -S "$APP/Contents/MacOS/$APPLICATION_NAME"
diff --git a/resources/OpenBoard.qrc b/resources/OpenBoard.qrc
index 9327c9e7..d1a5661f 100644
--- a/resources/OpenBoard.qrc
+++ b/resources/OpenBoard.qrc
@@ -378,5 +378,12 @@
images/stylusPalette/pen.svgimages/stylusPalette/penOn.svgimages/stylusPalette/penOnArrow.svg
+ images/trash-my-documents.png
+ images/trash-empty.png
+ images/trash-folder.png
+ images/trash-delete-document.png
+ images/trash-delete-folder.png
+ images/trash-document.png
+ images/trash-document-page.png
diff --git a/resources/etc/OpenBoard.config b/resources/etc/OpenBoard.config
index 5d29fb4b..77eea8d1 100644
--- a/resources/etc/OpenBoard.config
+++ b/resources/etc/OpenBoard.config
@@ -124,6 +124,8 @@ RefreshRateInFramePerSecond=2
[PDF]
enableQualityLossToIncreaseZoomPerfs=true
+ExportBackgroundGrid=false
+ExportBackgroundColor=false
Margin=20
PageFormat=A4
Resolution=300
@@ -147,11 +149,8 @@ ReplyPlusMaxKeypads=100
ReplyWWSerialPort=3
[Web]
-AddBookmarkURL="http://www.myuniboard.com/bookmarks/save/?url="
-BookmarksPage=http://www.myuniboard.com
HistoryLimit=15
Homepage=http://www.openboard.ch
-ShowAddBookmarkButton=true
ShowPageImediatelyOnMirroredScreen=false
UseExternalBrowser=false
diff --git a/resources/forms/mainWindow.ui b/resources/forms/mainWindow.ui
index 052230ac..a24810b4 100644
--- a/resources/forms/mainWindow.ui
+++ b/resources/forms/mainWindow.ui
@@ -1497,16 +1497,16 @@
Configure Podcast Recording
-
+ :/images/toolbar/addToolToLibrary.png:/images/toolbar/addToolToLibrary.png
- Flash Trap
+ Capture Web Content
- Trap Flash Content
+ Capture Web Content
diff --git a/resources/forms/trapFlash.ui b/resources/forms/trapFlash.ui
index 2a7f4a69..00c36a00 100644
--- a/resources/forms/trapFlash.ui
+++ b/resources/forms/trapFlash.ui
@@ -19,7 +19,7 @@
- Select a flash to trap
+ Select a content to capture
diff --git a/resources/i18n/OpenBoard_ar.ts b/resources/i18n/OpenBoard_ar.ts
index 9ad98c6d..3f19c962 100644
--- a/resources/i18n/OpenBoard_ar.ts
+++ b/resources/i18n/OpenBoard_ar.ts
@@ -697,11 +697,11 @@
Flash Trap
- قلاش تراب
+ قلاش ترابTrap Flash Content
- محتوى فلاش تراب
+ محتوى فلاش ترابWeb Trap
@@ -839,6 +839,10 @@
Draw intermediate grid lines
+
+ Capture Web Content
+
+ PasswordDialog
@@ -896,6 +900,14 @@
Are you sure you want to remove 1 page from the selected document '%0'?هل تريدون حقا إزالة صفحة واحدة من الوثيقة '%0' المختارة؟
+
+ Loading scene (%1/%2)
+
+
+
+ Moving cached scenes (%1/%2)
+
+ UBApplication
@@ -907,6 +919,10 @@
Podcastبودكاست
+
+ Cannot open your UBX file directly. Please import it in Documents mode instead
+
+ UBApplicationController
@@ -1235,6 +1251,10 @@
Title page
+
+ Refreshing Document Thumbnails View (%1/%2)
+
+ UBDocumentManager
@@ -1285,6 +1305,10 @@
Page %0صفحة %0
+
+ Generating thumbnails for board (%1/%2)
+
+ UBDocumentPublisher
@@ -1985,6 +2009,10 @@ Do you want to ignore these errors for this host?
OpenBoard 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.
+
+ Renaming pages (%1/%2)
+
+ UBPlatformUtils
@@ -2148,6 +2176,10 @@ Do you want to ignore these errors for this host?
%1 thumbnails generated ...1 % صور مصغرة مولّدة
+
+ Loading thumbnail (%1/%2)
+
+ UBThumbnailTextItem
@@ -2924,7 +2956,7 @@ p, li { white-space: pre-wrap; }
Select a flash to trap
- اختيار فلاش للامساك به
+ اختيار فلاش للامساك بهabout:blank
@@ -2938,5 +2970,9 @@ p, li { white-space: pre-wrap; }
Create Applicationإنشاء تطبيق
+
+ Select a content to capture
+
+
diff --git a/resources/i18n/OpenBoard_bg.ts b/resources/i18n/OpenBoard_bg.ts
index 303f13a3..1628b746 100644
--- a/resources/i18n/OpenBoard_bg.ts
+++ b/resources/i18n/OpenBoard_bg.ts
@@ -697,11 +697,11 @@
Flash Trap
- Инструмент за Flash съдържание
+ Инструмент за Flash съдържаниеTrap Flash Content
- Съдържание на Flash
+ Съдържание на FlashWeb Trap
@@ -839,6 +839,10 @@
Draw intermediate grid lines
+
+ Capture Web Content
+
+ PasswordDialog
@@ -896,6 +900,14 @@
Are you sure you want to remove 1 page from the selected document '%0'?Сигурни ли сте ,че искате да премахнете 1 страница от избрания документ '%0'?
+
+ Loading scene (%1/%2)
+
+
+
+ Moving cached scenes (%1/%2)
+
+ UBApplication
@@ -907,6 +919,10 @@
PodcastПодкаст
+
+ Cannot open your UBX file directly. Please import it in Documents mode instead
+
+ UBApplicationController
@@ -1227,6 +1243,10 @@
Title page
+
+ Refreshing Document Thumbnails View (%1/%2)
+
+ UBDocumentManager
@@ -1277,6 +1297,10 @@
Page %0Страница %0
+
+ Generating thumbnails for board (%1/%2)
+
+ UBDocumentReplaceDialog
@@ -1964,6 +1988,10 @@ Do you want to ignore these errors for this host?
OpenBoard 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.
+
+ Renaming pages (%1/%2)
+
+ UBPlatformUtils
@@ -2127,6 +2155,10 @@ Do you want to ignore these errors for this host?
%1 thumbnails generated ...%1 икони са създадени ...
+
+ Loading thumbnail (%1/%2)
+
+ UBThumbnailTextItem
@@ -2904,7 +2936,7 @@ p, li { white-space: pre-wrap; }
Select a flash to trap
- Избери флаш , който ще използваш
+ Избери флаш , който ще използвашabout:blank
@@ -2918,5 +2950,9 @@ p, li { white-space: pre-wrap; }
Create ApplicationСъздаване на приложение
+
+ Select a content to capture
+
+
diff --git a/resources/i18n/OpenBoard_ca.ts b/resources/i18n/OpenBoard_ca.ts
index e7b01e8d..e18fcfd4 100644
--- a/resources/i18n/OpenBoard_ca.ts
+++ b/resources/i18n/OpenBoard_ca.ts
@@ -729,11 +729,11 @@
Flash Trap
- Captura d'objectes Flash
+ Captura d'objectes FlashTrap Flash Content
- Captura un objecte Flash
+ Captura un objecte FlashWeb Trap
@@ -839,6 +839,10 @@
Draw intermediate grid lines
+
+ Capture Web Content
+
+ PasswordDialog
@@ -896,6 +900,14 @@
Are you sure you want to remove 1 page from the selected document '%0'?Esteu segur que voleu eliminar 1 pàgina del document seleccionat '%0'?
+
+ Loading scene (%1/%2)
+
+
+
+ Moving cached scenes (%1/%2)
+
+ UBApplication
@@ -907,6 +919,10 @@
PodcastPodcast
+
+ Cannot open your UBX file directly. Please import it in Documents mode instead
+
+ UBApplicationController
@@ -1226,6 +1242,10 @@
Title page
+
+ Refreshing Document Thumbnails View (%1/%2)
+
+ UBDocumentManager
@@ -1276,6 +1296,10 @@
Page %0Pàgina %0
+
+ Generating thumbnails for board (%1/%2)
+
+ UBDocumentPublisher
@@ -1970,6 +1994,10 @@ Voleu ignorar aquests errors per a aquest amfitrió?
OpenBoard 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.
+
+ Renaming pages (%1/%2)
+
+ UBPlatformUtils
@@ -2126,6 +2154,10 @@ Voleu ignorar aquests errors per a aquest amfitrió?
%1 thumbnails generated ...S'han generat %1 miniatures...
+
+ Loading thumbnail (%1/%2)
+
+ UBThumbnailTextItem
@@ -2904,7 +2936,7 @@ p, li { white-space: pre-wrap; }
Select a flash to trap
- Seleccioneu l'objecte Flash a capturar
+ Seleccioneu l'objecte Flash a capturarabout:blank
@@ -2918,5 +2950,9 @@ p, li { white-space: pre-wrap; }
Create ApplicationCrea una aplicació
+
+ Select a content to capture
+
+
diff --git a/resources/i18n/OpenBoard_cs.ts b/resources/i18n/OpenBoard_cs.ts
index 92187e20..2860b481 100644
--- a/resources/i18n/OpenBoard_cs.ts
+++ b/resources/i18n/OpenBoard_cs.ts
@@ -374,7 +374,7 @@
Trap Flash Content
- Přenést obsah ve Flashi
+ Přenést obsah ve FlashiImport
@@ -562,7 +562,7 @@
Flash Trap
- Přenést Flash
+ Přenést FlashWindow Capture
@@ -840,6 +840,10 @@
Draw intermediate grid lines
+
+ Capture Web Content
+
+ PasswordDialog
@@ -897,6 +901,14 @@
Are you sure you want to remove 1 page from the selected document '%0'?Opravdu chcete odstranit 1 stránku z vybraného dokumentu '%0'?
+
+ Loading scene (%1/%2)
+
+
+
+ Moving cached scenes (%1/%2)
+
+ UBApplication
@@ -908,6 +920,10 @@
Page SizeVelikost stránky
+
+ Cannot open your UBX file directly. Please import it in Documents mode instead
+
+ UBApplicationController
@@ -1229,6 +1245,10 @@
Title page
+
+ Refreshing Document Thumbnails View (%1/%2)
+
+ UBDocumentManager
@@ -1279,6 +1299,10 @@
Page %0Stránka %0
+
+ Generating thumbnails for board (%1/%2)
+
+ UBDocumentReplaceDialog
@@ -1969,6 +1993,10 @@ Chcete ignorovat tyto chyby na tomto serveru?
OpenBoard 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.
+
+ Renaming pages (%1/%2)
+
+ UBPlatformUtils
@@ -2132,6 +2160,10 @@ Chcete ignorovat tyto chyby na tomto serveru?
Generating preview thumbnails ...Vytváří se miniatury obrázků ...
+
+ Loading thumbnail (%1/%2)
+
+ UBThumbnailTextItem
@@ -2910,7 +2942,7 @@ p, li { white-space: pre-wrap; }
Select a flash to trap
- Vyberte flash, který chcete přenést
+ Vyberte flash, který chcete přenéstabout:blank
@@ -2924,5 +2956,9 @@ p, li { white-space: pre-wrap; }
Create ApplicationVytvořit aplikaci
+
+ Select a content to capture
+
+
diff --git a/resources/i18n/OpenBoard_da.ts b/resources/i18n/OpenBoard_da.ts
index 60f55f91..35cd0e1c 100644
--- a/resources/i18n/OpenBoard_da.ts
+++ b/resources/i18n/OpenBoard_da.ts
@@ -697,11 +697,11 @@
Flash Trap
- Flash Trap
+ Flash TrapTrap Flash Content
- Opsaml Flash-indhold
+ Opsaml Flash-indholdWeb Trap
@@ -839,6 +839,10 @@
Draw intermediate grid lines
+
+ Capture Web Content
+
+ PasswordDialog
@@ -896,6 +900,14 @@
Are you sure you want to remove 1 page from the selected document '%0'?Er du sikker på, at du vil fjerne 1 side fra det valgte dokument'%0'?
+
+ Loading scene (%1/%2)
+
+
+
+ Moving cached scenes (%1/%2)
+
+ UBApplication
@@ -907,6 +919,10 @@
PodcastPodcast
+
+ Cannot open your UBX file directly. Please import it in Documents mode instead
+
+ UBApplicationController
@@ -1226,6 +1242,10 @@
Title page
+
+ Refreshing Document Thumbnails View (%1/%2)
+
+ UBDocumentManager
@@ -1276,6 +1296,10 @@
Page %0Side %0
+
+ Generating thumbnails for board (%1/%2)
+
+ UBDocumentPublisher
@@ -1970,6 +1994,10 @@ Do you want to ignore these errors for this host?
OpenBoard 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.
+
+ Renaming pages (%1/%2)
+
+ UBPlatformUtils
@@ -2133,6 +2161,10 @@ Do you want to ignore these errors for this host?
%1 thumbnails generated ...%1 miniaturebilleder genereret...
+
+ Loading thumbnail (%1/%2)
+
+ UBThumbnailTextItem
@@ -2907,7 +2939,7 @@ p, li { white-space: pre-wrap; }
Select a flash to trap
- Vælg en flash der skal opsamles
+ Vælg en flash der skal opsamlesabout:blank
@@ -2921,5 +2953,9 @@ p, li { white-space: pre-wrap; }
Create ApplicationOpret applikation
+
+ Select a content to capture
+
+
diff --git a/resources/i18n/OpenBoard_de.ts b/resources/i18n/OpenBoard_de.ts
index 9a67156d..c6305089 100644
--- a/resources/i18n/OpenBoard_de.ts
+++ b/resources/i18n/OpenBoard_de.ts
@@ -697,11 +697,11 @@
Flash Trap
- Einblendung einfangen
+ Einblendung einfangenTrap Flash Content
- Eingeblendeten Inhalt einfangen
+ Eingeblendeten Inhalt einfangenWeb Trap
@@ -839,6 +839,10 @@
Draw intermediate grid linesGitter-Zwischenlinien zeichnen
+
+ Capture Web Content
+ Webinhalte erfassen
+ PasswordDialog
@@ -896,6 +900,14 @@
Are you sure you want to remove 1 page from the selected document '%0'?Wollen Sie wirklich die ausgewählte Seite des Dokuments '%0' entfernen?
+
+ Loading scene (%1/%2)
+ Laden der Szene (%1/%2)
+
+
+ Moving cached scenes (%1/%2)
+ Verschieben von zwischengespeicherten Szenen (%1/%2)
+ UBApplication
@@ -907,6 +919,10 @@
PodcastPodcast
+
+ Cannot open your UBX file directly. Please import it in Documents mode instead
+ Ihre UBX-Datei kann nicht direkt geöffnet werden. Bitte importieren Sie die Datei im Dokumentenmodus
+ UBApplicationController
@@ -1242,6 +1258,10 @@
Empty My DocumentsEigene Dokumente leeren
+
+ Refreshing Document Thumbnails View (%1/%2)
+ Aktualisieren der Vorschauen im Dokumentenmodus (%1/%2)
+ UBDocumentManager
@@ -1292,6 +1312,10 @@
Page %0Seite %0
+
+ Generating thumbnails for board (%1/%2)
+ Erstellen von Voransichten des Tabellenmodus (%1/%2)
+ UBDocumentPublisher
@@ -2028,6 +2052,10 @@ Möchten Sie diese Fehler für diesen Computer ignorieren?
OpenBoard 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.Openboard hat den Zugang zum Dokumentenarchiv '%1' verloren. Die Anwendung muss leider beendet werden, um Datenkorruption zu vermeiden. Der Verlust kürzlich vorgenommener Änderungen ist möglich.
+
+ Renaming pages (%1/%2)
+ Aktualisieren der aktuellen Seitennamen (%1/%2)
+ UBPlatformUtils
@@ -2196,6 +2224,10 @@ Möchten Sie diese Fehler für diesen Computer ignorieren?
Miniaturansicht der Seite %1 wird geladen
+
+ Loading thumbnail (%1/%2)
+ Laden der Vorschau (%1/%2)
+ UBThumbnailTextItem
@@ -2978,7 +3010,7 @@ p, li { white-space: pre-wrap; }
Select a flash to trap
- Wählen Sie eine Einblendung, die festgehalten werden soll
+ Wählen Sie eine Einblendung, die festgehalten werden sollabout:blank
@@ -2992,5 +3024,9 @@ p, li { white-space: pre-wrap; }
Create ApplicationAnwendung erstellen
+
+ Select a content to capture
+ Einen zu erfassenden Inhalt auswählen
+
diff --git a/resources/i18n/OpenBoard_el.ts b/resources/i18n/OpenBoard_el.ts
index 329a7b9a..4296a070 100644
--- a/resources/i18n/OpenBoard_el.ts
+++ b/resources/i18n/OpenBoard_el.ts
@@ -697,11 +697,11 @@
Flash Trap
- Λήψη αντικειμένου flash
+ Λήψη αντικειμένου flashTrap Flash Content
- Λήψη περιεχομένου ενός αντικειμένου flash
+ Λήψη περιεχομένου ενός αντικειμένου flashWeb Trap
@@ -839,6 +839,10 @@
Draw intermediate grid lines
+
+ Capture Web Content
+
+ PasswordDialog
@@ -896,6 +900,14 @@
Are you sure you want to remove 1 page from the selected document '%0'?Είστε βέβαιος ότι θέλετε να αφαιρέσετε μια σελίδα από το επιλεγμένο έγγραφο '%0'?
+
+ Loading scene (%1/%2)
+
+
+
+ Moving cached scenes (%1/%2)
+
+ UBApplication
@@ -907,6 +919,10 @@
PodcastΒίντεο
+
+ Cannot open your UBX file directly. Please import it in Documents mode instead
+
+ UBApplicationController
@@ -1226,6 +1242,10 @@
Title page
+
+ Refreshing Document Thumbnails View (%1/%2)
+
+ UBDocumentManager
@@ -1276,6 +1296,10 @@
Page %0Σελίδα %0
+
+ Generating thumbnails for board (%1/%2)
+
+ UBDocumentReplaceDialog
@@ -1963,6 +1987,10 @@ Do you want to ignore these errors for this host?
OpenBoard 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.
+
+ Renaming pages (%1/%2)
+
+ UBPlatformUtils
@@ -2126,6 +2154,10 @@ Do you want to ignore these errors for this host?
%1 thumbnails generated ...%1 μικρογραφίες δημιουργήθηκαν...
+
+ Loading thumbnail (%1/%2)
+
+ UBThumbnailTextItem
@@ -2904,7 +2936,7 @@ p, li { white-space: pre-wrap; }
Select a flash to trap
- Επιλογή αντικειμένου flash για λήψη
+ Επιλογή αντικειμένου flash για λήψηabout:blank
@@ -2918,5 +2950,9 @@ p, li { white-space: pre-wrap; }
Create ApplicationΔημιουργία εφαρμογής
+
+ Select a content to capture
+
+
diff --git a/resources/i18n/OpenBoard_en.ts b/resources/i18n/OpenBoard_en.ts
index 348265ef..ca3377a0 100644
--- a/resources/i18n/OpenBoard_en.ts
+++ b/resources/i18n/OpenBoard_en.ts
@@ -703,14 +703,6 @@
Configure Podcast Recording
-
- Flash Trap
-
-
-
- Trap Flash Content
-
- Web Trap
@@ -831,6 +823,10 @@
Draw intermediate grid lines
+
+ Capture Web Content
+
+ PasswordDialog
@@ -888,6 +884,14 @@
Are you sure you want to remove 1 page from the selected document '%0'?
+
+ Loading scene (%1/%2)
+
+
+
+ Moving cached scenes (%1/%2)
+
+ UBApplication
@@ -899,6 +903,10 @@
Podcast
+
+ Cannot open your UBX file directly. Please import it in Documents mode instead
+
+ UBApplicationController
@@ -1166,6 +1174,10 @@
Empty
+
+ Refreshing Document Thumbnails View (%1/%2)
+
+ UBDocumentManager
@@ -1216,6 +1228,10 @@
Page %0
+
+ Generating thumbnails for board (%1/%2)
+
+ UBDocumentReplaceDialog
@@ -1845,6 +1861,10 @@ Do you want to ignore these errors for this host?
OpenBoard 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.
+
+ Renaming pages (%1/%2)
+
+ UBPlatformUtils
@@ -1974,6 +1994,10 @@ Do you want to ignore these errors for this host?
%1 thumbnails generated ...
+
+ Loading thumbnail (%1/%2)
+
+ UBThumbnailTextItem
@@ -2718,10 +2742,6 @@ p, li { white-space: pre-wrap; }
Trap flash
-
- Select a flash to trap
-
- about:blank
@@ -2734,5 +2754,9 @@ p, li { white-space: pre-wrap; }
Create Application
+
+ Select a content to capture
+
+
diff --git a/resources/i18n/OpenBoard_en_UK.ts b/resources/i18n/OpenBoard_en_UK.ts
index 348265ef..ca3377a0 100644
--- a/resources/i18n/OpenBoard_en_UK.ts
+++ b/resources/i18n/OpenBoard_en_UK.ts
@@ -703,14 +703,6 @@
Configure Podcast Recording
-
- Flash Trap
-
-
-
- Trap Flash Content
-
- Web Trap
@@ -831,6 +823,10 @@
Draw intermediate grid lines
+
+ Capture Web Content
+
+ PasswordDialog
@@ -888,6 +884,14 @@
Are you sure you want to remove 1 page from the selected document '%0'?
+
+ Loading scene (%1/%2)
+
+
+
+ Moving cached scenes (%1/%2)
+
+ UBApplication
@@ -899,6 +903,10 @@
Podcast
+
+ Cannot open your UBX file directly. Please import it in Documents mode instead
+
+ UBApplicationController
@@ -1166,6 +1174,10 @@
Empty
+
+ Refreshing Document Thumbnails View (%1/%2)
+
+ UBDocumentManager
@@ -1216,6 +1228,10 @@
Page %0
+
+ Generating thumbnails for board (%1/%2)
+
+ UBDocumentReplaceDialog
@@ -1845,6 +1861,10 @@ Do you want to ignore these errors for this host?
OpenBoard 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.
+
+ Renaming pages (%1/%2)
+
+ UBPlatformUtils
@@ -1974,6 +1994,10 @@ Do you want to ignore these errors for this host?
%1 thumbnails generated ...
+
+ Loading thumbnail (%1/%2)
+
+ UBThumbnailTextItem
@@ -2718,10 +2742,6 @@ p, li { white-space: pre-wrap; }
Trap flash
-
- Select a flash to trap
-
- about:blank
@@ -2734,5 +2754,9 @@ p, li { white-space: pre-wrap; }
Create Application
+
+ Select a content to capture
+
+
diff --git a/resources/i18n/OpenBoard_es.ts b/resources/i18n/OpenBoard_es.ts
index f3543d1a..8569eca5 100644
--- a/resources/i18n/OpenBoard_es.ts
+++ b/resources/i18n/OpenBoard_es.ts
@@ -697,11 +697,11 @@
Flash Trap
- Captura de elemento Flash
+ Captura de elemento FlashTrap Flash Content
- Capturar contenido Flash
+ Capturar contenido FlashWeb Trap
@@ -839,6 +839,10 @@
Draw intermediate grid lines
+
+ Capture Web Content
+
+ PasswordDialog
@@ -896,6 +900,14 @@
Are you sure you want to remove 1 page from the selected document '%0'?¿Está seguro de que quiere eliminar 1 página del documento seleccionado.'%0?
+
+ Loading scene (%1/%2)
+
+
+
+ Moving cached scenes (%1/%2)
+
+ UBApplication
@@ -907,6 +919,10 @@
PodcastPodcast
+
+ Cannot open your UBX file directly. Please import it in Documents mode instead
+
+ UBApplicationController
@@ -1238,6 +1254,10 @@
Title pagePágina de título
+
+ Refreshing Document Thumbnails View (%1/%2)
+
+ UBDocumentManager
@@ -1288,6 +1308,10 @@
Page %0Página %0
+
+ Generating thumbnails for board (%1/%2)
+
+ UBDocumentReplaceDialog
@@ -1979,6 +2003,10 @@ Do you want to ignore these errors for this host?
OpenBoard 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.OpenBoard perdió el acceso al repositorio de documentos '%1'. Desafortunadamente, la aplicación debe cerrarse para evitar la corrrupción de datos. También se pueden perder los últimos cambios.
+
+ Renaming pages (%1/%2)
+
+ UBPlatformUtils
@@ -2146,6 +2174,10 @@ Do you want to ignore these errors for this host?
loading thumbnail of page %1cargando miniaturas de la página %1
+
+ Loading thumbnail (%1/%2)
+
+ UBThumbnailTextItem
@@ -2924,7 +2956,7 @@ p, li { white-space: pre-wrap; }
Select a flash to trap
- Seleccionar un flash para capturar
+ Seleccionar un flash para capturarabout:blank
@@ -2938,5 +2970,9 @@ p, li { white-space: pre-wrap; }
Create ApplicationCrear aplicación
+
+ Select a content to capture
+
+
diff --git a/resources/i18n/OpenBoard_fr.ts b/resources/i18n/OpenBoard_fr.ts
index a0735e73..8551977e 100644
--- a/resources/i18n/OpenBoard_fr.ts
+++ b/resources/i18n/OpenBoard_fr.ts
@@ -181,11 +181,11 @@
Flash Trap
- Capturer du contenu Flash
+ Capturer du contenu FlashTrap Flash Content
- Capturer du contenu Flash
+ Capturer du contenu FlashWeb Trap
@@ -840,6 +840,10 @@
Draw intermediate grid linesDessiner des lignes intermédiaires
+
+ Capture Web Content
+ Capturer du contenu web
+ PasswordDialog
@@ -897,6 +901,14 @@
Are you sure you want to remove 1 page from the selected document '%0'?Voulez-vous vraiment effacer 1 page de ce document '%0'?
+
+ Loading scene (%1/%2)
+ Chargement de la scène (%1/%2)
+
+
+ Moving cached scenes (%1/%2)
+ Déplacement des scènes mises en cache (%1/%2)
+ UBApplication
@@ -908,6 +920,10 @@
PodcastPodcast
+
+ Cannot open your UBX file directly. Please import it in Documents mode instead
+ Impossible d'ouvrir un fichier UBX directement. Veuillez l'importer depuis le mode Documents
+ UBApplicationController
@@ -1251,6 +1267,10 @@
Empty My DocumentsVider Mes Documents
+
+ Refreshing Document Thumbnails View (%1/%2)
+ Actualisation des aperçus du mode Documents (%1/%2)
+ UBDocumentManager
@@ -1302,6 +1322,10 @@
Page %0Page %0
+
+ Generating thumbnails for board (%1/%2)
+ Création des aperçus du mode Tableau (%1/%2)
+ UBDocumentPublisher
@@ -2041,6 +2065,10 @@ Voulez-vous ignorer les erreurs pour ce serveur ?
OpenBoard 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.OpenBoard a perdu l'accès au répertoire des documents '%1'. Malheureusement, l'application sera fermée afin d'éviter la corruption des données. Les dernières modifications pourraient être également perdues.
+
+ Renaming pages (%1/%2)
+ Actualisation des noms des pages en cours (%1/%2)
+ UBPlatformUtils
@@ -2208,6 +2236,10 @@ Voulez-vous ignorer les erreurs pour ce serveur ?
loading thumbnail of page %1Chargement aperçu page %1
+
+ Loading thumbnail (%1/%2)
+ Chargement de l'aperçu (%1/%2)
+ UBThumbnailTextItem
@@ -2995,7 +3027,7 @@ p, li { white-space: pre-wrap; }
Select a flash to trap
- Sélectionner un contenu Flash à capturer
+ Sélectionner un contenu Flash à capturerabout:blank
@@ -3009,5 +3041,9 @@ p, li { white-space: pre-wrap; }
Create ApplicationCréer une application
+
+ Select a content to capture
+ Sélectionner un contenu à capturer
+
diff --git a/resources/i18n/OpenBoard_fr_CH.ts b/resources/i18n/OpenBoard_fr_CH.ts
index 2b764e91..408972ca 100644
--- a/resources/i18n/OpenBoard_fr_CH.ts
+++ b/resources/i18n/OpenBoard_fr_CH.ts
@@ -181,11 +181,11 @@
Flash Trap
- Capturer du contenu Flash
+ Capturer du contenu FlashTrap Flash Content
- Capturer du contenu Flash
+ Capturer du contenu FlashWeb Trap
@@ -840,6 +840,10 @@
Draw intermediate grid linesDessiner des lignes intermédiaires
+
+ Capture Web Content
+ Capturer du contenu web
+ PasswordDialog
@@ -897,6 +901,14 @@
Are you sure you want to remove 1 page from the selected document '%0'?Voulez-vous vraiment effacer 1 page de ce document '%0'?
+
+ Loading scene (%1/%2)
+ Chargement de la scène (%1/%2)
+
+
+ Moving cached scenes (%1/%2)
+ Déplacement des scènes mises en cache (%1/%2)
+ UBApplication
@@ -908,6 +920,10 @@
PodcastPodcast
+
+ Cannot open your UBX file directly. Please import it in Documents mode instead
+ Impossible d'ouvrir un fichier UBX directement. Veuillez l'importer depuis le mode Documents
+ UBApplicationController
@@ -1251,6 +1267,10 @@
Empty My DocumentsVider Mes Documents
+
+ Refreshing Document Thumbnails View (%1/%2)
+ Actualisation des aperçus du mode Documents (%1/%2)
+ UBDocumentManager
@@ -1302,6 +1322,10 @@
Page %0Page %0
+
+ Generating thumbnails for board (%1/%2)
+ Création des aperçus du mode Tableau (%1/%2)
+ UBDocumentPublisher
@@ -2041,6 +2065,10 @@ Voulez-vous ignorer les erreurs pour ce serveur ?
OpenBoard 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.OpenBoard a perdu l'accès au répertoire des documents '%1'. Malheureusement, l'application sera fermée afin d'éviter la corruption des données. Les dernières modifications pourraient être également perdues.
+
+ Renaming pages (%1/%2)
+ Actualisation des noms des pages en cours (%1/%2)
+ UBPlatformUtils
@@ -2208,6 +2236,10 @@ Voulez-vous ignorer les erreurs pour ce serveur ?
loading thumbnail of page %1Chargement aperçu page %1
+
+ Loading thumbnail (%1/%2)
+ Chargement de l'aperçu (%1/%2)
+ UBThumbnailTextItem
@@ -2995,7 +3027,7 @@ p, li { white-space: pre-wrap; }
Select a flash to trap
- Sélectionner un contenu Flash à capturer
+ Sélectionner un contenu Flash à capturerabout:blank
@@ -3009,5 +3041,9 @@ p, li { white-space: pre-wrap; }
Create ApplicationCréer une application
+
+ Select a content to capture
+ Sélectionner un contenu à capturer
+
diff --git a/resources/i18n/OpenBoard_gl.ts b/resources/i18n/OpenBoard_gl.ts
index ba0a0751..6d56580c 100644
--- a/resources/i18n/OpenBoard_gl.ts
+++ b/resources/i18n/OpenBoard_gl.ts
@@ -697,11 +697,11 @@
Flash Trap
- Captura de elemento Flash
+ Captura de elemento FlashTrap Flash Content
- Capturar contido Flash
+ Capturar contido FlashWeb Trap
@@ -839,6 +839,10 @@
Draw intermediate grid lines
+
+ Capture Web Content
+
+ PasswordDialog
@@ -896,6 +900,14 @@
Are you sure you want to remove 1 page from the selected document '%0'?¿Está seguro de que quere eliminar 1 páxina do documento seleccionado.'%0?
+
+ Loading scene (%1/%2)
+
+
+
+ Moving cached scenes (%1/%2)
+
+ UBApplication
@@ -907,6 +919,10 @@
PodcastPodcast
+
+ Cannot open your UBX file directly. Please import it in Documents mode instead
+
+ UBApplicationController
@@ -1238,6 +1254,10 @@
Title pagePáxina de título
+
+ Refreshing Document Thumbnails View (%1/%2)
+
+ UBDocumentManager
@@ -1288,6 +1308,10 @@
Page %0Páxina %0
+
+ Generating thumbnails for board (%1/%2)
+
+ UBDocumentReplaceDialog
@@ -1979,6 +2003,10 @@ Do you want to ignore these errors for this host?
OpenBoard 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.OpenBoard perdeu o acceso ao repositorio de documentos '%1'. Desafortunadamente, a aplicación debe pecharse para evitar a corrrupción de datos. Tamén se poden perder os últimos cambios.
+
+ Renaming pages (%1/%2)
+
+ UBPlatformUtils
@@ -2146,6 +2174,10 @@ Do you want to ignore these errors for this host?
loading thumbnail of page %1cargando miniaturas da páxina %1
+
+ Loading thumbnail (%1/%2)
+
+ UBThumbnailTextItem
@@ -2901,7 +2933,7 @@ p, li { white-space: pre-wrap; }
Select a flash to trap
- Seleccionar un flash para capturar
+ Seleccionar un flash para capturarabout:blank
@@ -2915,5 +2947,9 @@ p, li { white-space: pre-wrap; }
Create ApplicationCrear aplicación
+
+ Select a content to capture
+
+
diff --git a/resources/i18n/OpenBoard_hu.ts b/resources/i18n/OpenBoard_hu.ts
index a66081cf..9f8bdf4f 100644
--- a/resources/i18n/OpenBoard_hu.ts
+++ b/resources/i18n/OpenBoard_hu.ts
@@ -50,7 +50,7 @@
IntranetPodcastPublishingDialogPublish Podcast to YouTube
- Podcast publikálása a YouTubera
+ Podcast közzététele a YouTube-onTitle
@@ -441,7 +441,7 @@
Reload Current Page
- Aktuális oldal újratöltése
+ Jelenlegi oldal újratöltéseLoad Home Page
@@ -641,11 +641,11 @@
Add To New Page
- Hozzáadás új oldalhoz
+ Hozzáadás az új oldalhozAdd Item To New Page
- Tartalom hozzáadása új oldalhoz
+ Elem hozzáadása az új oldalhozAdd To Library
@@ -653,7 +653,7 @@
Add Item To Library
- Tartalom hozzáadása a könyvtárhoz
+ Elem hozzáadása a könyvtárhozPages
@@ -701,11 +701,11 @@
Flash Trap
- Flash rögzítése
+ Flash rögzítéseTrap Flash Content
- Flash tartalom rögzítése
+ Flash tartalom rögzítéseWeb Trap
@@ -813,30 +813,34 @@
Small Eraser
-
+ Kis radírColor 1
-
+ 1. színColor 2
-
+ 2. színColor 3
-
+ 3. színColor 4
-
+ 4. színColor 5
-
+ 5. színDraw intermediate grid lines
+ Köztes rácsvonalak rajzolása
+
+
+ Capture Web Content
@@ -886,14 +890,22 @@
Are you sure you want to remove 1 page from the selected document '%0'?
- Biztosan el akarsz távolítani 1 oldalt a kiválasztott dokumentumból '%0'?
+ Biztosan szeretné eltávolítani 1 oldalt a kijelölt „%0”-dokumentumból?Element ID =
-
+ Elem azonosítója = Content is not supported in destination format.
+ A tartalom nem támogatott célformátumban.
+
+
+ Loading scene (%1/%2)
+
+
+
+ Moving cached scenes (%1/%2)
@@ -907,6 +919,10 @@
PodcastPodcast
+
+ Cannot open your UBX file directly. Please import it in Documents mode instead
+
+ UBApplicationController
@@ -932,7 +948,7 @@
Board drawing...
- Tábla rajzolása...
+ Tábla rajzolása…
@@ -943,7 +959,7 @@
Draw intermediate grid lines
-
+ Köztes rácsvonalak rajzolása
@@ -990,11 +1006,11 @@
Saving document...
- Dokumentum mentése...
+ Dokumentum mentése…Document has just been saved...
- Dokumentum éppen most mentve...
+ Dokumentum éppen most mentve…Deleting page %1
@@ -1002,7 +1018,7 @@
Color
- Szín
+ Szín
@@ -1020,7 +1036,7 @@
UBBoardThumbnailsViewLoading page (%1/%2)
- Oldalak betöltése (%1/%2)
+ Oldalak betöltése: %1/%2
@@ -1113,23 +1129,23 @@
Are you sure you want to remove the document '%1'?
- Biztosan szeretné eltávolítani a '%1' dokumentumot?
+ Biztosan szeretné eltávolítani a(z) „%1” dokumentumot?Empty Trash
- Kuka kiürítése
+ Törölt elemek kiürítéseAre you sure you want to empty trash?
- Biztosan szeretné a kukát üríteni?
+ Biztosan szeretné kiüríteni a törölt elemeket?Emptying trash
- Kuka kiürítése folyamatban
+ Törölt elemek kiürítése folyamatban van…Emptied trash
- Kuka kiürítve
+ Törölt elemek kiürítveRemove Folder
@@ -1137,7 +1153,7 @@
Are you sure you want to remove the folder '%1' and all its content?
- Biztosan eltávolítja a(z) '%1' mappát és minden tartalmát?
+ Biztosan szeretné eltávolítani a(z) „%1” mappát és az összes tartalmát?No document selected!
@@ -1149,7 +1165,7 @@
Importing file %1...
- %1 fájl importálása...
+ %1 fájl importálása…Failed to import file ...
@@ -1169,7 +1185,7 @@
Trash
- Kuka
+ Törölt elemekOpen Document
@@ -1187,11 +1203,9 @@
Selection does not contain any image files!A kiválasztásban nincs egyetlen kép sem!
-
+ Are you sure you want to remove %n page(s) from the selected document '%1'?
-
- Biztosan szeretne eltávolítani %n oldalt a kiválasztott '%1' dokumentumból?
-
+ Biztosan szeretné eltávolítani %n oldalt a kiválasztott „%1” dokumentumból?Folder does not contain any image files
@@ -1203,11 +1217,11 @@
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?
- A '%1' dokumentum az OpenBoard újabb verziójával (%2) készült. Megnyitásával néhány információ elveszhet. Szeretné folytatni?
+ A(z) „%1” dokumentum az OpenBoard újabb verziójával (%2) készült. Megnyitásával néhány információ elveszhet. Szeretné folytatni?Are you sure you want to remove all selected documents?
- Biztosan szeretne eltávolítani minden kiválasztott dokumentumot?
+ Biztosan szeretné eltávolítani minden kijelölt dokumentumot?Remove multiple documents
@@ -1217,19 +1231,23 @@
duplicated %1 pageduplicated %1 pages
-
+ %1 oldal másolataRemove Item
-
+ Elem eltávolításaAre you sure you want to remove the selected item(s) ?
-
+ Biztosan szeretné eltávolítani a kijelölt elem(ek)et?Title page
+ Címlap
+
+
+ Refreshing Document Thumbnails View (%1/%2)
@@ -1261,7 +1279,7 @@
Inserting page %1 of %2
- %2 / %1 oldal beszúrása
+ Oldal beszúrása: %1/%2Import successful.
@@ -1280,6 +1298,10 @@
UBDocumentNavigatorPage %0
+ %0. oldal
+
+
+ Generating thumbnails for board (%1/%2)
@@ -1287,32 +1309,34 @@
UBDocumentReplaceDialogAccept
- Elfogad
+ ElfogadásReplace
-
+ CsereCancel
- Mégse
+ MégseThe name %1 is allready used.
Keeping this name will replace the document.
Providing a new name will create a new document.
-
+ A(z) %1 név már használatban van.
+Ennek a névnek a megtartása helyettesíti a dokumentumot.
+Új név megadása új dokumentumot hoz létre.UBDocumentTreeModelMy documents
-
+ Saját dokumentumokTrash
- Kuka
+ Törölt elemek%1 pages copied
@@ -1325,7 +1349,7 @@ Providing a new name will create a new document.
UBDocumentTreeViewCopying page %1/%2
- %1/%2 oldal másolása
+ Oldal másolása: %1/%2%1 pages copied
@@ -1335,11 +1359,11 @@ Providing a new name will create a new document.
Remove Item
-
+ Elem eltávolításaAre you sure you want to remove the selected item(s) ?
-
+ Biztosan szeretné eltávolítani a kijelölt elem(ek)et?
@@ -1350,13 +1374,11 @@ Providing a new name will create a new document.
Copying page %1/%2
- %1/%2 oldal másolása
+ Oldal másolása: %1/%2
-
+ %1 pages copied
-
- %1 oldal másolva
-
+ %1 oldal másolva
@@ -1374,7 +1396,7 @@ Providing a new name will create a new document.
UBDraggableThumbnailPage %0
-
+ %0. oldal
@@ -1392,7 +1414,7 @@ Providing a new name will create a new document.
Exporting document...
- Dokumentum exportálása...
+ Dokumentum exportálása…Export failed
@@ -1415,23 +1437,23 @@ Providing a new name will create a new document.
UBExportCFFExport to IWB
-
+ Exportálás IWB-formátumkéntExport as IWB File
-
+ Exportálás IWB-fájlformátumkéntExporting document...
- Dokumentum exportálása...
+ Dokumentum exportálása…Export successful.
- Exportálás sikeres.
+ Az exportálás sikeres.Export failed.
- Exportálás sikertelen.
+ Az exportálás sikertelen.
@@ -1446,7 +1468,7 @@ Providing a new name will create a new document.
Exporting %1 %2 of %3
- %1 exportálása %2/%3
+ %1 exportálása: %2/%3Export to OpenBoard Format
@@ -1457,27 +1479,27 @@ Providing a new name will create a new document.
UBExportDocumentSetAdaptorFailed to export...
-
+ Exportálás sikertelen…Export as UBX File
-
+ Exportálás UBX-fájlkéntExporting document...
- Dokumentum exportálása...
+ Dokumentum exportálása…Export successful.
- Exportálás sikeres.
+ Exportálás sikeres.Export failed.
- Exportálás sikertelen.
+ Exportálás sikertelen.Export to OpenBoard UBX Format
-
+ Exportálás OpenBoard UBX-formátumként
@@ -1499,7 +1521,7 @@ Providing a new name will create a new document.
Exporting page %1 of %2
- %2 / %1 oldal exportálása
+ Oldal exportálása: %1/%2Export to PDF
@@ -1518,7 +1540,7 @@ Providing a new name will create a new document.
Exporting document...
- Dokumentum exportálása...
+ Dokumentum exportálása…Export successful.
@@ -1627,14 +1649,14 @@ Providing a new name will create a new document.
Trash
- Kuka
+ Törölt elemekUBFeaturesNewFolderDialogAccept
- Elfogad
+ ElfogadásCancel
@@ -1705,7 +1727,7 @@ Providing a new name will create a new document.
UBGraphicsTextItem<Type Text Here>
- <Szöveg helye>
+ <Adja meg a szöveget ide>
@@ -1730,7 +1752,7 @@ Providing a new name will create a new document.
UBGraphicsWidgetItemLoading ...
- Betöltés ...
+ Betöltés folyamatban van…
@@ -1748,30 +1770,30 @@ Providing a new name will create a new document.
UBImportCFFCommon File Format (
-
+ Közös fájlformátum (Importing file %1...
- %1 fájl importálása...
+ %1 fájl importálása…Import of file %1 failed.
- %1 fájl importálása sikertelen.
+ %1 fájl importálása sikertelen.Import successful.
- Importálás sikeres.
+ Importálás sikeres.Import failed.
-
+ Importálás sikertelen.UBImportDocumentImporting file %1...
- %1 fájl importálása...
+ %1 fájl importálása…Import successful.
@@ -1790,14 +1812,14 @@ Providing a new name will create a new document.
UBImportDocumentSetAdaptorOpenboard (set of documents) (*.ubx)
-
+ OpenBoard (dokumentumkészlet) (*.ubx)UBImportImageImage Format (
- Kép formátum (
+ Kép-formátum (
@@ -1812,25 +1834,25 @@ Providing a new name will create a new document.
Importing page %1 of %2
- %2 / %1 oldal importálása
+ Oldal importálása: %1/%2UBIntranetPodcastPublisherError while publishing video to intranet (%1)
- Hiba a videó intranetre való publikálása közben (%1)
+ Hiba történt videó közzétételekor az intraneten (%1)Publishing to Intranet in progress %1 %
- Intranetre publikálás folyamatban %1 %
+ Az intraneten való közzététel folyamatban van %1%UBIntranetPodcastPublishingDialogPublish
- Publikálás
+ Közzététel
@@ -1936,14 +1958,18 @@ Figyelmen kívül hagyja ezeket a hibákat ennél a hosztnál?
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.
- elveszítette a '%1' dokumentum repository hozzáférését. Sajnálatosan az alkalmazásnak le kellett állnia, hogy elkerülje az adatsérülést. A legutóbbi változtatások elveszhettek.
+ elveszítette a(z) „%1” dokumentum repository hozzáférését. Sajnálatosan az alkalmazásnak le kellett állnia, hogy elkerülje az adatsérülést. A legutóbbi változtatások elveszhettek.Moving page to trash folder...
- Oldal áthelyezése a kukába...
+ Oldal áthelyezése a törölt elemek mappába…OpenBoard 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.
+ Az OpenBoard elvesztette a hozzáférést a(z) „%1” dokumentumtárához. Sajnos az alkalmazást le kell állítani az adatvesztés elkerülése érdekében. A legújabb változások is elveszhetnek.
+
+
+ Renaming pages (%1/%2)
@@ -1974,11 +2000,11 @@ Figyelmen kívül hagyja ezeket a hibákat ennél a hosztnál?
UBPodcastControllerFailed to start encoder ...
- Sikertelen a kódoló indítása...
+ Sikertelen a kódoló indítása…No Podcast encoder available ...
- Nincs elérhető podcast kódoló ...
+ Nincs elérhető podcast kódoló…Part %1
@@ -1986,7 +2012,7 @@ Figyelmen kívül hagyja ezeket a hibákat ennél a hosztnál?
on your desktop ...
- az asztalán ...
+ az asztalán…in folder %1
@@ -2022,11 +2048,11 @@ Figyelmen kívül hagyja ezeket a hibákat ennél a hosztnál?
Publish to Intranet
- Publikálás az Intranetre
+ Közzététel az IntranetenPublish to Youtube
- Publikálás a YouTubera
+ Közzététel a Youtube-onOpenBoard Cast
@@ -2048,7 +2074,7 @@ Figyelmen kívül hagyja ezeket a hibákat ennél a hosztnál?
UBProxyLoginDlgProxy Login
- Proxy belépés
+ Proxy bejelentkezésUsername:
@@ -2063,7 +2089,7 @@ Figyelmen kívül hagyja ezeket a hibákat ennél a hosztnál?
UBPublicationDlgPublish document on the web
- Dokumentum publikálása a WEBre
+ Dokumentum közzététele az internetenTitle:
@@ -2075,7 +2101,7 @@ Figyelmen kívül hagyja ezeket a hibákat ennél a hosztnál?
Publish
- Publikálás
+ Közzététel
@@ -2103,16 +2129,20 @@ Figyelmen kívül hagyja ezeket a hibákat ennél a hosztnál?
UBThumbnailAdaptorGenerating preview thumbnails ...
- Előképek létrehozása...
+ Előképek létrehozása…%1 thumbnails generated ...
- %1 előkép létrehozva...
+ %1 előkép létrehozva…loading thumbnail of page %1%1. oldal előképének betöltése
+
+ Loading thumbnail (%1/%2)
+
+ UBThumbnailTextItem
@@ -2153,7 +2183,7 @@ Figyelmen kívül hagyja ezeket a hibákat ennél a hosztnál?
Axes
-
+ Tengelyek
@@ -2212,7 +2242,7 @@ Please reboot the application to access the updated documents.
Please wait the import process will start soon...
- Kérem várjon. Az importálási folyamat hamarosan elindul...
+ Kérem várjon. Az importálási folyamat hamarosan elindul…Remind me later
@@ -2223,7 +2253,7 @@ Please reboot the application to access the updated documents.
UBWebPluginWidgetLoading...
- Betöltés ...
+ Betöltés folyamatban van…
@@ -2256,7 +2286,7 @@ Please reboot the application to access the updated documents.
Autos & Vehicles
- Autók & Járművek
+ Autók és JárművekMusic
@@ -2264,7 +2294,7 @@ Please reboot the application to access the updated documents.
Pets & Animals
- Házi kedvencek @ Állatok
+ Háziállatok és ÁllatokSports
@@ -2272,7 +2302,7 @@ Please reboot the application to access the updated documents.
Travel & Events
- Utazás & Események
+ Utazás és EseményekGaming
@@ -2284,11 +2314,11 @@ Please reboot the application to access the updated documents.
People & Blogs
- Emberek & Blogok
+ Emberek és Webes naplókNews & Politics
- Hírek & Politika
+ Hírek és PolitikaEntertainment
@@ -2300,15 +2330,15 @@ Please reboot the application to access the updated documents.
Howto & Style
- Hogyan Csináld & Stílus
+ Hogyan kell és StílusNonprofits & Activism
- NonProfit & Aktivisták
+ Nonprofit szervezetek és AktivizmusScience & Technology
- Tudomány & Technológia
+ Tudomány és Technológia
@@ -2361,7 +2391,7 @@ Please reboot the application to access the updated documents.
%1 of %2 (%3/sec) %4
- %1 / %2 (%3/mp) %4
+ %1/%2 (%3/mp) %4?
@@ -2370,7 +2400,7 @@ Please reboot the application to access the updated documents.
%1 of %2 - Stopped
- %1 / %2 - Megállítva
+ %1/%2 - Megállítvabytes
@@ -2430,11 +2460,11 @@ Please reboot the application to access the updated documents.
WBTabBarNew &Tab
- Új fül &T
+ Új &LapClone Tab
- Fül másolása
+ Lap másolása&Close Tab
@@ -2442,15 +2472,15 @@ Please reboot the application to access the updated documents.
Close &Other Tabs
- Többi fül bezárása &O
+ &Többi lap bezárásaReload Tab
- Fül frissítése
+ Lap újratöltéseReload All Tabs
- Minden fül frissítése
+ Minden lap újratöltése
@@ -2491,7 +2521,7 @@ Please reboot the application to access the updated documents.
Add to Current Document
- Hozzaadás az aktuális dokumentumhoz
+ Hozzaadás a jelenlegi dokumentumhozPDF
@@ -2517,14 +2547,14 @@ Please reboot the application to access the updated documents.
XPDFRendererProcessing...
-
+ Feldolgozás folyamatban van…YouTubePublishingDialogPublish Podcast to YouTube
- Podcast publikálása YouTubera
+ Podcast közzététele a YouTube-onTitle
@@ -2645,19 +2675,19 @@ p, li { white-space: pre-wrap; }
Creation date
-
+ Létrehozás dátumaUpdate date
-
+ Frissítés dátumaAlphabetical order
-
+ Rendezés betűrendbenSort Order
-
+ Rendezési sorrend
@@ -2744,7 +2774,7 @@ p, li { white-space: pre-wrap; }
version : …
- verziószám: ...
+ verziószám: Licences
@@ -2828,31 +2858,31 @@ p, li { white-space: pre-wrap; }
Swap first and second view displays
-
+ Első és második kijelző megcseréléseDocuments Mode
-
+ Dokumentum üzemmódDisplay date column on alphabetical sort
-
+ Dátum oszlop megjelenítése betűrendbenEmpty trash for documents older than
-
+ A törölt elemek ürítése a következőknél régebbi dokumentumokhoz:days
-
+ napPDF Rendering
-
+ PDF-megjelenítőImprove zoom execution time (can slightly affect rendering quality)
-
+ Nagyitás végrehajtási idő csökkentése (némileg befolyásolhatja a renderelés minőségét)
@@ -2863,7 +2893,7 @@ p, li { white-space: pre-wrap; }
Select a flash to trap
- Flash kiválasztása a rögzítéshez
+ Flash kiválasztása a rögzítéshezabout:blank
@@ -2877,5 +2907,9 @@ p, li { white-space: pre-wrap; }
Create ApplicationAlkalmazás létrehozása
+
+ Select a content to capture
+
+
diff --git a/resources/i18n/OpenBoard_it.ts b/resources/i18n/OpenBoard_it.ts
index c134c503..f7ec8b85 100644
--- a/resources/i18n/OpenBoard_it.ts
+++ b/resources/i18n/OpenBoard_it.ts
@@ -697,11 +697,11 @@
Flash Trap
- Cattura Flash
+ Cattura FlashTrap Flash Content
- Cattura contenuto flash
+ Cattura contenuto flashWeb Trap
@@ -839,6 +839,10 @@
Draw intermediate grid linesdisegna linee di griglia intermedie
+
+ Capture Web Content
+ Catturare il contenuto del web
+ PasswordDialog
@@ -896,6 +900,14 @@
Are you sure you want to remove 1 page from the selected document '%0'?Sei sicuro di voler rimuovere 1 pagina dal documento selezionato '%0'?
+
+ Loading scene (%1/%2)
+ Caricamento della scena (%1/%2)
+
+
+ Moving cached scenes (%1/%2)
+ Spostamento delle scene in cache (%1/%2)
+ UBApplication
@@ -907,6 +919,10 @@
PodcastPodCast
+
+ Cannot open your UBX file directly. Please import it in Documents mode instead
+ Impossibile aprire direttamente un file UBX. Si prega di importarlo dalla modalità Documenti
+ UBApplicationController
@@ -1238,6 +1254,10 @@
Title pageFrontespizio
+
+ Refreshing Document Thumbnails View (%1/%2)
+ Aggiornamento delle anteprime in modalità Documenti (%1/%2)
+ UBDocumentManager
@@ -1288,6 +1308,10 @@
Page %0Pagina %0
+
+ Generating thumbnails for board (%1/%2)
+ Creazione delle anteprime in modalità Lavagna (%1/%2)
+ UBDocumentPublisher
@@ -2020,6 +2044,10 @@ Vuoi ignorare gli errori per questo host?
OpenBoard 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.OpenBoard ha perso l'accesso al repository documenti "%1". Sfortunatamente l'applicazione deve essere chiusa per evitare di rovinare i dati. Gli ultimi cambiamenti potrebbero andare persi.
+
+ Renaming pages (%1/%2)
+ Aggiornamento dei nomi delle pagine in corso (%1/%2)
+ UBPlatformUtils
@@ -2187,6 +2215,10 @@ Vuoi ignorare gli errori per questo host?
loading thumbnail of page %1Caricamento miniatura della pagina %1
+
+ Loading thumbnail (%1/%2)
+ Caricamento dell'anteprima (%1/%2)
+ UBThumbnailTextItem
@@ -2969,7 +3001,7 @@ p, li { white-space: pre-wrap; }
Select a flash to trap
- Seleziona un'applicazione flash da catturare
+ Seleziona un'applicazione flash da catturareabout:blank
@@ -2983,5 +3015,9 @@ p, li { white-space: pre-wrap; }
Create ApplicationCrea applicazione
+
+ Select a content to capture
+ Selezionare il contenuto da catturare
+
diff --git a/resources/i18n/OpenBoard_iw.ts b/resources/i18n/OpenBoard_iw.ts
index c44ddd5b..a94f9f82 100644
--- a/resources/i18n/OpenBoard_iw.ts
+++ b/resources/i18n/OpenBoard_iw.ts
@@ -697,11 +697,11 @@
Flash Trap
- מלכודת פלאש
+ מלכודת פלאשTrap Flash Content
- תוכן מלכודת פלאש
+ תוכן מלכודת פלאשWeb Trap
@@ -840,6 +840,10 @@
Draw intermediate grid lines
+
+ Capture Web Content
+
+ PasswordDialog
@@ -897,6 +901,14 @@
Are you sure you want to remove 1 page from the selected document '%0'?האם אתה בטוח שברצונך למחוק דף 1 מהמסמך שנבחר %0?
+
+ Loading scene (%1/%2)
+
+
+
+ Moving cached scenes (%1/%2)
+
+ UBApplication
@@ -908,6 +920,10 @@
Podcastפודקסט
+
+ Cannot open your UBX file directly. Please import it in Documents mode instead
+
+ UBApplicationController
@@ -1227,6 +1243,10 @@
Title page
+
+ Refreshing Document Thumbnails View (%1/%2)
+
+ UBDocumentManager
@@ -1277,6 +1297,10 @@
Page %0עמוד %0
+
+ Generating thumbnails for board (%1/%2)
+
+ UBDocumentReplaceDialog
@@ -1959,6 +1983,10 @@ Do you want to ignore these errors for this host?
OpenBoard 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.
+
+ Renaming pages (%1/%2)
+
+ UBPlatformUtils
@@ -2122,6 +2150,10 @@ Do you want to ignore these errors for this host?
%1 thumbnails generated ...נוצרה תמונה מוקטנת של %1...
+
+ Loading thumbnail (%1/%2)
+
+ UBThumbnailTextItem
@@ -2896,7 +2928,7 @@ p, li { white-space: pre-wrap; }
Select a flash to trap
- בחר פלאש ללכידה
+ בחר פלאש ללכידהabout:blank
@@ -2910,5 +2942,9 @@ p, li { white-space: pre-wrap; }
Create Applicationצור יישום
+
+ Select a content to capture
+
+
diff --git a/resources/i18n/OpenBoard_ja.ts b/resources/i18n/OpenBoard_ja.ts
index 2af7f683..8051862e 100644
--- a/resources/i18n/OpenBoard_ja.ts
+++ b/resources/i18n/OpenBoard_ja.ts
@@ -697,11 +697,11 @@
Flash Trap
- フラッシュトラップ
+ フラッシュトラップTrap Flash Content
- トラップフラッシュコンテンツ
+ トラップフラッシュコンテンツWeb Trap
@@ -839,6 +839,10 @@
Draw intermediate grid lines
+
+ Capture Web Content
+
+ PasswordDialog
@@ -896,6 +900,14 @@
Are you sure you want to remove 1 page from the selected document '%0'?
+
+ Loading scene (%1/%2)
+
+
+
+ Moving cached scenes (%1/%2)
+
+ UBApplication
@@ -907,6 +919,10 @@
Podcastポッドキャスト
+
+ Cannot open your UBX file directly. Please import it in Documents mode instead
+
+ UBApplicationController
@@ -1220,6 +1236,10 @@
Title page
+
+ Refreshing Document Thumbnails View (%1/%2)
+
+ UBDocumentManager
@@ -1270,6 +1290,10 @@
Page %0%0ページ
+
+ Generating thumbnails for board (%1/%2)
+
+ UBDocumentReplaceDialog
@@ -1955,6 +1979,10 @@ Do you want to ignore these errors for this host?
OpenBoard 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.
+
+ Renaming pages (%1/%2)
+
+ UBPlatformUtils
@@ -2118,6 +2146,10 @@ Do you want to ignore these errors for this host?
%1 thumbnails generated ...%1 サムネイル作成済み ...
+
+ Loading thumbnail (%1/%2)
+
+ UBThumbnailTextItem
@@ -2892,7 +2924,7 @@ p, li { white-space: pre-wrap; }
Select a flash to trap
- フラッシュを選択してトラップする
+ フラッシュを選択してトラップするabout:blank
@@ -2906,5 +2938,9 @@ p, li { white-space: pre-wrap; }
Create Applicationアプリケーションを作成
+
+ Select a content to capture
+
+
diff --git a/resources/i18n/OpenBoard_ko.ts b/resources/i18n/OpenBoard_ko.ts
index c5b62ec7..3e0cfe29 100644
--- a/resources/i18n/OpenBoard_ko.ts
+++ b/resources/i18n/OpenBoard_ko.ts
@@ -697,11 +697,11 @@
Flash Trap
- 플래시 트랩
+ 플래시 트랩Trap Flash Content
- 플래시 콘텐츠 트랩
+ 플래시 콘텐츠 트랩Web Trap
@@ -839,6 +839,10 @@
Draw intermediate grid lines
+
+ Capture Web Content
+
+ PasswordDialog
@@ -896,6 +900,14 @@
Are you sure you want to remove 1 page from the selected document '%0'?선택한 문서 '%0'에서 1페이지를 제거하시겠습니까?
+
+ Loading scene (%1/%2)
+
+
+
+ Moving cached scenes (%1/%2)
+
+ UBApplication
@@ -907,6 +919,10 @@
Podcast팟캐스트
+
+ Cannot open your UBX file directly. Please import it in Documents mode instead
+
+ UBApplicationController
@@ -1224,6 +1240,10 @@
Title page
+
+ Refreshing Document Thumbnails View (%1/%2)
+
+ UBDocumentManager
@@ -1274,6 +1294,10 @@
Page %0%0 페이지
+
+ Generating thumbnails for board (%1/%2)
+
+ UBDocumentPublisher
@@ -1974,6 +1998,10 @@ Do you want to ignore these errors for this host?
OpenBoard 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.
+
+ Renaming pages (%1/%2)
+
+ UBPlatformUtils
@@ -2137,6 +2165,10 @@ Do you want to ignore these errors for this host?
%1 thumbnails generated ...%1 썸네일 생성됨 ...
+
+ Loading thumbnail (%1/%2)
+
+ UBThumbnailTextItem
@@ -2915,7 +2947,7 @@ p, li { white-space: pre-wrap; }
Select a flash to trap
- 플래시를 트랩으로 저장
+ 플래시를 트랩으로 저장about:blank
@@ -2929,5 +2961,9 @@ p, li { white-space: pre-wrap; }
Create Application응용 프로그램 만들기
+
+ Select a content to capture
+
+
diff --git a/resources/i18n/OpenBoard_mg.ts b/resources/i18n/OpenBoard_mg.ts
index 7adefee0..98e8a6db 100644
--- a/resources/i18n/OpenBoard_mg.ts
+++ b/resources/i18n/OpenBoard_mg.ts
@@ -681,11 +681,11 @@
Flash Trap
- Alaina ny Flash
+ Alaina ny FlashTrap Flash Content
- Alaina ny mpiatiny Flash
+ Alaina ny mpiatiny FlashWeb Trap
@@ -839,6 +839,10 @@
Draw intermediate grid lines
+
+ Capture Web Content
+
+ PasswordDialog
@@ -896,6 +900,14 @@
Are you sure you want to remove 1 page from the selected document '%0'?Tena te hamafa pejy iray avy amin'ilay rakitra '%0' voafidy ve ianao ?
+
+ Loading scene (%1/%2)
+
+
+
+ Moving cached scenes (%1/%2)
+
+ UBApplication
@@ -907,6 +919,10 @@
PodcastPodcast
+
+ Cannot open your UBX file directly. Please import it in Documents mode instead
+
+ UBApplicationController
@@ -1226,6 +1242,10 @@
Title page
+
+ Refreshing Document Thumbnails View (%1/%2)
+
+ UBDocumentManager
@@ -1276,6 +1296,10 @@
Page %0Pejy %0
+
+ Generating thumbnails for board (%1/%2)
+
+ UBDocumentPublisher
@@ -1970,6 +1994,10 @@ Tena tsy te hiraharaha an'ireo tsy mety ho an'ilay milina ve ianao?OpenBoard 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.
+
+ Renaming pages (%1/%2)
+
+ UBPlatformUtils
@@ -2133,6 +2161,10 @@ Tena tsy te hiraharaha an'ireo tsy mety ho an'ilay milina ve ianao?%1 thumbnails generated ...
%1 ny kisarisary no voaforona ...
+
+ Loading thumbnail (%1/%2)
+
+ UBThumbnailTextItem
@@ -2911,7 +2943,7 @@ p, li { white-space: pre-wrap; }
Select a flash to trap
- Safidio ny Flash ho alaina
+ Safidio ny Flash ho alainaabout:blank
@@ -2925,5 +2957,9 @@ p, li { white-space: pre-wrap; }
Create ApplicationMamorona rindran'asa
+
+ Select a content to capture
+
+
diff --git a/resources/i18n/OpenBoard_nb.ts b/resources/i18n/OpenBoard_nb.ts
index 5b4409ae..e03e507c 100644
--- a/resources/i18n/OpenBoard_nb.ts
+++ b/resources/i18n/OpenBoard_nb.ts
@@ -697,11 +697,11 @@
Flash Trap
- Flash trap
+ Flash trapTrap Flash Content
- Trap flash-innhold
+ Trap flash-innholdWeb Trap
@@ -839,6 +839,10 @@
Draw intermediate grid lines
+
+ Capture Web Content
+
+ PasswordDialog
@@ -896,6 +900,14 @@
Are you sure you want to remove 1 page from the selected document '%0'?Er du sikker på at du vil fjerne side 1 fra det valgte dokumentet '%0'?
+
+ Loading scene (%1/%2)
+
+
+
+ Moving cached scenes (%1/%2)
+
+ UBApplication
@@ -907,6 +919,10 @@
PodcastPodcast
+
+ Cannot open your UBX file directly. Please import it in Documents mode instead
+
+ UBApplicationController
@@ -1227,6 +1243,10 @@
Title page
+
+ Refreshing Document Thumbnails View (%1/%2)
+
+ UBDocumentManager
@@ -1277,6 +1297,10 @@
Page %0Side %0
+
+ Generating thumbnails for board (%1/%2)
+
+ UBDocumentReplaceDialog
@@ -1959,6 +1983,10 @@ Do you want to ignore these errors for this host?
OpenBoard 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.
+
+ Renaming pages (%1/%2)
+
+ UBPlatformUtils
@@ -2122,6 +2150,10 @@ Do you want to ignore these errors for this host?
%1 thumbnails generated ...%1 miniatyrbilder generert ...
+
+ Loading thumbnail (%1/%2)
+
+ UBThumbnailTextItem
@@ -2901,7 +2933,7 @@ p, li { white-space: pre-wrap; }
Select a flash to trap
- Velg flash som skal tas
+ Velg flash som skal tasabout:blank
@@ -2915,5 +2947,9 @@ p, li { white-space: pre-wrap; }
Create ApplicationOpprett applikasjon
+
+ Select a content to capture
+
+
diff --git a/resources/i18n/OpenBoard_nl.ts b/resources/i18n/OpenBoard_nl.ts
index d3e15859..cd013ed2 100644
--- a/resources/i18n/OpenBoard_nl.ts
+++ b/resources/i18n/OpenBoard_nl.ts
@@ -697,11 +697,11 @@
Flash Trap
- Flash Trap
+ Flash TrapTrap Flash Content
- Trap flash inhoud
+ Trap flash inhoudWeb Trap
@@ -839,6 +839,10 @@
Draw intermediate grid lines
+
+ Capture Web Content
+
+ PasswordDialog
@@ -896,6 +900,14 @@
Are you sure you want to remove 1 page from the selected document '%0'?
+
+ Loading scene (%1/%2)
+
+
+
+ Moving cached scenes (%1/%2)
+
+ UBApplication
@@ -907,6 +919,10 @@
PodcastPodcast
+
+ Cannot open your UBX file directly. Please import it in Documents mode instead
+
+ UBApplicationController
@@ -1222,6 +1238,10 @@
Title page
+
+ Refreshing Document Thumbnails View (%1/%2)
+
+ UBDocumentManager
@@ -1272,6 +1292,10 @@
Page %0Pagina %0
+
+ Generating thumbnails for board (%1/%2)
+
+ UBDocumentPublisher
@@ -1960,6 +1984,10 @@ Do you want to ignore these errors for this host?
OpenBoard 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.
+
+ Renaming pages (%1/%2)
+
+ UBPlatformUtils
@@ -2123,6 +2151,10 @@ Do you want to ignore these errors for this host?
%1 thumbnails generated ...%1 miniaturen opgeladen...
+
+ Loading thumbnail (%1/%2)
+
+ UBThumbnailTextItem
@@ -2900,7 +2932,7 @@ p, li { white-space: pre-wrap; }
Select a flash to trap
- Te vangen licht selecteren
+ Te vangen licht selecterenabout:blank
@@ -2914,5 +2946,9 @@ p, li { white-space: pre-wrap; }
Create ApplicationApplicatie maken
+
+ Select a content to capture
+
+
diff --git a/resources/i18n/OpenBoard_pl.ts b/resources/i18n/OpenBoard_pl.ts
index 5802b1bb..f1bc06d8 100644
--- a/resources/i18n/OpenBoard_pl.ts
+++ b/resources/i18n/OpenBoard_pl.ts
@@ -481,7 +481,7 @@
Grid Light Background
- Jasne rastrowe tło
+ Jasne tło w kratkęPlain Dark Background
@@ -493,7 +493,7 @@
Grid Dark Background
- Ciemne rastrowe tło
+ Ciemne tło w kratkęPodcast
@@ -561,7 +561,7 @@
Highlight
- Wyróżnienie
+ Wyróżnienie Ctrl+M
@@ -697,16 +697,15 @@
Flash Trap
- Pułapka Flash
+ Pułapka FlashTrap Flash Content
- Złap zawartość Flash
+ Złap zawartość FlashWeb Trap
-
-
+ Pułapka sieciowaTrap Web Content
@@ -797,50 +796,54 @@
Ruled Light Background
-
+ Jasne tło w linieRuled Dark Background
-
+ Ciemne tło w linieOpen Tutorial
-
+ Otwórz samouczekOpen the tutorial web page
-
+ Otwórz stronę samouczkaReset grid size
-
+ Zresetuj rozmiar kratkiSmall Eraser
-
+ Mała gumkaColor 1
-
+ Kolor 1Color 2
-
+ Kolor 2Color 3
-
+ Kolor 3Color 4
-
+ Kolor 4Color 5
-
+ Kolor 5Draw intermediate grid lines
+ Rysuj drobne linie kratki
+
+
+ Capture Web Content
@@ -886,7 +889,7 @@
QObjectElement ID =
- ID elementu =
+ ID elementu = Content is not supported in destination format.
@@ -900,6 +903,14 @@
Are you sure you want to remove 1 page from the selected document '%0'?Czy na pewno chcesz usunąć 1 stronę z wybranego dokumentu „%0”?
+
+ Loading scene (%1/%2)
+
+
+
+ Moving cached scenes (%1/%2)
+
+ UBApplication
@@ -911,6 +922,10 @@
PodcastPodkast
+
+ Cannot open your UBX file directly. Please import it in Documents mode instead
+
+ UBApplicationController
@@ -939,11 +954,11 @@
UBBackgroundPaletteGrid size
-
+ Rozmiar kratkiDraw intermediate grid lines
-
+ Rysuj drobne linie kratki
@@ -994,19 +1009,19 @@
Saving document...
-
+ Zapisywanie dokumentu...Document has just been saved...
-
+ Dokument został właśnie zapisany...Deleting page %1
-
+ Usuwanie strony %1Color
- Kolor
+ Kolor
@@ -1024,7 +1039,7 @@
UBBoardThumbnailsViewLoading page (%1/%2)
-
+ Ładowanie strony (%1/%2)
@@ -1074,7 +1089,7 @@
Show OpenBoard
-
+ Pokaż OpenBoard
@@ -1157,7 +1172,7 @@
Failed to import file ...
- Importowanie pliku zakończone niepowodzeniem...
+ Importowanie pliku zakończone niepowodzeniem... Import all Images from Folder
@@ -1210,26 +1225,30 @@
duplicated %1 pageduplicated %1 pages
-
-
-
-
+
+ zduplikowano %1 stronę
+ zduplikowano %1 strony
+ Zduplikowano %1 stronRemove Item
-
+ Usuń elementAre you sure you want to remove the selected item(s) ?
-
+ Czy na pewno chcesz usunąć zaznaczone elementy?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?
-
+ Dokument '%1' został utworzony przy użyciu nowszej wersji OpenBoard (%2). Otwierając go możesz stracić niektóre informację. Czy chcesz kontynuować?Title page
+ Strona tytułowa
+
+
+ Refreshing Document Thumbnails View (%1/%2)
@@ -1282,6 +1301,10 @@
Page %0Strona %0
+
+ Generating thumbnails for board (%1/%2)
+
+ UBDocumentPublisher
@@ -1294,32 +1317,34 @@
UBDocumentReplaceDialogAccept
- Akceptuj
+ AkceptujCancel
- Anuluj
+ AnulujReplace
-
+ ZastąpThe name %1 is allready used.
Keeping this name will replace the document.
Providing a new name will create a new document.
-
+ Nazwa %1 jest już używana.
+Pozostawienie tej nazwy zastąpi ten dokument.
+Zmiana nazwy na nową utworzy nowy dokument.UBDocumentTreeModelTrash
- Kosz
+ Kosz%1 pages copied
-
+ Skopiowano %1 stronęSkopiowano %1 stronySkopiowano %1 stron
@@ -1327,14 +1352,14 @@ Providing a new name will create a new document.
My documents
-
+ Moje dokumentyUBDocumentTreeView%1 pages copied
-
+ Skopiowano %1 stronęSkopiowano %1 stronySkopiowano %1 stron
@@ -1342,15 +1367,15 @@ Providing a new name will create a new document.
Remove Item
-
+ Usuń elementyAre you sure you want to remove the selected item(s) ?
-
+ Czy na pewno chcesz usunąć zaznaczone elementy?Copying page %1/%2
- Kopiowanie strony %1/%2
+ Kopiowanie strony %1/%2
@@ -1388,14 +1413,14 @@ Providing a new name will create a new document.
UBDraggableThumbnailPage %0
- Strona %0
+ Strona %0UBDraggableThumbnailViewPage %0
- Strona %0
+ Strona %0
@@ -1406,23 +1431,23 @@ Providing a new name will create a new document.
Exporting document...
- Eksportowanie dokumentu...
+ Eksportowanie dokumentu...Export successful.
- Eksportowanie zakończone powodzeniem.
+ Eksportowanie zakończone powodzeniem.Export failed
-
+ Eksportowanie zakończone niepowodzeniemUnable to export to the selected location. You do not have the permissions necessary to save the file.
-
+ Nie udało się wyeksportować do wybranej lokacji. Nie masz wystarczających uprawnień do zapisania pliku.Export failed: location not writable
-
+ Eksportowanie nie powiodło się: niemożliwy zapis do lokacji
@@ -1472,34 +1497,34 @@ Providing a new name will create a new document.
Export to OpenBoard Format
-
+ Wyeksportuj do formatu OpenBoardUBExportDocumentSetAdaptorExporting document...
- Eksportowanie dokumentu...
+ Eksportowanie dokumentu...Export successful.
- Eksportowanie zakończone powodzeniem.
+ Eksportowanie zakończone powodzeniem.Export failed.
- Eksportowanie zakończone niepowodzeniem.
+ Eksportowanie zakończone niepowodzeniem.Failed to export...
-
+ Nie udało się wyeksportować...Export as UBX File
-
+ Wyeksportuj jako plik UBXExport to OpenBoard UBX Format
-
+ Wyeksportuj jako plik formatu OpenBoard UBX
@@ -1691,7 +1716,7 @@ Providing a new name will create a new document.
UBFeaturesProgressInfoLoading
- Wczytywanie
+ Wczytywanie
@@ -1721,26 +1746,26 @@ Providing a new name will create a new document.
Set as background
- Ustaw jako tło
+ Ustaw jako tłoUBGraphicsMediaItemMedia resource couldn't be resolved
-
+ Nie udało się znaleźć zasobu multimedialnegoUnsupported media format
-
+ Niewspierany format zasobu multimedialnegoMedia playback service not found
-
+ Nie znaleziono usługi odtwarzaniaMedia error:
-
+ Błąd multimediów:
@@ -1783,7 +1808,7 @@ Providing a new name will create a new document.
Transform as Tool
- Przekształć jako narzędzie
+ Przekształć jako narzędzie
@@ -1825,14 +1850,14 @@ Providing a new name will create a new document.
OpenBoard (*.ubz)
-
+ OpenBoard (*.ubz)UBImportDocumentSetAdaptorOpenboard (set of documents) (*.ubx)
-
+ Openboard (zbiór dokumentów) (*.ubx)
@@ -1943,27 +1968,27 @@ Czy chcesz ignorować te błędy dla tego hosta?
UBOpenSankoreImporterWidgetCancel
- Anuluj
+ AnulujOpen-Sankore Documents Detected
-
+ Wykryto dokumenty Open-SankoreOpen-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.
-
+ Dokumenty Open-Sankoré są dostępne na twoimkomputerze. Możliwy jest ich import do OpenBoard naciskając przycisk "Kontynuuj" by uruchomić aplikację importującą.Show this panel next time
-
+ Pokaż ten panel następnym razemYou 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.
-
+ Zawsze możesz zyskać dostęp do aplikacji importującej OpenBoard poprzez panel Ustawień w karcie O programie. Uwaga: jeśli zaimportowałaś już dane Open-Sankore, możesz stracić swoje aktualne dokumenty OpenBoard.Proceed
-
+ Kontynuuj
@@ -1978,6 +2003,10 @@ Czy chcesz ignorować te błędy dla tego hosta?
OpenBoard 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.
+ OpenBoard stracił dostęp do repozytorium dokumentów '%1'. Niestety aplikacja musi zostać zamknięta by uniknąć korupcji danych. Ostatnie zmiany również mogą zostać utracone.
+
+
+ Renaming pages (%1/%2)
@@ -2064,7 +2093,7 @@ Czy chcesz ignorować te błędy dla tego hosta?
OpenBoard Cast
-
+ OpenBoard Cast
@@ -2123,7 +2152,7 @@ Czy chcesz ignorować te błędy dla tego hosta?
UBStartupHintsPaletteVisible next time
-
+ Pokaż następnym razem
@@ -2143,12 +2172,16 @@ Czy chcesz ignorować te błędy dla tego hosta?
%1 thumbnails generated ...Wygenerowano %1 miniatur...
+
+ Loading thumbnail (%1/%2)
+
+ UBThumbnailTextItemPage %0
- Strona %0
+ Strona %0
@@ -2183,7 +2216,7 @@ Czy chcesz ignorować te błędy dla tego hosta?
Axes
-
+ Osie
@@ -2461,7 +2494,7 @@ Aby uzyskać dostęp do zaktualizowanych dokumentów, należy ponownie uruchomi
WBTabBarNew &Tab
- Nowa zakładka
+ &Nowa zakładkaClone Tab
@@ -2469,11 +2502,11 @@ Aby uzyskać dostęp do zaktualizowanych dokumentów, należy ponownie uruchomi
&Close Tab
- Zamknij zakładkę
+ &Zamknij kartęClose &Other Tabs
- Zamknij inne zakładki
+ Zamknij &Inne kartyReload Tab
@@ -2534,7 +2567,7 @@ Aby uzyskać dostęp do zaktualizowanych dokumentów, należy ponownie uruchomi
Download PDF Document: would you prefer to download the PDF file or add it to the current OpenBoard document?
-
+ Pobierz dokument PDF: chcesz pobrać plik PDF, czy dodać go do aktualnego dokumentu OpenBoard?
@@ -2548,7 +2581,7 @@ Aby uzyskać dostęp do zaktualizowanych dokumentów, należy ponownie uruchomi
XPDFRendererProcessing...
-
+ Przetwarzanie...
@@ -2591,19 +2624,15 @@ p, li { white-space: pre-wrap; }
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
p, li { white-space: pre-wrap; }
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Lucida Grande'; font-size:10pt;">Klikając „Wyślij”, poświadczasz, że posiadasz wszelkie prawa do zawartości lub masz zezwolenie właściciela zawartości na jej publiczne udostępnianie w serwisie YouTube, a także, że zawartość jest zgodna z Warunkami korzystania z serwisu YouTube dostępnymi pod adresem </span><a href="http://www.youtube.com/t/terms"><span style=" font-family:'Lucida Grande'; font-size:10pt; text-decoration: underline; color:#0000ff;">http://www.youtube.com/t/terms</span></a></p></body></html>
-
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Lucida Grande'; font-size:10pt;">Klikając „Wyślij”, poświadczasz, że posiadasz wszelkie prawa do zawartości lub masz zezwolenie właściciela zawartości na jej publiczne udostępnianie w serwisie YouTube, a także, że zawartość jest zgodna z Warunkami korzystania z serwisu YouTube dostępnymi pod adresem </span><a href="http://www.youtube.com/t/terms"><span style=" font-family:'Lucida Grande'; font-size:10pt; text-decoration: underline; color:#0000ff;">http://www.youtube.com/t/terms</span></a></p></body></html>
OpenBoard
-
- OpenBoard
-
-
+ OpenBoardRestore credentials on reboot
-
+ Przywróć dane logowania po restarcie
@@ -2642,11 +2671,11 @@ p, li { white-space: pre-wrap; }
Show preview circle from
-
+ Pokaż podgląd pędzla odpx
-
+ px
@@ -2699,23 +2728,23 @@ p, li { white-space: pre-wrap; }
documentsOpenBoard Documents
-
+ Dokumenty OpenBoardCreation date
-
+ Data utworzeniaUpdate date
-
+ Data modyfikacjiAlphabetical order
-
+ Porządek alfabetycznySort Order
-
+ Porządek sortowania
@@ -2738,7 +2767,7 @@ p, li { white-space: pre-wrap; }
Display
- Wyświetlaj
+ WyświetlanieInternet
@@ -2858,63 +2887,63 @@ p, li { white-space: pre-wrap; }
On Dark Background
- Na ciemnym tle
+ Na ciemnym tleOpacity
- Nieprzezroczystość
+ NieprzezroczystośćOn Light Background
- Na jasnym tle
+ Na jasnym tleSwap first and second view displays
-
+ Zamień wyświetlaczeBuilt-in virtual keyboard button size:
-
+ Rozmiar klawiszy wyświetlanej klawiatury:Use system keyboard (recommended)
-
+ Użyj klawiatury systemowej (zalecane)Grid
-
+ KratkaOpen-Sankoré Importer
-
+ Open-Sankoré ImporterCheck if Open-Sankoré data could be imported at launch
-
+ Sprawdź czy dane Open-Sankoré mogą być zaimportowane przy starcieDocuments Mode
-
+ Tryb dokumentówDisplay date column on alphabetical sort
-
+ Wyświetl kolumnę dat w porządku alfabetycznymEmpty trash for documents older than
-
+ Usuń dokumenty z kosza, które są starsze niżdays
-
+ dniPDF Rendering
-
+ Renderowanie PDFImprove zoom execution time (can slightly affect rendering quality)
-
+ Usprawnij wykonywanie przybliżania (może nieco pogorszyć jakość renderowania)
@@ -2925,7 +2954,7 @@ p, li { white-space: pre-wrap; }
Select a flash to trap
- Wybierz Flash do złapania
+ Wybierz Flash do złapaniaabout:blank
@@ -2939,5 +2968,9 @@ p, li { white-space: pre-wrap; }
Create ApplicationStwórz aplikację
+
+ Select a content to capture
+
+
diff --git a/resources/i18n/OpenBoard_pt.ts b/resources/i18n/OpenBoard_pt.ts
index 8ba43ccf..c79bf7b2 100644
--- a/resources/i18n/OpenBoard_pt.ts
+++ b/resources/i18n/OpenBoard_pt.ts
@@ -698,11 +698,11 @@
Flash Trap
- Captura de Flash
+ Captura de FlashTrap Flash Content
- Captura de Conteúdo Flash
+ Captura de Conteúdo FlashWeb Trap
@@ -841,6 +841,10 @@
Draw intermediate grid lines
+
+ Capture Web Content
+
+ PasswordDialog
@@ -898,6 +902,14 @@
Are you sure you want to remove 1 page from the selected document '%0'?Tem a certeza que quer remover 1 página do documento selecionado '%0'?
+
+ Loading scene (%1/%2)
+
+
+
+ Moving cached scenes (%1/%2)
+
+ UBApplication
@@ -909,6 +921,10 @@
PodcastPodcast
+
+ Cannot open your UBX file directly. Please import it in Documents mode instead
+
+ UBApplicationController
@@ -1236,6 +1252,10 @@
Title page
+
+ Refreshing Document Thumbnails View (%1/%2)
+
+ UBDocumentManager
@@ -1286,6 +1306,10 @@
Page %0Página %0
+
+ Generating thumbnails for board (%1/%2)
+
+ UBDocumentReplaceDialog
@@ -2002,6 +2026,10 @@ Quer ignorar estes erros, deste servidor?
OpenBoard 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.
+
+ Renaming pages (%1/%2)
+
+ UBPlatformUtils
@@ -2158,6 +2186,10 @@ Quer ignorar estes erros, deste servidor?
%1 thumbnails generated ...%1 de miniaturas geradas ...
+
+ Loading thumbnail (%1/%2)
+
+ UBThumbnailTextItem
@@ -2940,7 +2972,7 @@ p, li { white-space: pre-wrap; }
Select a flash to trap
- Selecionar o flash a capturar
+ Selecionar o flash a capturarabout:blank
@@ -2954,5 +2986,9 @@ p, li { white-space: pre-wrap; }
Create ApplicationCriar Aplicação
+
+ Select a content to capture
+
+
diff --git a/resources/i18n/OpenBoard_pt_BR.ts b/resources/i18n/OpenBoard_pt_BR.ts
index b5240dd5..342e27e7 100644
--- a/resources/i18n/OpenBoard_pt_BR.ts
+++ b/resources/i18n/OpenBoard_pt_BR.ts
@@ -1,1716 +1,1803 @@
-
+BlackoutWidgetClick to Return to Application
- Clicar para voltar para a Aplicação
+ Clique para voltar à AplicaçãoDownloadDialogDownloads
- Transferências
+ TransferênciasClean Up
- Limpar
+ Limpar0 Items
- 0 Itens
+ 0 ItensDownloadItemForm
- Formulário
+ FormulárioFilename
- Nome do arquivo
+ Nome do arquivoTry Again
- Tentar novamente
+ Tentar novamenteStop
- Parar
+ PararOpen
- Abrir
+ AbrirIntranetPodcastPublishingDialogPublish Podcast to YouTube
- Publicar Podcast no YouTube
+ Publicar Podcast no YouTubeTitle
- Título
+ TítuloDescription
- Descrição
+ DescriçãoAuthor
- Autor
+ AutorMainWindow
+
+ OpenBoard
+ OpenBoard
+ Board
- Quadro
+ QuadroWeb
- Web
+ WebDocuments
- Documentos
+ DocumentosStylus
- Paleta
+ PaletaCtrl+T
- Ctrl+T
+ Ctrl+TBackgrounds
- Fundo
+ FundoChange Background
- Mudar Fundo
+ Mudar FundoUndo
- Desfazer
+ DesfazerCtrl+Z
- Ctrl+Z
+ Ctrl+ZRedo
- Refazer
+ RefazerCtrl+Y
- Ctrl+Y
+ Ctrl+YPrevious
- Anterior
+ AnteriorPrevious Page
- Página anterior
+ Página anteriorPgUp
- Subir na página
+ Subir na páginaNext
- Próximo
+ PróximoNext Page
- Próxima Página
+ Próxima PáginaPgDown
- Descer na página
+ Descer na páginaManage Documents
- Gerir Documentos
+ Gerir DocumentosCtrl+D
- Ctrl+D
+ Ctrl+DWeb Browsing
- Navegar na Web
+ Navegar na WebCtrl+W
- Ctrl+W
+ Ctrl+WLine
- Linha
+ LinhaSmall Line
- Traço Fino
+ Traço FinoMedium Line
- Traço Médio
+ Traço MédioLarge Line
- Traço Grosso
+ Traço GrossoQuit
- Sair
+ Sair
- Eraser
- Borracha
+ Quit OpenBoard
+ Fechar OpenBoard
- Smalle Eraser
- Borracha Pequena
+ Eraser
+ BorrachaMedium Eraser
- Borracha Média
+ Borracha MédiaLarge Eraser
- Borracha Grande
-
-
- Color
- Cores
+ Borracha GrandeBack
- Recuar
+ VoltarLeft
- Esquerda
+ EsquerdaForward
- Avançar
+ AvançarRight
- Direita
+ DireitaReload
- Recarregar
+ RecarregarReload Current Page
- Recarregar a página atual
+ Recarregar a página atualHome
- Página Inicial
+ Página InicialLoad Home Page
- Carregar a Página Inicial
+ Carregar a Página InicialBookmarks
- Favoritos
+ FavoritosShow Bookmarks
- Mostrar os Favoritos
+ Mostrar os FavoritosBookmark
- Favorito
+ FavoritoAdd Bookmark
- Adicionar aos Favoritos
+ Adicionar aos FavoritosDisplay Board
- Mostrar o Quadro
+ Mostrar o QuadroCtrl+B
- Ctrl+B
+ Ctrl+BErase
- Apagar
+ ApagarErase Content
- Apagar Conteúdo
+ Apagar ConteúdoPreferences
- Preferências
+ PreferênciasDisplay Preferences
- Mostrar Preferências
+ Mostrar PreferênciasLibrary
- Biblioteca
+ BibliotecaShow Library
- Mostrar Biblioteca
+ Mostrar BibliotecaCtrl+L
- Ctrl+L
+ Ctrl+LShow Desktop
- Ver desktop
+ Área de TrabalhoShow Computer Desktop
- Mostrar o ambiente de trabalho do Computador
+ Mostrar o ambiente de trabalho do ComputadorCtrl+Shift+H
- Ctrl+Shift+H
+ Ctrl+Shift+HBigger
- Ampliar
+ AmpliarZoom In
- Aproximar
+ AmpliarCtrl++
- Ctrl++
+ Ctrl++Smaller
- Reduzir
+ ReduzirZoom Out
- Afastar
+ AfastarCtrl+-
- Ctrl+-
+ Ctrl+-New Folder
- Nova Pasta
+ Nova PastaCreate a New Folder
- Criar uma Nova Pasta
+ Criar uma Nova PastaNew Document
- Novo Documento
+ Novo DocumentoCreate a New Document
- Criar um Novo Documento
+ Criar um Novo DocumentoImport
- Importar
+ ImportarImport a Document
- Importar um Documento
+ Importar um DocumentoExport
- Exportar
+ ExportarExport a Document
- Exportar um Documento
+ Exportar um DocumentoOpen in Board
- Abrir no Quadro
+ Abrir no QuadroOpen Page in Board
- Abrir Página no Quadro
+ Abrir Página no QuadroCtrl+O
- Ctrl+O
+ Ctrl+ODuplicate
- Duplicar
+ DuplicarDuplicate Selected Content
- Duplicar o Conteúdo Selecionado
+ Duplicar o Conteúdo SelecionadoDelete
- Apagar
+ ApagarDelete Selected Content
- Apagar o Conteúdo Selecionado
+ Apagar o Conteúdo SelecionadoDel
- Del
+ DelAdd to Working Document
- Adicionar ao Documento de Trabalho
+ Adicionar ao Documento de TrabalhoAdd Selected Content to Open Document
- Adicionar o Conteúdo Selecionado ao Documento Aberto
+ Adicionar o Conteúdo Selecionado ao Documento AbertoAdd
- Adicionar
+ AdicionarAdd Content to Document
- Adicionar Conteúdo ao Documento
+ Adicionar Conteúdo ao DocumentoRename
- Mudar o Nome
+ Mudar o NomeRename Content
- Mudar o Nome do Conteúdo
+ Mudar o Nome do ConteúdoTools
- Ferramentas
+ FerramentasDisplay Tools
- Mostrar Ferramentas
+ Mostrar FerramentasMulti Screen
- Múltiplos Monitores
+ Múltiplos MonitoresWide Size (16/9)
- Formato Panorâmico (16/9)
+ Formato Panorâmico (16/9)Use Document Wide Size (16/9)
- Usar documento no Formato Panorâmico (16/9)
+ Usar documento no Formato Panorâmico (16/9)Regular Size (4/3)
- Formato Tradicional (4/3)
+ Formato Tradicional (4/3)Use Document Regular Size (4/3)
- Usar documento no Formato Tradicional (4/3)
+ Usar documento no Formato Tradicional (4/3)Custom Size
- Tamanho Personalizado
+ Tamanho PersonalizadoUse Custom Document Size
- Usar documento no Tamanho Personalizado
+ Usar documento no Tamanho PersonalizadoStop Loading
- Parar de Carregar
+ Parar de CarregarStop Loading Web Page
- Parar de Carregar a Página Web
+ Parar de Carregar a Página WebCut
- Cortar
+ CortarCopy
- Copiar
+ CopiarPaste
- Colar
+ ColarSleep
- Modo "Espera"
+ Modo "Espera"Put Presentation to Sleep
- Colocar a Apresentaçãao em modo "Espera"
+ Colocar a Apresentaçãao em modo "Espera"Virtual Keyboard
- Teclado Virtual
+ Teclado VirtualDisplay Virtual Keyboard
- Mostrar o Teclado Virtual
+ Mostrar o Teclado VirtualPlain Light Background
- Fundo Branco e Liso
+ Fundo Branco e LisoLight
- Claro
+ ClaroGrid Light Background
- Fundo Branco e Quadriculado
+ Fundo Claro Quadriculado
+
+
+ Ruled Light Background
+ Caderno com Fundo ClaroPlain Dark Background
- Fundo Preto e Liso
+ Fundo Escuro QuadriculadoDark
- Escuro
+ EscuroGrid Dark Background
- Fundo Preto e Quadriculado
+ Fundo Escuro Quadriculado
+
+
+ Ruled Dark Background
+ Caderno com Fundo EscuroPodcast
- Podcast
+ PodcastRecord Presentation to Video
- Gravar a Apresentação em Vídeo
+ Gravar a Apresentação em VídeoRecord
- Gravar
+ GravarStart Screen Recording
- Iniciar a Gravação do Vídeo
+ Iniciar a Gravação do VídeoErase Items
- Apagar Itens
+ Apagar ItensErase All Items
- Apagar Todos os Itens
+ Apagar Todos os ItensErase Annotations
- Apagar Anotações
+ Apagar AnotaçõesErase All Annotations
- Apagar Todas as Anotações
+ Apagar Todas as AnotaçõesClear Page
- Limpar a Página
+ Limpar a PáginaClear All Elements
- Limpar Todos os Elementos
+ Limpar Todos os ElementosPen
- Caneta
+ CanetaAnnotate Document
- Escrever
+ EscreverCtrl+I
- Ctrl+I
+ Ctrl+IErase Annotation
- Apagar
+ Apagar AnotaçãoCtrl+E
- Ctrl+E
+ Ctrl+EMarker
- Marcador
+ Marca-TextoHighlight
- Marcador
+ Realçar Ctrl+M
- Ctrl+M
+ Ctrl+MSelector
- Seletor
+ SeletorSelect And Modify Objects
- Selecionar e Modificar Objetos
+ Selecionar e Modificar ObjetosCtrl+F
- Ctrl+F
+ Ctrl+FHand
- Mão
+ MãoScroll Page
- Desloca-se na página
+ Arrastar a páginaLaser Pointer
- Apontador Laser
+ Apontador LaserVirtual Laser Pointer
- Apontador Laser Virtual
+ Apontador Laser VirtualCtrl+G
- Ctrl+G
+ Ctrl+GDraw Lines
- Desenhar Linhas
+ Desenhar LinhasCtrl+J
- Ctrl+J
+ Ctrl+JText
- Texto
+ TextoWrite Text
- Escrever Texto
+ Escrever TextoCtrl+K
- Ctrl+K
+ Ctrl+KCapture
- Capturar
+ CapturarCapture Part of the Screen
- Capturar uma Parte da Tela
+ Capturar uma Parte da TelaAdd To Current Page
- Adicionar à Página Atual
+ Adicionar à Página AtualAdd Item To Current Page
- Adicionar Item à Página Atual
+ Adicionar Item à Página AtualAdd To New Page
- Adicionar a uma Página Nova
+ Adicionar a uma Página NovaAdd Item To New Page
- Adicionar Item a uma Página Nova
+ Adicionar Item a uma Página NovaAdd To Library
- Adicionar à Biblioteca
+ Adicionar à BibliotecaAdd Item To Library
- Adicionar Item à Biblioteca
+ Adicionar Item à BibliotecaPages
- Páginas
+ PáginasCreate a New Page
- Criar uma Nova Página
+ Criar uma Nova PáginaNew Page
- Nova Página
+ Nova PáginaDuplicate Page
- Duplicar Página
+ Duplicar PáginaDuplicate the Current Page
- Duplicar a Página Atual
+ Duplicar a Página AtualImport Page
- Importar Página
+ Importar PáginaImport an External Page
- Importar uma Página Externa
+ Importar uma Página ExternaPause
- Pausa
+ PausaPause Podcast Recording
- Pausar a Gravação do Podcast
+ Pausar a Gravação do PodcastPodcast Config
- Configuração do Podcast
+ Configuração do PodcastConfigure Podcast Recording
- Configuração da Gravação de Podcast
+ Configuração da Gravação de PodcastFlash Trap
- Captura de Flash
+ Captura de FlashTrap Flash Content
- Captura de Conteúdo Flash
+ Captura de Conteúdo FlashWeb Trap
- Captura de Web
+ Captura de WebTrap Web Content
- Captura de Conteúdo Web
+ Captura de Conteúdo WebCustom Capture
- Captura Personalizada
+ Captura PersonalizadaWindow Capture
- Captura da Janela
+ Captura da JanelaCapture a Window
- Capturar uma Janela
+ Capturar uma JanelaEmbed Web Content
- Conteúdo Web Embutido
+ Conteúdo Web EmbutidoCapture Embeddable Web Content
- Capturar Conteúdo Web Embutido
+ Capturar Conteúdo Web EmbutidoShow on Display
- Mostrar no Vídeo
+ Mostrar no VídeoShow Main Screen on Display Screen
- Mostrar a Tela Principal no Vídeo
+ Mostrar a Tela Principal no VídeoErase all Annotations
- Apagar todas as notas
+ Apagar todas as notaseduMedia
- eduMedia
+ eduMediaImport eduMedia simulation
- Importar uma simulação eduMedia
+ Importar uma simulação eduMediaCheck Update
- Verificar Atualização
-
-
- Ctrl+H
- Ctrl+H
-
-
- OpenBoard
- OpenBoard
-
-
- Quit OpenBoard
- Sair do OpenBoard
+ Verificar AtualizaçãoHide OpenBoard
- Ocultar o OpenBoard
+ Ocultar o OpenBoardHide OpenBoard Application
- Ocultar a Aplicação OpenBoard
+ Ocultar a Aplicação OpenBoard
+
+
+ Ctrl+H
+ Ctrl+HPlayComeçar(?)
- Iniciar
+ IniciarInteract with items
- Interagir com itens
+ Interagir com itensErase Background
- Apagar o fundo
+ Apagar o fundoRemove the backgound
- Remover o fundo
+ Remover o fundoOpen Tutorial
- Abrir Tutorial
+ Abrir TutorialOpen the tutorial web page
- Abrir a página web de tutorial
+ Abrir tutorial na web
+
+
+ Reset grid size
+ Redefinir o tamanho da grade
+
+
+ Small Eraser
+ Borracha estreita
+
+
+ Color 1
+ Cor 1
+
+
+ Color 2
+ Cor 2
+
+
+ Color 3
+ Cor 3
+
+
+ Color 4
+ Cor 4
+
+
+ Color 5
+ Cor 5
+
+
+ Draw intermediate grid lines
+ Desenhar linhas intermediáriasPasswordDialogAuthentication Required
- Autenticação Necessária
+ Autenticação NecessáriaUsername:
- Usuário:
+ Usuário:Password:
- Senha:
+ Senha:ProxyDialogProxy Authentication
- Autenticação do Proxy
+ Autenticação do ProxyConnect to Proxy
- Conetar ao Proxy
+ Conetar ao ProxyUsername:
- Nome de Utilizador:
+ Nome do Usuário:Password:
- Senha:
+ Senha:Save username and password for future use
- Gravar "Nome de Usuário" e "Senha" para futuras utilizações
+ Gravar "Nome de Usuário" e "Senha" para futuras utilizaçõesQObjectElement ID =
- ID do Elemento
+ ID do ElementoContent is not supported in destination format.
- O conteúdo não é suportado no formato de destino.
+ O conteúdo não é suportado no formato de destino.Remove Page
- Remover Página
+ Remover PáginaAre you sure you want to remove 1 page from the selected document '%0'?
- Tem a certeza que quer remover 1 página do documento selecionado '%0'?
+ Tem certeza que deseja remover 1 página do documento '%0' selecionado?
+
+
+ Common
+ UsualUBApplicationPage Size
- Tamanho da Página
+ Tamanho da PáginaPodcast
- Podcast
+ PodcastUBApplicationControllerWeb
- Web
+ WebUpdate available
- Atualização disponível
+ Atualização disponívelNew update available, would you go to the web page ?
- Nova atualização disponível. Ir para a página web?
+ Atualização disponível: deseja ir até a página de download?
+
+
+ Update
+ AtualizarNo update available
- Nenhuma atualização disponível
+ Sem atualização disponível
+
+
+ UBBackgroundPalette
- Update
- Atualizar
+ Grid size
+ Tamanho da grade
+
+
+ Draw intermediate grid lines
+ Desenhar linhas de grade intermediáriasUBBoardController
- Downloading content %1 failed
- A transferência de conteúdos falhou %1
+ Group
+ Agrupar
- Download finished
- Transferência Completa
+ Ungroup
+ Desagrupar
- Unknown tool type %1
- Tipo de ferramenta desconhecido %1
+ Saving document...
+ Salvando documento...
- Unknown content type %1
- Tipo de conteúdo desconhecido %1
+ Document has just been saved...
+ O documento acabou de ser salvo...
- Add Item
- Adicionar Item
+ Deleting page %1
+ Deletando página %1
- All Supported (%1)
- Tudo Suportado (%1)
+ Page %1 deleted
+ Página %1 deletada
- Delete page %1 from document
- Apagar a página %1 do documento
+ Downloading content %1 failed
+ A transferência de conteúdos falhou %1
- Page %1 deleted
- Página %1 apagada
+ Download finished
+ Transferência concluídaAdd file operation failed: file copying error
- Falha na operação de adição de arquivo: erro na cópia do arquivo
+ Falha na operação de adição de arquivo: erro ao copiar arquivo
- Group
- Agrupar
+ Unknown tool type %1
+ Tipo de ferramenta desconhecido %1
- Ungroup
- Desagrupar
+ Unknown content type %1
+ Tipo de conteúdo desconhecido %1
- Saving document...
- Gravando documento...
+ Add Item
+ Adicionar Item
- Document has just been saved...
- Documento acaba de ser gravado...
+ All Supported (%1)
+ Tudo Suportado (%1)
+
+
+ Color
+ CorUBBoardPaletteManager
+
+ CapturedImage
+ Imagem capturada
+ Error Adding Image to Library
- Erro ao Adicionar Imagem à Biblioteca
+ Erro ao Adicionar Imagem à Biblioteca
+
+
+ UBBoardThumbnailsView
- CapturedImage
- Imagem capturada
+ Loading page (%1/%2)
+ Carregando página (%1/%2)UBCachePropertiesWidgetCache Properties
- Propriedades da Cache
+ Propriedades da CacheColor:
- Cor:
+ Cor:Shape:
- Forma:
+ Forma:Size:
- Tamanho:
+ Tamanho:Close
- Fechar
+ FecharUBDesktopPalette
+
+ Show OpenBoard
+ Mostrar OpenBoard
+ Capture Part of the Screen
- Capturar Parte da Tela
+ Capturar Parte da TelaCapture the Screen
- Capturar Tela
+ Capturar TelaShow the stylus palette
- Mostrar Paleta
+ Mostrar PaletaShow Board on Secondary Screen
- Mostrar o Quadro num Vídeo Secundário
+ Mostrar o Quadro numa Tela SecundáriaShow Desktop on Secondary Screen
- Mostrar Ambiente de Trabalho num Vídeo Secundário
-
-
- Show OpenBoard
- Mostrar OpenBoard
+ Mostrar Área de Trabalho numa Tela SecundáriaUBDocumentController
- New Folder
- Nova Pasta
+ Trash
+ Lixeira
- Page %1
- Página %1
+ Untitled Documents
+ Documentos sem nome
+
+
+ New Folder
+ Nova PastaAdd Folder of Images
- Adicionar Pasta de Imagens
+ Adicionar Pasta de ImagensAdd Images
- Adicionar Imagens
+ Adicionar ImagensAdd Pages from File
- Adicionar Páginas de um Arquivo
+ Adicionar Páginas de um Arquivo
+
+
+ duplicated %1 page
+ duplicated %1 pages
+
+ %1 página duplicada
+ %1 páginas duplicadas
+ Duplicating Document %1
- A Duplicar Documento %1
+ Copiando Documento %1Document %1 copied
- Documento %1 Copiado
-
-
- Remove Page
- Remover Página
-
-
- Remove Document
- Remover Documento
-
-
- Are you sure you want to remove the document '%1'?
- Tem a certeza que quer remover o documento '%1'?
-
-
- Empty Trash
- Vazar Lixo
-
-
- Are you sure you want to empty trash?
- Tem a certeza que quer vazar a pasta Lixo?
+ Documento %1 copiado
- Emptying trash
- A vazar Lixo
+ Remove Item
+ Remover Item
- Emptied trash
- Pasta Lixo limpa
-
-
- Remove Folder
- Apagar Pasta
-
-
- Are you sure you want to remove the folder '%1' and all its content?
- Tem a certeza que quer apagar a pasta '%1' e todo o seu conteúdo?
-
-
- No document selected!
- Não há documentos selecionados!
+ Are you sure you want to remove the selected item(s) ?
+ Tem certeza que deseja excluir os itens selecionados?Open Supported File
- Abrir Arquivo Suportado
+ Abrir Arquivo SuportadoImporting file %1...
- Importando arquivo %1...
+ Importando arquivo %1...Failed to import file ...
- Falha ao importar arquivo ...
+ Falha ao importar arquivo ...Import all Images from Folder
- Importar todas as Imagens de uma Pasta
-
-
- Delete
- Apagar
+ Importar todas as Imagens de uma Pasta
- Empty
- Vazio
+ Folder does not contain any image files
+ A pasta não contém imagens
- Trash
- Lixo
+ Open Document
+ Abrir Documento
- Open Document
- Abrir Documento
+ 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?
+ O documento '%1' foi produzido com uma versão mais nova do OpenBoard (%2). Ao abri-lo, você poderá perder alguma informação. Gostaria de continuar?Add all Images to Document
- Adicionar todas as imagens ao Documento
+ Adicionar todas as imagens ao DocumentoAll Images (%1)
- Todas as Imagens (%1)
+ Todas as Imagens (%1)Selection does not contain any image files!
- A seleção não contém arquivos de Imagem!
-
-
- Are you sure you want to remove %n page(s) from the selected document '%1'?
-
- Tem certeza que quer apagar %n página do documento selecionado '%1'?
- Tem certeza que quer apagar %n páginas do documento selecionado '%1'?
-
-
-
- Folder does not contain any image files
- O diretório não contém imagens
+ A seleção não contém arquivos de Imagem!
- Untitled Documents
- Documentos sem nome
+ Delete
+ Apagar
- 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?
- O documento '%1' foi produzido com uma versão mais nova do OpenBoard (%2). Ao abri-lo, você poderá perder alguma informação. Gostaria de continuar?
+ Page %1
+ Página %1
- Are you sure you want to remove all selected documents?
- Você tem certeza que deseja remover todos os documentos selecionados?
+ Title page
+ Título da página
- Remove multiple documents
- Remover múltiplos documentos
+ Empty
+ VazioUBDocumentManagerimages
- imagens
+ imagensvideos
- vídeos
+ vídeosobjects
- objetos
+ objetoswidgets
- widgets
+ widgetsAll supported files (*.%1)
- Todos os arquivos suportados (*.%1)
-
-
- File %1 saved
- Arquivo %1 gravado
+ Todos os arquivos suportados (*.%1)Inserting page %1 of %2
- A inserir página %1 de %2
+ A inserir página %1 de %2Import successful.
- Importação bem sucedida.
+ Importado com sucesso..
+
+
+ Importing file %1
+ Importando o arquivo %1Import of file %1 successful.
- Importação do arquivo %1 bem sucedida.
+ Importação do arquivo %1 bem sucedida.
- Importing file %1
- Importando o arquivo %1
+ File %1 saved
+ Arquivo %1 gravadoUBDocumentNavigatorPage %0
- Página %0
+ Página %0
- UBDocumentTreeWidget
+ UBDocumentReplaceDialog
- %1 (copy)
- %1 (cópia)
+ Accept
+ Aceitar
- Copying page %1/%2
- Copiando página %1/%2
+ Replace
+ Substituir
+
+
+ Cancel
+ Cancelar
+
+
+ The name %1 is allready used.
+Keeping this name will replace the document.
+Providing a new name will create a new document.
+ O nome %1 já está em uso.
+ATENÇÃO: Ao manter este nome, o documento antigo será sobrescrito pelo novo.
+Um outro nome permitirá que você mantenha o documento antigo.
+
+
+
+ UBDocumentTreeModel
+
+ My documents
+ Meus documentos
+
+
+ Trash
+ Lixeira
+
+
+ %1 pages copied
+
+ %1 página copiada
+ %1 páginas copiadas
+
+
+
+ UBDocumentTreeView%1 pages copied
-
+ %1 página copiada%1 páginas copiadas
+
+ Remove Item
+ Remover itens
+
+
+ Are you sure you want to remove the selected item(s) ?
+ Tem certeza que deseja excluir os itens selecionados?
+
+
+ Copying page %1/%2
+ Cópia da página %1/%2 em andamento
+ UBDownloadWidgetDownloading files
- Baixando arquivos
+ Transferindo arquivosCancel
- Cancelar
+ Cancelar
- UBExportAdaptor
+ UBDraggableThumbnail
- Warnings during export was appeared
- Surgiram alertas durante a exportação
+ Page %0
+ Página %0
- UBExportCFF
+ UBDraggableThumbnailView
- Export to IWB
- Exportar para IWB
+ Page %0
+ Página %0
+
+
+ UBExportAdaptor
- Export as IWB File
- Exportar como arquivo IWB
+ Exporting document...
+ A exportar documento...
- Exporting document...
- A exportar documento...
+ Export failed
+ Falha ao exportar
+
+
+ Unable to export to the selected location. You do not have the permissions necessary to save the file.
+ Impossível exportar para a localização selcionada. Você não possui as permissões necessárias para gravar o arquivo.
+
+
+ Export failed: location not writable
+ Exportação falhou: localização não gravávelExport successful.
- Exportação bem sucedida.
+ Exportado com sucesso.
- Export failed.
- Falha na Exportação.
+ Warnings during export was appeared
+ Surgiram alertas durante a exportação
- UBExportDocument
+ UBExportCFF
- Page
- Página
+ Export to IWB
+ Exportar como IWB
- Export as UBZ File
- Exportar como Arquivo UBZ
+ Export as IWB File
+ Exportar como arquivo IWBExporting document...
- A exportar documento...
+ A exportar documento...Export successful.
- Exportação bem sucedida.
+ Exportado com sucesso.
- Exporting %1 %2 of %3
- A exportar %1 %2 de %3
+ Export failed.
+ Falha na Exportação.
+
+
+ UBExportDocument
- Export to OpenBoard Format
- Exportar para o formato OpenBoard
+ Page
+ Página
- Export failed: location not writable
- Exportação falhou: localização não gravável
+ Export as UBZ File
+ Exportar como Arquivo UBZ
- Export failed
- Exportação falhou
+ Exporting %1 %2 of %3
+ A exportar %1 %2 de %3
- Unable to export to the selected location. You do not have the permissions necessary to save the file.
- Impossível exportar para a localização selcionada. Você não possui as permissões necessárias para gravar o arquivo.
+ Export to OpenBoard Format
+ Exportar para o formato OpenBoard
- UBExportFullPDF
+ UBExportDocumentSetAdaptor
- Export as PDF File
- Exportar como Arquivo PDF
+ Failed to export...
+ Falha ao exportar...
+
+
+ Export as UBX File
+ Exportar para formato UBX (*.ubx)Exporting document...
- A exportar documento...
+ Exportando documento...Export successful.
- Exportação bem sucedida.
+ Exportado com sucesso.
- Export to PDF
- Exportar para PDF
+ Export failed.
+ Falha ao exportar.
- Export failed: location not writable
- Exportação falhou: localização não gravável
+ Export to OpenBoard UBX Format
+ Exportar para formato OpenBoard UBX
+
+
+ UBExportFullPDF
- Export failed
- Exportação falhou
+ Export as PDF File
+ Exportar como Arquivo PDF
- Unable to export to the selected location. You do not have the permissions necessary to save the file.
- Impossível exportar para a localização selecionada. Você não possui as permissões necessárias para gravar o arquivo.
+ Export to PDF
+ Exportar como PDFUBExportPDFExport as PDF File
- Exportar como Arquivo PDF
-
-
- Exporting document...
- Exportando documento...
-
-
- Export successful.
- Exportação bem sucedida.
+ Exportar como Arquivo PDFExporting page %1 of %2
- Exportando página %1 de %2
+ Exportando página %1 de %2Export to PDF
- Exportar para PDF
+ Exportar como PDFUBExportWebPage
- Página
+ PáginaExport as Web data
- Exportar para formato de Web
+ Exportar para formato de WebExporting document...
- Exportando documento...
+ A exportar documento...Export successful.
- Exportação bem sucedida.
+ Exportado com sucesso.Export failed.
- Falha na exportação.
+ Exportação falhou.Export to Web Browser
- Exportar para Explorador Web
+ Exportar para Navegador WebUBFeaturePropertiesAdd to page
- Adicionar à página
-
-
- Set as background
- Definir como fundo
+ Adicionar à páginaAdd to library
- Adicionar à biblioteca
+ Adicionar à bibliotecaObject informations
- Informações do Objecto
+ Informações do ObjetoUBFeaturesActionBarAdd to favorites
- Adicionar aos favoritos
+ Adicionar aos favoritosShare
- Partilhar
+ PartilharSearch
- Procurar
+ Procurar
+
+
+ Rescan file system
+ Verificar novamente o sistema de arquivosDelete
- Apagar
+ ApagarBack to folder
- Voltar à pasta
+ Voltar à pastaRemove from favorites
- Remover dos favoritos
+ Remover dos favoritosCreate new folder
- Criar uma nova pasta
-
-
- Rescan file system
- "Procurar arquivo de Sistema"(?)
- Voltar a procurar arquivo de Sistema
+ Criar uma nova pastaUBFeaturesController
-
- ImportedImage
- Imagem Importada
- Audios
- Áudios
+ ÁudiosMovies
- Vídeos
+ VídeosPictures
- Imagens
+ ImagensAnimations
- Animações
+ FlashInteractivities
- Atividades Interativas
+ InteragirApplications
- Aplicações
+ UtilidadesShapes
- Formas
+ FormasFavorites
- Favoritos
+ FavoritosWeb search
- Busca na web
+ Busca WebTrash
- Lixo
+ Lixeira
+
+
+ ImportedImage
+ Imagem ImportadaUBFeaturesNewFolderDialogAccept
- Aceitar
+ AceitarCancel
- Cancelar
+ CancelarEnter a new folder name
- Escrever um novo nome para o diretório
+ Dê um novo nome para o diretórioUBFeaturesProgressInfoLoading
- A carregar
+ A carregarUBGraphicsGroupContainerItemDelegateLocked
- Bloqueado
+ BloqueadoVisible on Extended Screen
- Visível em Vídeo Expandido
+ Visível na Tela EstendidaUBGraphicsItemDelegateLocked
- Bloqueado
+ BloqueadoVisible on Extended Screen
- Visível em Vídeo Expandido
+ Visível na Tela Estendida
+
+
+ Set as background
+ Definir como fundoGo to Content Source
- Ir para a Fonte do Conteúdo
+ Ir para a Fonte do ConteúdoUBGraphicsMediaItemMedia resource couldn't be resolved
- Recurso de mídia não pode ser resolvido
+ Recurso de mídia não pôde ser resolvidoUnsupported media format
- Formato de mídia não suportado
+ Formato de mídia não suportadoMedia playback service not found
- Serviço de reprodução de mídia não encontrado
+ Serviço de reprodução de mídia não encontradoMedia error:
- Erro de mídia:
+ Erro na mídia:UBGraphicsTextItem<Type Text Here>
- <Introduzir o Texto Aqui>
+ <Digite o Texto Aqui>UBGraphicsTextItemDelegateText Color
- Cor do Texto
+ Cor do TextoEditable
- Editável
+ EditávelUBGraphicsW3CWidgetItemWeb
- Web
+ WebUBGraphicsWidgetItemLoading ...
- Carregando ...
+ Carregando ...UBGraphicsWidgetItemDelegateFrozen
- Congelado
+ CongeladoTransform as Tool
- Transformar em Ferramenta
+ Transformar em FerramentaUBImportCFFCommon File Format (
- Formato de Arquivo Frequente (
+ Formato de Arquivo Frequente (Importing file %1...
- Importando arquivos %1...
+ Importando arquivos %1...Import of file %1 failed.
- Falha a importar arquivo %1.
+ Falha a importar arquivo %1.Import successful.
- Importação bem sucedida.
+ Importado com sucesso..Import failed.
- Falha na importação.
+ Falha na importação.UBImportDocument
+
+ OpenBoard (*.ubz)
+ OpenBoard (*.ubz)
+ Importing file %1...
- Importando arquivo %1...
+ Importando arquivo %1...Import of file %1 failed.
- Falha a importar arquivo %1.
+ Falha a importar arquivo %1.Import successful.
- Importação bem sucedida.
+ Importado com sucesso.
+
+
+ UBImportDocumentSetAdaptor
- OpenBoard (*.ubz)
- OpenBoard (*.ubz)
+ Openboard (set of documents) (*.ubx)
+ Openboard (conjunto de documentos) (*.ubx)UBImportImageImage Format (
- Formato da Imagem (
+ Formato da Imagem (UBImportPDFPortable Document Format (*.pdf)
- Portable Document Format (*.pdf)
+ Portable Document Format (*.pdf)PDF import failed.
- Falha na importação de PDF.
+ Falha na importação de PDF.Importing page %1 of %2
- Importando página %1 de %2
+ Importando página %1 de %2UBIntranetPodcastPublisherError while publishing video to intranet (%1)
- Erro durante a publicação do vídeo na intranet (%1)
+ Erro durante a publicação do vídeo na intranet (%1)Publishing to Intranet in progress %1 %
- Publicação na Intranet em progresso %1 %
+ Publicação na Intranet em progresso %1 %UBIntranetPodcastPublishingDialogPublish
- Publicar
+ PublicarUBKeyboardPaletteEnter
- Enter
+ EnterUBMainWindowYes
- Sim
+ SimNo
- Não
+ NãoOk
- Ok
+ OKUBMessagesDialogClose
- Fechar
+ FecharUBNetworkAccessManager<qt>Enter username and password for "%1" at %2</qt>
- <qt>Introduzir o Nome de Usuário e Senha "%1" em %2</qt>
+ <qt>Introduzir o Nome de Usuário e Senha "%1" em %2</qt>Failed to log to Proxy
- Falha ao entrar no Proxy
+ Falha ao entrar no ProxySSL Errors:
@@ -1720,641 +1807,799 @@
%2
Do you want to ignore these errors for this host?
- Erros SSL:
+ Erros SSL:
%1
%2
-Quer ignorar estes erros, deste servidor?
+Quer ignorar estes erros deste servidor?Yes
- Sim
+ SimNo
- Não
+ NãoUBOpenSankoreImporterWidgetOpen-Sankore Documents Detected
- Documentos do Open-Sankore Detectado
+ Documentos do Open-Sankore Detectados
+
+
+ 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.
+ Há documentos do Open-Sankoré em seu computador. É possível importá-los para o OpenBoard pressionando o botão "Prosseguir" para lançar o recurso de importação.Show this panel next time
- Mostrar este painel da próxima vez
+ Mostrar este painel na próxima vezYou 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.
- Você sempre poderá acessar o Importador de Documentos OpenBoard através do painel de Preferências na aba Sobre. Aviso, se você já importou seus dados do Open-Sankoré, você poderá perder seus atuais documentos do OpenBoard.
+ Você sempre poderá acessar o Importador de Documentos OpenBoard através do painel de Preferências na aba Sobre. Aviso, se você já importou seus dados do Open-Sankoré, você poderá perder seus documentos atuais do OpenBoard.Cancel
- Cancelar
+ CancelarProceed
- Prosseguir
-
-
- 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.
- Documentos do Open-Sankoré estão presentes em seu computador. É possível importá-los para o OpenBoard pressionando o botão "Prosseguir" para lançar a aplicação de importação.
+ ProsseguirUBPersistenceManager(copy)
- (cópia)
+ (cópia)Document Repository Loss
- Repositório de Documentos perdido
+ Repositório de Documentos perdido
- 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.
- Acesso ao repositório '%1' foi perdido. Infelizmente a aplicação deverá desligar para avitar a corrupção de dados. As últimas alterações também serão perdidas.
+ OpenBoard 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.
+ Acesso ao repositório '%1' foi perdido. Infelizmente, deverá encerrar a aplicação para evitar a corrupção de dados. As últimas alterações também serão perdidas.UBPlatformUtilsEnglish
- Inglês
+ InglêsRussian
- Russo
+ RussoGerman
- Alemão
+ AlemãoFrench
- Francês
+ FrancêsSwiss French
- Francês (Suiço)
+ Francês (Suíço)UBPodcastController
+
+ OpenBoard Cast
+ OpenBoard Cast
+ Failed to start encoder ...
- Falha ao iniciar o codificador ...
+ Falha ao iniciar o codificador...No Podcast encoder available ...
- Nenhum codificador de Podcast disponível ...
+ Nenhum codificador de Podcast disponível ...Part %1
- Parte %1
+ Parte %1on your desktop ...
- no seu ambiente de trabalho ...
+ no seu ambiente de trabalho ...in folder %1
- na pasta %1
+ na pasta %1Podcast created %1
- Podcast criado %1
+ Podcast criado %1Podcast recording error (%1)
- Erro de gravação do Podcast (%1)
+ Erro ao gravar Podcast (%1)Default Audio Input
- Entrada de áudio padrão
+ Entrada de áudio padrãoNo Audio Recording
- Sem gravação de áudio
+ Sem gravação de áudioSmall
- Pequeno
+ PequenaMedium
- Médio
+ MédiaFull
- Completo
+ CheiaPublish to Intranet
- Publicar na Intranet
+ Publicar na IntranetPublish to Youtube
- Publicar no Youtube
-
-
- OpenBoard Cast
- OpenBoard Cast
+ Publicar no YoutubeUBPreferencesControllerversion:
- versão:
+ versão: Marker is pressure sensitive
- O marcador é sensível à pressão
+ Marca-texto sensível à pressão
-
-
- UBProxyLoginDlg
- Proxy Login
- Iniciar sessão no Proxy
+ Key sequence already in use
+ Combinação de teclas já em uso
- Username:
- Nome de Utilizador:
+ Mouse button already in use
+ Botão do mouse já em uso
- Password:
- Senha:
+ Stylus button already in use
+ Botão de caneta já em uso
+
+
+ Accept
+ preferencesDialog
+ Aceitar
+
+
+ Record
+ preferencesDialog
+ Gravar
- UBPublicationDlg
+ UBSettings
- Publish document on the web
- Publicar documentos na web
+ My Movies
+ Meus Vídeos
+
+
+ UBShortcutManager
- Title:
- Título:
+ Common
+ Frequente
- Description:
- Descrição:
+ Board
+ Quadro
- Publish
- Publicar
+ Stylus Palette
+ Paleta
-
-
- UBSettings
- My Movies
- Os meus filmes
+ Lines and colours
+ Linhas e cores
+
+
+ Background
+ Fundo
+
+
+ Podcast
+ Podcast
+
+
+ First scene
+ Primeira cena
+
+
+ Show first scene
+ Ver primeira cena
+
+
+ Last scene
+ Última cena
+
+
+ Show last scene
+ Ver última cena
+
+
+ Zoom reset
+ Zoom 1:1
+
+
+ Reset zoom factor
+ Redefinir fator de zoom
+
+
+ Scroll left
+ Rolar para a esquerda
+
+
+ Scroll page left
+ Rolar página para a esquerda
+
+
+ Scroll right
+ Rolar para a direita
+
+
+ Scroll page right
+ Rolar página para a direita
+
+
+ Scroll up
+ Rolar para cima
+
+
+ Scroll page up
+ Rolar página para cima
+
+
+ Scroll down
+ Rolar para baixo
+
+
+ Scroll page down
+ Rolar página para baixo
+
+
+ Built-in (not editable)
+ Integrado (não editável)
+
+
+ Command
+ Comando
+
+
+ Description
+ Descrição
+
+
+ Key Sequence
+ Sequência de Teclas
+
+
+ Mouse Button
+ Botão do Mouse
+
+
+ Tablet Button
+ Botão da Mesa Digitalizadora
+
+
+ Left
+ MouseButton
+ Esquerdo
+
+
+ Right
+ MouseButton
+ Direito
+
+
+ Middle
+ MouseButton
+ Meio
+
+
+ Back
+ MouseButton
+ Voltar
+
+
+ Forward
+ MouseButton
+ Avançar
+
+
+ Task
+ MouseButton
+ Tarefa
+
+
+ Extra
+ MouseButton
+ ExtraUBStartupHintsPaletteVisible next time
- Visível na próxima vez
+ Visível na próxima vez
+
+
+
+ UBTeacherBarWidget
+
+
+ UBThumbnailAdaptorGenerating preview thumbnails ...
- A gerar pré-visualização de miniaturas ...
+ Criando miniaturas de visualização...%1 thumbnails generated ...
- %1 de miniaturas geradas ...
+ %1 miniaturas criadas...
+
+
+
+ UBThumbnailTextItem
+
+ Page %0
+ Página %0UBToolsManagerMask
- Cortina
+ CortinaRuler
- Régua
+ RéguaCompass
- Compasso
+ CompassoProtractor
- Transferidor
+ TransferidorTriangle
- Esquadro
+ EsquadroMagnifier
- Lupa
+ LupaCache
- Cache
+ Cache
+
+
+ Axes
+ EixosUBTrapFlashControllerWhole page
- Página completa
+ Página completaWeb
- Web
+ WebUBUpdateDlgDocument updater
- Atualizador de documento
+ Atualizador de documento files require an update.
- arquivos requerem uma atualização.
+ arquivos requerem uma atualização.Backup path:
- Localização da Cópia de Segurança:
+ Localização da Cópia de Segurança:Browse
- Procurar
+ ProcurarUpdate
- Atualizar
+ Atualizar
+
+
+ Remind me later
+ Lembrar-me depoisSelect a backup folder
- Selecione uma pasta para a Cópia de Segurança
+ Selecione uma pasta para cópia de segurançaPlease wait the import process will start soon...
- Aguarde. O processo de importação vai começar em breve...
+ Aguarde. O processo de importação iniciará em breve...Files update successful!
Please reboot the application to access the updated documents.
- Atualização de arquivos bem sucedida!
+ Atualização de arquivos bem sucedida!
Por favor, reinicie o aplicativo para ir aos documentos atualizados.An error occured during the update. The files have not been affected.
- Ocorreu um erro durante a atualização. Os arquivos não foram afetados.
+ Ocorreu um erro durante a atualização. Os arquivos não foram afetados.Files update results
- Resultados da atualização de arquivos
+ Resultados da atualização de arquivosUpdating file
- Atualizando o arquivo
-
-
- Remind me later
- Lembrar-me depois
+ Atualizando o arquivo UBWebPluginWidgetLoading...
- Carregando...
+ Carregando...UBWidgetUniboardAPI%0 called (method=%1, status=%2)
- %0 pedido (método=%1, estado=%2)
+ %0 pedido (método=%1, estado=%2)UBYouTubePublisherYouTube authentication failed.
- Erro de autenticação no YouTube.
+ Erro de autenticação no YouTube.Error while uploading video to YouTube (%1)
- Erro no envio do vídeo para o YouTube (%1)
+ Erro ao enviar o vídeo para o YouTube (%1)Upload to YouTube in progress %1 %
- Envio para o YouTube em curso %1 %
+ Envio para o YouTube em curso %1 %UBYouTubePublishingDialogUpload
- Enviar
+ EnviarAutos & Vehicles
- Automóveis
+ VeículosMusic
- Música
+ MúsicaPets & Animals
- Animais
+ AnimaisSports
- Esportes
+ EsportesTravel & Events
- Viagens e Eventos
+ Viagens & EventosGaming
- Jogos
+ JogosComedy
- Humor
+ ComédiaPeople & Blogs
- Pessoas e Blogues
+ Pessoas & BloguesNews & Politics
- Notícias e Política
+ Notícias & PolíticaEntertainment
- Entretenimento
+ EntretenimentoEducation
- Educação
+ EducaçãoHowto & Style
- Guias e Estilo
+ Tutoriais & EstiloNonprofits & Activism
- Sem fins lucrativos e Ativismo
+ ONGs & AtivismoScience & Technology
- Ciência e Tecnologia
+ Ciência & TecnologiaUBZoomPalette%1 x
- %1 x
+ %1 xWBClearButtonClear
- Limpar
+ LimparWBDownloadItemSave File
- Gravar arquivo
+ Gravar arquivoDownload canceled: %1
- Download cancelado: %1
+ Transferência cancelada: %1Error opening saved file: %1
- Erro a abrir o arquivo gravado: %1
+ Erro ao abrir o arquivo gravado: %1Error saving: %1
- Erro ao gravar: %1
+ Erro ao gravar: %1Network Error: %1
- Erro na Ligação: %1
+ Erro na Ligação: %1seconds
- Segundos
+ segundosminutes
- Minutos
+ minutos- %4 %5 remaining
- - %4 %5 de tempo restante
+ - %4 %5 de tempo restante%1 of %2 (%3/sec) %4
- %1 de %2 (%3/seg) %4
+ %1 de %2 (%3/s) %4?unknown file sizeTamanho do arquivo desconhecido
- ?
+ ?%1 of %2 - Stopped
- %1 de %2 - Parado
+ %1 de %2 - Paradobytes
- bytes
+ bytesKB
- KB
+ KBMB
- MB
+ MBWBDownloadManager1 Download
- 1 arquivo baixado
+ 1 arquivo transferido%1 Downloadsalways >= 2
- Sempre >= 2
- %1 arquivos baixados
+ %1 arquivos transferidosWBHistoryModelTitle
- Título
+ TítuloAddress
- Endereço
+ EndereçoWBHistoryTreeModelEarlier Today
- Hoje
+ Hoje%1 items
- %1 item(s)
+ %1 itensWBSearchLineEditSearch
- Pesquisar
+ PesquisarWBTabBarNew &Tab
- Novo &Separador
+ Novo &SeparadorClone Tab
- Duplicar Separador
+ Duplicar Separador&Close Tab
- &Fechar Separador
+ &Fechar SeparadorClose &Other Tabs
- Fechar os &Outros Separadores
+ Fechar os &Outros SeparadoresReload Tab
- Atualizar Separador
+ Atualizar SeparadorReload All Tabs
- Atualizar todos os Separadores
+ Atualizar todos os SeparadoresWBTabWidgetRecently Closed Tabs
- Separadores recentemente fechados
+ Separadores recentemente fechados(Untitled)
- (Sem Título)
+ (Sem Título)WBToolbarSearchSearch
- Pesquisar
+ PesquisarNo Recent Searches
- Sem pesquisas recentes
+ Sem pesquisas recentesRecent Searches
- Pesquisas recentes
+ Pesquisas recentesClear Recent Searches
- Limpar as pesquisas recentes
+ Limpar as pesquisas recentesWBWebPage
+
+ Download PDF Document: would you prefer to download the PDF file or add it to the current OpenBoard document?
+ Download de Documento PDF: você prefere transferir o arquivo PDF ou adicioná-lo ao documento OpenBoard atual?
+ Download
- Baixar
+ TransferirAdd to Current Document
- Adicionar ao documento atual
+ Adicionar ao documento atualPDF
- PDF
+ PDFError loading page: %1
- Erro ao carregar a página: %1
-
-
- Download PDF Document: would you prefer to download the PDF file or add it to the current OpenBoard document?
- Download de Documento PDF: você prefere baixar o arquivo PDF ou adicioná-lo ao atual documento OpenBoard?
+ Erro ao carregar a página: %1WBWebViewOpen in New Tab
- Abrir num Novo Separador
+ Abrir num Novo Separador
+
+
+
+ XPDFRenderer
+
+ Processing...
+ Processando...YouTubePublishingDialogPublish Podcast to YouTube
- Publicar Podcast no Youtube
+ Publicar Podcast no YouTubeTitle
- Título
+ TítuloDescription
- Descrição
+ DescriçãoKeywords
- Palavras chave
+ Tags (Palavras-Chave)
+
+
+ OpenBoard
+ OpenBoardCategory
- Categoria
+ CategoriaYouTube Username
- Nome de utilizador do Youtube
+ Nome de Usuário YoutubeYouTube Password
- Senha do Youtube
+ Senha no Youtube<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
@@ -2362,264 +2607,362 @@ Por favor, reinicie o aplicativo para ir aos documentos atualizados.
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
p, li { white-space: pre-wrap; }
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Lucida Grande'; font-size:10pt;">Clicando em 'Enviar', você certifica que possui todos os direitos sobre o conteúdo ou que está autorizado pelo proprietário a tornar o conteúdo disponível publicamente no YouTube, e que esta de acordo com os Termos de Serviço do YouTube localizado em</span><a href="http://www.youtube.com/t/terms"><span style=" font-family:'Lucida Grande'; font-size:10pt; text-decoration: underline; color:#0000ff;">http://www.youtube.com/t/terms</span></a></p></body></html>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Lucida Grande'; font-size:10pt;">Clicando em 'Enviar', você certifica que possui todos os direitos sobre o conteúdo ou que está autorizado pelo proprietário a tornar o conteúdo disponível publicamente no YouTube, e que està de acordo com os Termos de Serviço do YouTube localizado em </span><a href="http://www.youtube.com/t/terms"><span style=" font-family:'Lucida Grande'; font-size:10pt; text-decoration: underline; color:#0000ff;">http://www.youtube.com/t/terms</span></a></p></body></html>Restore credentials on reboot
- Reestabelecer credenciais ao reiniciar
-
-
- OpenBoard
- OpenBoard
+ Reestabelecer credenciais ao reiniciarbrushProperties
- On Light Background
- Num fundo branco
+ Pen is Pressure Sensitive
+ Caneta sensível à pressão
- On Dark Background
- Num fundo preto
+ Opacity
+ Opacidade
- Opacity
- Opacidade
+ On Light Background
+ Em fundo claro
+
+
+ On Dark Background
+ Em fundo escuroLine Width
- Largura da linha
+ Largura da PontaMedium
- Médio
+ MédiaStrong
- Largo
+ GrossaFine
- Fino
+ Fina
- Pen is Pressure Sensitive
- Caneta sensível à pressão
+ Show preview circle from
+ Ver cruz a partir de
+
+
+ px
+ pxcapturePublishingDialogDialog
- Caixa de Diálogo
+ Caixa de DiálogoTitle
- Título
+ TítuloE-mail
- E-mail
+ E-mailAuthor
- Autor
+ AutorDescription
- Descrição
+ DescriçãodocumentsOpenBoard Documents
- Documentos OpenBoard
+ Documentos OpenBoard
+
+
+ Creation date
+ Data de criação
+
+
+ Update date
+ Data de modificação
+
+
+ Alphabetical order
+ Ordem alfabética
+
+
+ Sort Order
+ Inverter OrdempreferencesDialogPreferences
- Preferências
-
-
- version : …
- versão : ...
+ PreferênciasDefault Settings
- Configuração por defeito
+ Configurações PadrãoClose
- Fechar
+ FecharDisplay
- Exibir
+ Exibir
- Internet
- Internet
-
-
- Show Page with External Browser
- Mostrar a página num Browser externo
+ Multi display
+ Telas múltiplas
- Home Page:
- Página de entrada:
+ Swap control display and view display
+ Alternar entre telas de controle e de apresentação
- Virtual Keyboard
- Teclado virtual
+ Show internal web page content on secondary screen or projector
+ Mostrar o conteúdo interno da página web numa tela ou projetor secundário
- Keyboard button size:
- Tamanho dos botões do teclado:
+ Swap first and second view displays
+ Trocar as telasToolbar
- Barra de ferramentas
+ Barra de ferramentasPositioned at the Top (recommended for tablets)
- Posicionado no topo (recomendado para tablets)
+ Posicionado no topo (recomendado para tablets ou mesas digitalizadoras)Positioned at the Bottom (recommended for white boards)
- Posicionado em baixo (recomendado para quadros brancos)
+ Posicionado em baixo (recomendado para quadros brancos)Display Text Under Button
- Mostrar o texto por debaixo dos botões
+ Mostrar legenda abaixo dos botõesStylus Palette
- Paleta
+ PaletaHorizontal
- Horizontal
+ HorizontalVertical
- Vertical
+ Vertical
+
+
+ Mode
+ Modo
+
+
+ Mode to start in:
+ Iniciar como
+
+
+ Board
+ Quadro
+
+
+ Desktop
+ Área de Trabalho
+
+
+ Virtual Keyboard
+ Teclado Virtual
+
+
+ Built-in virtual keyboard button size:
+ Tamanho das teclas do teclado virtual embarcado:
+
+
+ Use system keyboard (recommended)
+ Usar teclado do sistema (recomendado)
+
+
+ Grid
+ Grade
+
+
+ On Light Background
+ Em fundo claro
+
+
+ Opacity
+ Opacidade
+
+
+ On Dark Background
+ Em fundo escuroPen
- Caneta
+ CanetaMarker
- Marcador
+ Marca-Texto
+
+
+ Network
+ Rede
+
+
+ Internet
+ Internet
+
+
+ Show Page with External Browser
+ Mostrar a página em navegador externo
+
+
+ Home Page:
+ Página Inicial:
+
+
+ Proxy User:
+ Usuário Proxy:
+
+
+ Pass:
+ Senha:Licences
- Licenças
+ Licenças
+
+
+ Credits
+ CréditosAbout
- Sobre
+ SobreSoftware Update
- Atualização de Software
+ Atualização de SoftwareCheck software update at launch
- Verificar atualizações de software no arranque
+ Verificar atualizações ao iniciar
- Network
- Rede
+ Open-Sankoré Importer
+ Importador Open-Sankoré
- Multi display
- Múltiplos Monitores
+ Check if Open-Sankoré data could be imported at launch
+ Verificar se os dados do Open-Sankoré poderão ser importados ao inicializar
- Show internal web page content on secondary screen or projector
- Mostrar o conteúdo interno da página web num monitor ou projetor secundário
+ version : …
+ versão : …
- Swap control display and view display
- Trocar entre o monitor de controle e apresentação?
- Trocar entre o monitor de controle e visualização
+ Documents Mode
+ Modo dos Documentos
- Mode
- Modo
+ Display date column on alphabetical sort
+ Mostrar coluna de data em ordem alfabética
- Mode to start in:
- "Mode to start in:"
- Modo iniciar:
+ Empty trash for documents older than
+ Esvaziar lixeira para documentos com mais de
- Board
- Quadro
+ days
+ dias
- Desktop
- Área de Trabalho
+ PDF Rendering
+ Renderização de PDF
- Proxy User:
- Proxy User:
+ Shortcut
+ Atalho
- Pass:
- Senha:
+ Filter
+ Filtro
- Credits
- Créditos
+ Active keyboard shortcuts without pressing Ctrl key
+ Ativar atalhos de teclado sem pressionar a tecla Ctrl
- Open-Sankoré Importer
- Importador Open-Sankoré
+ Shortcuts
+ Atalhos
- Check if Open-Sankoré data could be imported at launch
- Verifique se os dados do Open-Sankoré poderão ser importados na inicialização
+ Abort
+ Abortar
- Use system keyboard (recommended)
- Usar teclado do sistema (recomendado)
+ Record
+ Gravar
- Built-in virtual keyboard button size:
- Tamanho da tecla do teclado virtual embarcado:
+ Stylus Button
+ Botão da Caneta
+
+
+ Mouse Button
+ Botão do Mouse
+
+
+ Reset
+ Reiniciar
+
+
+ Key Sequence
+ Sequência de Teclas
+
+
+ Improve zoom execution time (can slightly affect rendering quality)
+ Melhorar o tempo de execução do zoom (pode afetar ligeiramente a qualidade da renderização)trapFlashDialogTrap flash
- Capturar flash
+ Capturar flashSelect a flash to trap
- Selecionar o flash a capturar
+ Selecionar o flash a capturarabout:blank
- Acerca:em branco
+ Sobre:em brancoApplication name
- Nome da Aplicação
+ Nome da AplicaçãoCreate Application
- Criar Aplicação
+ Criar Aplicação
diff --git a/resources/i18n/OpenBoard_ro.ts b/resources/i18n/OpenBoard_ro.ts
index fc63c391..0863a9fc 100644
--- a/resources/i18n/OpenBoard_ro.ts
+++ b/resources/i18n/OpenBoard_ro.ts
@@ -697,11 +697,11 @@
Flash Trap
- Blocare flash
+ Blocare flashTrap Flash Content
- Blocare conţinut flash
+ Blocare conţinut flashWeb Trap
@@ -839,6 +839,10 @@
Draw intermediate grid lines
+
+ Capture Web Content
+
+ PasswordDialog
@@ -896,6 +900,14 @@
Are you sure you want to remove 1 page from the selected document '%0'?Sunteți sigur că doriți să eliminați 1 pagină din documentul selectat '%0'?
+
+ Loading scene (%1/%2)
+
+
+
+ Moving cached scenes (%1/%2)
+
+ UBApplication
@@ -907,6 +919,10 @@
PodcastPodcast
+
+ Cannot open your UBX file directly. Please import it in Documents mode instead
+
+ UBApplicationController
@@ -1226,6 +1242,10 @@
Title page
+
+ Refreshing Document Thumbnails View (%1/%2)
+
+ UBDocumentManager
@@ -1276,6 +1296,10 @@
Page %0Pagina %0
+
+ Generating thumbnails for board (%1/%2)
+
+ UBDocumentPublisher
@@ -1970,6 +1994,10 @@ Doriţi să ignoraţi aceste erori pentru acest host?
OpenBoard 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.
+
+ Renaming pages (%1/%2)
+
+ UBPlatformUtils
@@ -2133,6 +2161,10 @@ Doriţi să ignoraţi aceste erori pentru acest host?
%1 thumbnails generated ...%1 miniaturi generate ...
+
+ Loading thumbnail (%1/%2)
+
+ UBThumbnailTextItem
@@ -2911,7 +2943,7 @@ p, li { white-space: pre-wrap; }
Select a flash to trap
- Selectaţi un flash pentru blocare
+ Selectaţi un flash pentru blocareabout:blank
@@ -2925,5 +2957,9 @@ p, li { white-space: pre-wrap; }
Create ApplicationCreare aplicaţie
+
+ Select a content to capture
+
+
diff --git a/resources/i18n/OpenBoard_ru.ts b/resources/i18n/OpenBoard_ru.ts
index ece64aea..fade77ea 100644
--- a/resources/i18n/OpenBoard_ru.ts
+++ b/resources/i18n/OpenBoard_ru.ts
@@ -697,11 +697,11 @@
Flash Trap
- Захват флэш
+ Захват флэшTrap Flash Content
- Захват флэш-содержимого
+ Захват флэш-содержимогоWeb Trap
@@ -839,6 +839,10 @@
Draw intermediate grid lines
+
+ Capture Web Content
+
+ PasswordDialog
@@ -896,6 +900,14 @@
Are you sure you want to remove 1 page from the selected document '%0'?Вы уверены, что хотите удалить 1 страницу из документа '%0'?
+
+ Loading scene (%1/%2)
+
+
+
+ Moving cached scenes (%1/%2)
+
+ UBApplication
@@ -907,6 +919,10 @@
PodcastПодкаст
+
+ Cannot open your UBX file directly. Please import it in Documents mode instead
+
+ UBApplicationController
@@ -1226,6 +1242,10 @@
Title pageЗаглавная страница
+
+ Refreshing Document Thumbnails View (%1/%2)
+
+ UBDocumentManager
@@ -1276,6 +1296,10 @@
Page %0Страница %0
+
+ Generating thumbnails for board (%1/%2)
+
+ UBDocumentPublisher
@@ -1972,6 +1996,10 @@ Do you want to ignore these errors for this host?
OpenBoard 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.Потерян доступ к репозиторию документов «%1». Приложение должно быть закрыто, чтобы избежать повреждения данных. Последние изменения также могут быть утеряны.
+
+ Renaming pages (%1/%2)
+
+ UBPlatformUtils
@@ -2135,6 +2163,10 @@ Do you want to ignore these errors for this host?
%1 thumbnails generated ...сгенерированы эскизы %1...
+
+ Loading thumbnail (%1/%2)
+
+ UBThumbnailTextItem
@@ -2913,7 +2945,7 @@ p, li { white-space: pre-wrap; }
Select a flash to trap
- Выбрать флеш-содержимое для захвата
+ Выбрать флеш-содержимое для захватаabout:blank
@@ -2927,5 +2959,9 @@ p, li { white-space: pre-wrap; }
Create ApplicationСоздать приложение
+
+ Select a content to capture
+
+
diff --git a/resources/i18n/OpenBoard_sk.ts b/resources/i18n/OpenBoard_sk.ts
index c2abbc34..fa627759 100644
--- a/resources/i18n/OpenBoard_sk.ts
+++ b/resources/i18n/OpenBoard_sk.ts
@@ -351,7 +351,7 @@
Trap Flash Content
- Označiť obsah vo Flashi
+ Označiť obsah vo FlashiImport
@@ -539,7 +539,7 @@
Flash Trap
- Označiť Flash
+ Označiť FlashWindow Capture
@@ -843,6 +843,10 @@
Draw intermediate grid lines
+
+ Capture Web Content
+
+ PasswordDialog
@@ -900,6 +904,14 @@
Are you sure you want to remove 1 page from the selected document '%0'?Určite chcete odstrániť 1 stránku z vybraného dokumentu '%0'?
+
+ Loading scene (%1/%2)
+
+
+
+ Moving cached scenes (%1/%2)
+
+ UBApplication
@@ -911,6 +923,10 @@
Page SizeVeľkosť stránky
+
+ Cannot open your UBX file directly. Please import it in Documents mode instead
+
+ UBApplicationController
@@ -1240,6 +1256,10 @@
Title page
+
+ Refreshing Document Thumbnails View (%1/%2)
+
+ UBDocumentManager
@@ -1290,6 +1310,10 @@
Page %0Stránka %0
+
+ Generating thumbnails for board (%1/%2)
+
+ UBDocumentReplaceDialog
@@ -2008,6 +2032,10 @@ Chcete ignorovať tieto chyby na tomto serveri?
OpenBoard 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.
+
+ Renaming pages (%1/%2)
+
+ UBPlatformUtils
@@ -2173,6 +2201,10 @@ Chcete ignorovať tieto chyby na tomto serveri?
Generating preview thumbnails ...Vytvárajú sa ukážky miniatúr...
+
+ Loading thumbnail (%1/%2)
+
+ UBThumbnailTextItem
@@ -2952,7 +2984,7 @@ p, li { white-space: pre-wrap; }
Select a flash to trap
- Vyberte flash, ktorý chcete označiť
+ Vyberte flash, ktorý chcete označiťabout:blank
@@ -2966,5 +2998,9 @@ p, li { white-space: pre-wrap; }
Create ApplicationVytvoriť aplikáciu
+
+ Select a content to capture
+
+
diff --git a/resources/i18n/OpenBoard_sv.ts b/resources/i18n/OpenBoard_sv.ts
index eed47fcb..f00c99ff 100644
--- a/resources/i18n/OpenBoard_sv.ts
+++ b/resources/i18n/OpenBoard_sv.ts
@@ -697,11 +697,11 @@
Flash Trap
- Lagra flash
+ Lagra flashTrap Flash Content
- Lagra flash innehål
+ Lagra flash innehålWeb Trap
@@ -839,6 +839,10 @@
Draw intermediate grid lines
+
+ Capture Web Content
+
+ PasswordDialog
@@ -896,6 +900,14 @@
Are you sure you want to remove 1 page from the selected document '%0'?Är du säker på att du vill ta bort 1 sida från det valda dokumentet '%0'?
+
+ Loading scene (%1/%2)
+
+
+
+ Moving cached scenes (%1/%2)
+
+ UBApplication
@@ -907,6 +919,10 @@
PodcastPodcast
+
+ Cannot open your UBX file directly. Please import it in Documents mode instead
+
+ UBApplicationController
@@ -1227,6 +1243,10 @@
Title page
+
+ Refreshing Document Thumbnails View (%1/%2)
+
+ UBDocumentManager
@@ -1277,6 +1297,10 @@
Page %0Sida %0
+
+ Generating thumbnails for board (%1/%2)
+
+ UBDocumentPublisher
@@ -1971,6 +1995,10 @@ Vill du ignorera felen för den här värden?
OpenBoard 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.
+
+ Renaming pages (%1/%2)
+
+ UBPlatformUtils
@@ -2134,6 +2162,10 @@ Vill du ignorera felen för den här värden?
%1 thumbnails generated ...%1 miniatybil genererad ...
+
+ Loading thumbnail (%1/%2)
+
+ UBThumbnailTextItem
@@ -2912,7 +2944,7 @@ p, li { white-space: pre-wrap; }
Select a flash to trap
- Välj en flash att lagra
+ Välj en flash att lagraabout:blank
@@ -2926,5 +2958,9 @@ p, li { white-space: pre-wrap; }
Create ApplicationSkapa applikation
+
+ Select a content to capture
+
+
diff --git a/resources/i18n/OpenBoard_tr.ts b/resources/i18n/OpenBoard_tr.ts
index efe8bbfb..d5ed2c55 100644
--- a/resources/i18n/OpenBoard_tr.ts
+++ b/resources/i18n/OpenBoard_tr.ts
@@ -701,11 +701,11 @@
Flash Trap
- Flash Tuzağı
+ Flash TuzağıTrap Flash Content
- Flash İçeriğini Yakala
+ Flash İçeriğini YakalaWeb Trap
@@ -839,6 +839,10 @@
Draw intermediate grid lines
+
+ Capture Web Content
+
+ PasswordDialog
@@ -896,6 +900,14 @@
Are you sure you want to remove 1 page from the selected document '%0'?Seçili olan '%0' adlı dökümandan 1 sayfayı kaldırmak üzeresiniz. Bu işlemi yapmak istediğinizden eminmisiniz?
+
+ Loading scene (%1/%2)
+
+
+
+ Moving cached scenes (%1/%2)
+
+ UBApplication
@@ -907,6 +919,10 @@
PodcastEkran Kaydı
+
+ Cannot open your UBX file directly. Please import it in Documents mode instead
+
+ UBApplicationController
@@ -1224,6 +1240,10 @@
Title page
+
+ Refreshing Document Thumbnails View (%1/%2)
+
+ UBDocumentManager
@@ -1274,6 +1294,10 @@
Page %0Sayfa %0
+
+ Generating thumbnails for board (%1/%2)
+
+ UBDocumentReplaceDialog
@@ -1958,6 +1982,10 @@ Bu host için yukarıdaki hatalar yok sayılsın mı?
OpenBoard 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.
+
+ Renaming pages (%1/%2)
+
+ UBPlatformUtils
@@ -2121,6 +2149,10 @@ Bu host için yukarıdaki hatalar yok sayılsın mı?
%1 thumbnails generated ...%1 adet önizleme resmi oluşturuldu ...
+
+ Loading thumbnail (%1/%2)
+
+ UBThumbnailTextItem
@@ -2899,7 +2931,7 @@ p, li { white-space: pre-wrap; }
Select a flash to trap
- Tuzağa almak için bir flash öğesi seçin
+ Tuzağa almak için bir flash öğesi seçinabout:blank
@@ -2913,5 +2945,9 @@ p, li { white-space: pre-wrap; }
Create ApplicationUygulama Oluştur
+
+ Select a content to capture
+
+
diff --git a/resources/i18n/OpenBoard_uk.ts b/resources/i18n/OpenBoard_uk.ts
index 8a9513e8..e39b6101 100644
--- a/resources/i18n/OpenBoard_uk.ts
+++ b/resources/i18n/OpenBoard_uk.ts
@@ -697,11 +697,11 @@
Flash Trap
- Захоплення флеш
+ Захоплення флешTrap Flash Content
- Захоплення флеш-вмісту
+ Захоплення флеш-вмістуWeb Trap
@@ -839,6 +839,10 @@
Draw intermediate grid lines
+
+ Capture Web Content
+
+ PasswordDialog
@@ -896,6 +900,14 @@
Are you sure you want to remove 1 page from the selected document '%0'?Ви впевнені, що хочете видалити 1 сторінку з документа '%0'?
+
+ Loading scene (%1/%2)
+
+
+
+ Moving cached scenes (%1/%2)
+
+ UBApplication
@@ -907,6 +919,10 @@
PodcastПодкаст
+
+ Cannot open your UBX file directly. Please import it in Documents mode instead
+
+ UBApplicationController
@@ -1234,6 +1250,10 @@
Title page
+
+ Refreshing Document Thumbnails View (%1/%2)
+
+ UBDocumentManager
@@ -1284,6 +1304,10 @@
Page %0Сторінка %0
+
+ Generating thumbnails for board (%1/%2)
+
+ UBDocumentReplaceDialog
@@ -1979,6 +2003,10 @@ Do you want to ignore these errors for this host?
OpenBoard 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.
+
+ Renaming pages (%1/%2)
+
+ UBPlatformUtils
@@ -2142,6 +2170,10 @@ Do you want to ignore these errors for this host?
%1 thumbnails generated ...згенеровані ескізи %1...
+
+ Loading thumbnail (%1/%2)
+
+ UBThumbnailTextItem
@@ -2897,7 +2929,7 @@ p, li { white-space: pre-wrap; }
Select a flash to trap
- Вибрати флеш-вміст для захоплення
+ Вибрати флеш-вміст для захопленняabout:blank
@@ -2911,5 +2943,9 @@ p, li { white-space: pre-wrap; }
Create ApplicationСтворити програму
+
+ Select a content to capture
+
+
diff --git a/resources/i18n/OpenBoard_zh.ts b/resources/i18n/OpenBoard_zh.ts
index 2621530a..453b04db 100644
--- a/resources/i18n/OpenBoard_zh.ts
+++ b/resources/i18n/OpenBoard_zh.ts
@@ -697,11 +697,11 @@
Flash Trap
- 截取动画
+ 截取动画Trap Flash Content
- 截取动画内容
+ 截取动画内容Web Trap
@@ -839,6 +839,10 @@
Draw intermediate grid lines
+
+ Capture Web Content
+
+ PasswordDialog
@@ -896,6 +900,14 @@
Are you sure you want to remove 1 page from the selected document '%0'?确定要删除选中文件“%0”中的1页?
+
+ Loading scene (%1/%2)
+
+
+
+ Moving cached scenes (%1/%2)
+
+ UBApplication
@@ -907,6 +919,10 @@
Podcast播客
+
+ Cannot open your UBX file directly. Please import it in Documents mode instead
+
+ UBApplicationController
@@ -1224,6 +1240,10 @@
Title page
+
+ Refreshing Document Thumbnails View (%1/%2)
+
+ UBDocumentManager
@@ -1274,6 +1294,10 @@
Page %0页面 %0
+
+ Generating thumbnails for board (%1/%2)
+
+ UBDocumentReplaceDialog
@@ -1958,6 +1982,10 @@ Do you want to ignore these errors for this host?
OpenBoard 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.
+
+ Renaming pages (%1/%2)
+
+ UBPlatformUtils
@@ -2121,6 +2149,10 @@ Do you want to ignore these errors for this host?
%1 thumbnails generated ...已为%1生成缩略图……
+
+ Loading thumbnail (%1/%2)
+
+ UBThumbnailTextItem
@@ -2899,7 +2931,7 @@ p, li { white-space: pre-wrap; }
Select a flash to trap
- 选择要截取的动画
+ 选择要截取的动画about:blank
@@ -2913,5 +2945,9 @@ p, li { white-space: pre-wrap; }
Create Application创建应用程序
+
+ Select a content to capture
+
+
diff --git a/resources/i18n/OpenBoard_zh_CN.ts b/resources/i18n/OpenBoard_zh_CN.ts
index 2621530a..453b04db 100644
--- a/resources/i18n/OpenBoard_zh_CN.ts
+++ b/resources/i18n/OpenBoard_zh_CN.ts
@@ -697,11 +697,11 @@
Flash Trap
- 截取动画
+ 截取动画Trap Flash Content
- 截取动画内容
+ 截取动画内容Web Trap
@@ -839,6 +839,10 @@
Draw intermediate grid lines
+
+ Capture Web Content
+
+ PasswordDialog
@@ -896,6 +900,14 @@
Are you sure you want to remove 1 page from the selected document '%0'?确定要删除选中文件“%0”中的1页?
+
+ Loading scene (%1/%2)
+
+
+
+ Moving cached scenes (%1/%2)
+
+ UBApplication
@@ -907,6 +919,10 @@
Podcast播客
+
+ Cannot open your UBX file directly. Please import it in Documents mode instead
+
+ UBApplicationController
@@ -1224,6 +1240,10 @@
Title page
+
+ Refreshing Document Thumbnails View (%1/%2)
+
+ UBDocumentManager
@@ -1274,6 +1294,10 @@
Page %0页面 %0
+
+ Generating thumbnails for board (%1/%2)
+
+ UBDocumentReplaceDialog
@@ -1958,6 +1982,10 @@ Do you want to ignore these errors for this host?
OpenBoard 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.
+
+ Renaming pages (%1/%2)
+
+ UBPlatformUtils
@@ -2121,6 +2149,10 @@ Do you want to ignore these errors for this host?
%1 thumbnails generated ...已为%1生成缩略图……
+
+ Loading thumbnail (%1/%2)
+
+ UBThumbnailTextItem
@@ -2899,7 +2931,7 @@ p, li { white-space: pre-wrap; }
Select a flash to trap
- 选择要截取的动画
+ 选择要截取的动画about:blank
@@ -2913,5 +2945,9 @@ p, li { white-space: pre-wrap; }
Create Application创建应用程序
+
+ Select a content to capture
+
+
diff --git a/resources/i18n/OpenBoard_zh_TW.ts b/resources/i18n/OpenBoard_zh_TW.ts
index 859aece4..336adbca 100644
--- a/resources/i18n/OpenBoard_zh_TW.ts
+++ b/resources/i18n/OpenBoard_zh_TW.ts
@@ -50,7 +50,7 @@
IntranetPodcastPublishingDialogPublish Podcast to YouTube
- 發佈Podcast至YouTube
+ 發佈 Podcast 至 YouTubeTitle
@@ -333,7 +333,7 @@
Pen
- 電子筆
+ 筆Annotate Document
@@ -365,7 +365,7 @@
Selector
- 選擇器
+ 選擇工具Select And Modify Objects
@@ -413,7 +413,7 @@
Import eduMedia simulation
- 匯入eduMedia模擬程序
+ 匯入 eduMedia 模擬程序Check Update
@@ -673,19 +673,19 @@
Podcast Config
- Podcast設定
+ Podcast 設定Configure Podcast Recording
- Podcast錄製設定
+ Podcast 錄製設定Flash Trap
- Flash動畫擷取
+ Flash 動畫擷取Trap Flash Content
- 擷取Flash動畫內容
+ 擷取 Flash 動畫內容Web Trap
@@ -745,11 +745,11 @@
Wide Size (16/9)
- 寬螢幕顯示(16/9)
+ 寬螢幕顯示 (16/9)Regular Size (4/3)
- 一般螢幕顯示(4/3)
+ 一般螢幕顯示 (4/3)Custom Size
@@ -765,15 +765,15 @@
Quit OpenBoard
- 退出OpenBoard
+ 退出 OpenBoardHide OpenBoard
- 隱藏OpenBoard
+ 隱藏 OpenBoardHide OpenBoard Application
- 隱藏OpenBoard應用程式
+ 隱藏 OpenBoard 應用程式Play
@@ -801,44 +801,48 @@
Open Tutorial
-
+ 開啟新手教學Open the tutorial web page
-
+ 打開教學網頁Reset grid size
-
+ 重設網格大小Small Eraser
-
+ 小橡皮擦Color 1
-
+ 顏色 1Color 2
-
+ 顏色 2Color 3
-
+ 顏色 3Color 4
-
+ 顏色 4Color 5
-
+ 顏色 5Draw intermediate grid lines
+
+ Capture Web Content
+
+ PasswordDialog
@@ -848,30 +852,30 @@
Username:
- 帳號:
+ 帳號:Password:
- 密碼:
+ 密碼:ProxyDialogProxy Authentication
- Proxy驗證
+ Proxy 驗證Connect to Proxy
- 連接至Proxy
+ 連接至 ProxyUsername:
- 帳號:
+ 帳號:Password:
- 密碼:
+ 密碼:Save username and password for future use
@@ -894,7 +898,15 @@
Are you sure you want to remove 1 page from the selected document '%0'?
- 確定要移除所選文件 '%0' 的一個頁面 ?
+ 確定要移除所選文件 '%0' 的一個頁面?
+
+
+ Loading scene (%1/%2)
+
+
+
+ Moving cached scenes (%1/%2)
+
@@ -907,6 +919,10 @@
PodcastPodcast
+
+ Cannot open your UBX file directly. Please import it in Documents mode instead
+
+ UBApplicationController
@@ -916,7 +932,7 @@
New update available, would you go to the web page ?
- 可更新,要上網頁嗎?
+ 有可用更新,要前往網頁下載嗎?No update available
@@ -924,7 +940,7 @@
Update available
- 目前可更新
+ 有可用更新Update
@@ -935,7 +951,7 @@
UBBackgroundPaletteGrid size
-
+ 網格大小Draw intermediate grid lines
@@ -954,7 +970,7 @@
Unknown tool type %1
- 陌生工具型態 %1
+ 未知工具類型 %1Add Item
@@ -962,11 +978,11 @@
All Supported (%1)
- 全部已支援(%1)
+ 全部已支援 (%1)Unknown content type %1
- 陌生內容型態 %1
+ 未知內容類型 %1Delete page %1 from document
@@ -978,7 +994,7 @@
Add file operation failed: file copying error
- 新增檔案失敗:檔案複製有錯誤
+ 新增檔案失敗:檔案複製錯誤Group
@@ -990,26 +1006,26 @@
Saving document...
-
+ 正在儲存檔案...Document has just been saved...
-
+ 檔案已被儲存...Deleting page %1
-
+ 正在刪除第 %1 頁Color
- 顏色
+ 顏色UBBoardPaletteManagerError Adding Image to Library
- 錯誤新增圖像至圖書館
+ 新增圖像至圖書館時發生錯誤CapturedImage
@@ -1020,26 +1036,26 @@
UBBoardThumbnailsViewLoading page (%1/%2)
-
+ 正在載入第 %1 頁,共 %2 頁UBCachePropertiesWidgetCache Properties
- Cache屬性
+ Cache 屬性Color:
- 顏色:
+ 顏色:Shape:
- 形狀:
+ 形狀:Size:
- 大小:
+ 大小:Close
@@ -1070,7 +1086,7 @@
Show OpenBoard
-
+ 顯示 OpenBoard
@@ -1085,7 +1101,7 @@
Add Folder of Images
- 新增圖像檔案夾
+ 新增圖像資料夾Add Images
@@ -1210,18 +1226,22 @@
Remove Item
-
+ 刪除項目Are you sure you want to remove the selected item(s) ?
-
+ 您確定要刪除所選項目嗎?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?
-
+ 檔案 '%1' 是由新版的 OpenBoard (%2) 建立的。開啟後可能會遺失資料。您確定要繼續嗎?Title page
+ 標題頁
+
+
+ Refreshing Document Thumbnails View (%1/%2)
@@ -1274,6 +1294,10 @@
Page %0第 %0 頁
+
+ Generating thumbnails for board (%1/%2)
+
+ UBDocumentPublisher
@@ -1286,15 +1310,15 @@
UBDocumentReplaceDialogAccept
- 接受
+ 接受Cancel
- 取消
+ 取消Replace
-
+ 取代The name %1 is allready used.
@@ -1307,38 +1331,38 @@ Providing a new name will create a new document.UBDocumentTreeModelTrash
- 回收桶
+ 回收桶%1 pages copied
-
+ 已複製 %1 個頁面My documents
-
+ 我的檔案UBDocumentTreeView%1 pages copied
-
+ 已複製 %1 個頁面Remove Item
-
+ 刪除項目Are you sure you want to remove the selected item(s) ?
-
+ 您確定要刪除所選項目嗎?Copying page %1/%2
- 頁面 %1/%2 複製中
+ 頁面 %1/%2 複製中
@@ -1391,38 +1415,38 @@ Providing a new name will create a new document.
Exporting document...
-
+ 匯出檔案中...Export failed
-
+ 匯出失敗Unable to export to the selected location. You do not have the permissions necessary to save the file.
-
+ 無法匯出至指定位置。您沒有儲存檔案的權限。Export failed: location not writable
-
+ 匯出失敗:路徑無法被寫入Export successful.
-
+ 匯出成功。UBExportCFFExport to IWB
- 匯出至IWB
+ 匯出至 IWBExport as IWB File
- 以IWB格式匯出
+ 以 IWB 格式匯出Exporting document...
- 匯出文件...
+ 匯出檔案中...Export successful.
@@ -1457,41 +1481,41 @@ Providing a new name will create a new document.
Export to OpenBoard Format
-
+ 以 OpenBoard 格式匯出UBExportDocumentSetAdaptorExport failed.
- 匯出失敗。
+ 匯出失敗。Failed to export...
-
+ 匯出失敗...Export as UBX File
-
+ 以 UBX 檔案匯出Exporting document...
-
+ 匯出檔案中...Export successful.
-
+ 匯出成功。Export to OpenBoard UBX Format
-
+ 以 OpenBoard UBX 格式匯出UBExportFullPDFExport as PDF File
- 以PDF格式匯出
+ 以 PDF 格式匯出Exporting document...
@@ -1499,7 +1523,7 @@ Providing a new name will create a new document.
Export to PDF
- 匯出成PDF
+ 匯出成 PDFExport successful.
@@ -1510,7 +1534,7 @@ Providing a new name will create a new document.
UBExportPDFExport as PDF File
- 以PDF格式匯出
+ 以 PDF 格式匯出Exporting page %1 of %2
@@ -1526,7 +1550,7 @@ Providing a new name will create a new document.
Export to PDF
- 匯出成PDF
+ 匯出成 PDF
@@ -1553,7 +1577,7 @@ Providing a new name will create a new document.
Export to Web Browser
- 匯出成網頁瀏覽
+ 匯出至瀏覽器
@@ -1669,7 +1693,7 @@ Providing a new name will create a new document.
Enter a new folder name
- 鍵入檔案名稱
+ 輸入檔案名稱
@@ -1706,7 +1730,7 @@ Providing a new name will create a new document.
Set as background
- 設定成背景
+ 設定成背景
@@ -1717,7 +1741,7 @@ Providing a new name will create a new document.
Unsupported media format
-
+ 不支援的媒體格式Media playback service not found
@@ -1725,14 +1749,14 @@ Providing a new name will create a new document.
Media error:
-
+ 媒體錯誤:UBGraphicsTextItem<Type Text Here>
- <此處鍵入文字>
+ <此處輸入文字>
@@ -1810,7 +1834,7 @@ Providing a new name will create a new document.
OpenBoard (*.ubz)
-
+ OpenBoard (*.ubz)
@@ -1824,18 +1848,18 @@ Providing a new name will create a new document.
UBImportImageImage Format (
- 圖像格式(
+ 圖像格式 (UBImportPDFPortable Document Format (*.pdf)
- Portable Document Format (*.pdf)
+ 可攜式檔案格式 (*.pdf)PDF import failed.
- PDF匯入失敗。
+ PDF 匯入失敗。Importing page %1 of %2
@@ -1864,7 +1888,7 @@ Providing a new name will create a new document.
UBKeyboardPaletteEnter
- 鍵入
+ 輸入
@@ -1897,7 +1921,7 @@ Providing a new name will create a new document.
Failed to log to Proxy
- 登入Proxy失敗
+ 登入 Proxy 失敗Yes
@@ -1922,7 +1946,7 @@ Do you want to ignore these errors for this host?
UBOpenSankoreImporterWidgetCancel
- 取消
+ 取消Open-Sankore Documents Detected
@@ -1942,7 +1966,7 @@ Do you want to ignore these errors for this host?
Proceed
-
+ 繼續
@@ -1959,6 +1983,10 @@ Do you want to ignore these errors for this host?
OpenBoard 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.
+
+ Renaming pages (%1/%2)
+
+ UBPlatformUtils
@@ -1980,22 +2008,22 @@ Do you want to ignore these errors for this host?
Swiss French
- 法文(瑞士)
+ 法文 (瑞士)UBPodcastControllerFailed to start encoder ...
- 編碼器(encoder)啟動失敗...
+ 編碼器啟動失敗...No Podcast encoder available ...
- 沒有可用的Podcast編碼器(encoder)...
+ 沒有可用的Podcast編碼器...Part %1
- Part %1
+ 第 %1 部分on your desktop ...
@@ -2011,7 +2039,7 @@ Do you want to ignore these errors for this host?
Podcast recording error (%1)
- Podcast錄製有錯誤 (%1)
+ Podcast 錄製有錯誤 (%1)Default Audio Input
@@ -2039,7 +2067,7 @@ Do you want to ignore these errors for this host?
Publish to Youtube
- 發佈至YouTube
+ 發佈至 YouTubeOpenBoard Cast
@@ -2050,7 +2078,7 @@ Do you want to ignore these errors for this host?
UBPreferencesControllerversion:
- 版本:
+ 版本:Marker is pressure sensitive
@@ -2061,15 +2089,15 @@ Do you want to ignore these errors for this host?
UBProxyLoginDlgProxy Login
- Proxy登入
+ Proxy 登入Username:
- 帳號:
+ 帳號:Password:
- 密碼:
+ 密碼:
@@ -2080,11 +2108,11 @@ Do you want to ignore these errors for this host?
Title:
- 標題:
+ 標題:Description:
- 描述:
+ 描述:Publish
@@ -2115,12 +2143,16 @@ Do you want to ignore these errors for this host?
%1 thumbnails generated ...已產生縮圖 %1...
+
+ Loading thumbnail (%1/%2)
+
+ UBThumbnailTextItemPage %0
- 第 %0 頁
+ 第 %0 頁
@@ -2151,7 +2183,7 @@ Do you want to ignore these errors for this host?
Cache
- Cache
+ 快取Axes
@@ -2199,7 +2231,7 @@ Do you want to ignore these errors for this host?
Files update successful!
Please reboot the application to access the updated documents.成功更新檔案!
-請重新啟動程式使用該檔案。
+請重新啟動程式以使用該檔案。
An error occured during the update. The files have not been affected.
@@ -2215,11 +2247,11 @@ Please reboot the application to access the updated documents.
Please wait the import process will start soon...
- 即將開始匯入,請稍待...
+ 即將開始匯入,請稍候...Remind me later
- 稍候題提醒我
+ 稍候提醒我
@@ -2240,15 +2272,15 @@ Please reboot the application to access the updated documents.
UBYouTubePublisherYouTube authentication failed.
- YouTube驗證失敗。
+ YouTube 驗證失敗。Error while uploading video to YouTube (%1)
- 影片上傳至YouTube (%1)過程中有錯誤
+ 影片上傳至 YouTube (%1)過程中有錯誤Upload to YouTube in progress %1 %
- 上傳至YouTube中 %1 %
+ 上傳至 YouTube 中 %1 %
@@ -2385,7 +2417,7 @@ Please reboot the application to access the updated documents.
?unknown file size
- ?
+ ?
@@ -2520,14 +2552,14 @@ Please reboot the application to access the updated documents.
XPDFRendererProcessing...
-
+ 處理中...YouTubePublishingDialogPublish Podcast to YouTube
- 發佈Podcast至YouTube
+ 發佈 Podcast 至 YouTubeTitle
@@ -2547,11 +2579,11 @@ Please reboot the application to access the updated documents.
YouTube Username
- YouTube帳號
+ YouTube 帳號YouTube Password
- YouTube密碼
+ YouTube 密碼<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
@@ -2567,7 +2599,7 @@ p, li { white-space: pre-wrap; }
OpenBoard
- OpenBoard
+ OpenBoardRestore credentials on reboot
@@ -2614,7 +2646,7 @@ p, li { white-space: pre-wrap; }
px
-
+ 像素
@@ -2671,19 +2703,19 @@ p, li { white-space: pre-wrap; }
Creation date
-
+ 建立日期Update date
-
+ 更新日期Alphabetical order
-
+ 按字母排序Sort Order
-
+ 排序方式
@@ -2750,7 +2782,7 @@ p, li { white-space: pre-wrap; }
Check software update at launch
- 啟用時檢查更新
+ 啟動時檢查更新Internet
@@ -2758,7 +2790,7 @@ p, li { white-space: pre-wrap; }
Home Page:
- 主頁:
+ 主頁:Toolbar
@@ -2774,7 +2806,7 @@ p, li { white-space: pre-wrap; }
version : …
- 版本: …
+ 版本: …Licences
@@ -2802,7 +2834,7 @@ p, li { white-space: pre-wrap; }
Mode to start in:
- 啟動模式:
+ 啟動模式:Board
@@ -2814,11 +2846,11 @@ p, li { white-space: pre-wrap; }
Proxy User:
- Proxy User:
+ Proxy 使用者:Pass:
- 密碼:
+ 密碼:Credits
@@ -2826,15 +2858,15 @@ p, li { white-space: pre-wrap; }
On Dark Background
- 深色背景
+ 深色背景Opacity
- 透明度
+ 透明度On Light Background
- 淡色背景
+ 淡色背景Swap first and second view displays
@@ -2842,15 +2874,15 @@ p, li { white-space: pre-wrap; }
Built-in virtual keyboard button size:
-
+ 內建虛擬鍵盤按鍵大小:Use system keyboard (recommended)
-
+ 使用系統鍵盤 (推薦)Grid
-
+ 網格Open-Sankoré Importer
@@ -2874,7 +2906,7 @@ p, li { white-space: pre-wrap; }
days
-
+ 天PDF Rendering
@@ -2889,11 +2921,11 @@ p, li { white-space: pre-wrap; }
trapFlashDialogTrap flash
- 擷取flash
+ 擷取 flashSelect a flash to trap
- 選擇要擷取的flash動畫
+ 選擇要擷取的 flash 動畫about:blank
@@ -2907,5 +2939,9 @@ p, li { white-space: pre-wrap; }
Create Application建立應用程式
+
+ Select a content to capture
+
+
diff --git a/resources/images/favorites.png b/resources/images/favorites.png
index a3275659..30c8dd04 100644
Binary files a/resources/images/favorites.png and b/resources/images/favorites.png differ
diff --git a/resources/images/folder.png b/resources/images/folder.png
index cff0b7f4..1f307946 100644
Binary files a/resources/images/folder.png and b/resources/images/folder.png differ
diff --git a/resources/images/libpalette/social.png b/resources/images/libpalette/social.png
index 9f1c6dcb..1322f27c 100644
Binary files a/resources/images/libpalette/social.png and b/resources/images/libpalette/social.png differ
diff --git a/resources/images/stylusPalette/eraserArrow.png b/resources/images/stylusPalette/eraserArrow.png
index 24f4bf99..e1c81098 100644
Binary files a/resources/images/stylusPalette/eraserArrow.png and b/resources/images/stylusPalette/eraserArrow.png differ
diff --git a/resources/images/stylusPalette/eraserOnArrow.png b/resources/images/stylusPalette/eraserOnArrow.png
index ee4953cb..3d1ec0ea 100644
Binary files a/resources/images/stylusPalette/eraserOnArrow.png and b/resources/images/stylusPalette/eraserOnArrow.png differ
diff --git a/resources/images/stylusPalette/markerArrow.png b/resources/images/stylusPalette/markerArrow.png
index c8b621bc..ef1a2281 100644
Binary files a/resources/images/stylusPalette/markerArrow.png and b/resources/images/stylusPalette/markerArrow.png differ
diff --git a/resources/images/stylusPalette/markerOnArrow.png b/resources/images/stylusPalette/markerOnArrow.png
index 36d1d2a8..e200d020 100644
Binary files a/resources/images/stylusPalette/markerOnArrow.png and b/resources/images/stylusPalette/markerOnArrow.png differ
diff --git a/resources/images/stylusPalette/penOnArrow.png b/resources/images/stylusPalette/penOnArrow.png
index 23aa2f9b..674ac013 100644
Binary files a/resources/images/stylusPalette/penOnArrow.png and b/resources/images/stylusPalette/penOnArrow.png differ
diff --git a/resources/images/toolPalette/axesTool.png b/resources/images/toolPalette/axesTool.png
index 05008c8c..78be7b06 100644
Binary files a/resources/images/toolPalette/axesTool.png and b/resources/images/toolPalette/axesTool.png differ
diff --git a/resources/images/tools.png b/resources/images/tools.png
index 5f40247e..04009965 100644
Binary files a/resources/images/tools.png and b/resources/images/tools.png differ
diff --git a/resources/images/trash-delete-document.png b/resources/images/trash-delete-document.png
new file mode 100644
index 00000000..05f9c1e1
Binary files /dev/null and b/resources/images/trash-delete-document.png differ
diff --git a/resources/images/trash-delete-folder.png b/resources/images/trash-delete-folder.png
new file mode 100644
index 00000000..ae920eaf
Binary files /dev/null and b/resources/images/trash-delete-folder.png differ
diff --git a/resources/images/trash-document-page.png b/resources/images/trash-document-page.png
new file mode 100644
index 00000000..19fc4089
Binary files /dev/null and b/resources/images/trash-document-page.png differ
diff --git a/resources/images/trash-document.png b/resources/images/trash-document.png
new file mode 100644
index 00000000..c3fda592
Binary files /dev/null and b/resources/images/trash-document.png differ
diff --git a/resources/images/trash-empty.png b/resources/images/trash-empty.png
new file mode 100644
index 00000000..94447b07
Binary files /dev/null and b/resources/images/trash-empty.png differ
diff --git a/resources/images/trash-folder.png b/resources/images/trash-folder.png
new file mode 100644
index 00000000..9cc89e97
Binary files /dev/null and b/resources/images/trash-folder.png differ
diff --git a/resources/images/trash-my-documents.png b/resources/images/trash-my-documents.png
new file mode 100644
index 00000000..a602798c
Binary files /dev/null and b/resources/images/trash-my-documents.png differ
diff --git a/resources/library/applications/WebBrowser.wgt/index.html b/resources/library/applications/WebBrowser.wgt/index.html
index a1ca93a7..8c77b1fe 100644
--- a/resources/library/applications/WebBrowser.wgt/index.html
+++ b/resources/library/applications/WebBrowser.wgt/index.html
@@ -138,12 +138,41 @@
if($("#textbox").val().length > 0){
loadingState = false;
var url = $("#textbox").val();
- var urlStart = url.split("://");
-
- if(urlStart[0]!="http"){
- url = "http://" + url;
- };
-
+ if(!url.startsWith("http"))
+ {
+ url = "https://" + url;
+ $("#textbox").val(url);
+ }
+
+ //non-exhaustive. add new names here as it is requested
+ var x_frame_options_secured_sites = [
+ "google.",
+ "youtube.",
+ "stackoverflow.",
+ "facebook.",
+ "github.",
+ "twitter.",
+ "amazon.",
+ "linkedin.",
+ "ebay."
+ ];
+
+ var iframe_denied = x_frame_options_secured_sites.some(function(element, indice, array)
+ {
+ return url.includes(element);
+ });
+
+ if (iframe_denied)
+ {
+ $("#container").addClass("error");
+ $("#web-content").hide();
+ $("#container-shadow").hide();
+ $("#content").hide();
+ $("#arrow").hide();
+ $("#notifications").html(sankoreLang[lang].error_xframe_options);
+ return false;
+ }
+
if(checkURLs(references, url)){
if(currentHistory == references.length)
references[currentHistory++] = url;
@@ -158,7 +187,8 @@
$("#arrow").hide();
$("#embeded-content").hide();
$("#web-content").hide();
- $('#web-content').attr('src',url);
+ $('#web-content').contents().find("body").html("");
+ $('#web-content').attr('src', url);
checkcontent();
checkLoading();
@@ -225,11 +255,12 @@
};
if(resizerIndex > 80){
resizerIndex = 0;
- console.log("error on loading page");
- $("#back-button").trigger("click");
- $("#textbox").val($("#textbox").val().replace("http://", ""));
- $("#textbox").val("http://www.metacrawler.com/search/web?&q=" + $("#textbox").val().replace("http://", "")+"&ql=");
- $("#search-button").trigger("click");
+ $("#container").addClass("error");
+ $("#web-content").hide();
+ $("#container-shadow").hide();
+ $("#content").hide();
+ $("#arrow").hide();
+ $("#notifications").html(sankoreLang[lang].error_loading_page);
}else{
resizer = setTimeout(function(){checkLoading()}, 100);
resizerIndex++;
@@ -280,6 +311,7 @@
+
diff --git a/resources/library/applications/WebBrowser.wgt/scripts/languages.js b/resources/library/applications/WebBrowser.wgt/scripts/languages.js
index 396dca88..6411fbee 100644
--- a/resources/library/applications/WebBrowser.wgt/scripts/languages.js
+++ b/resources/library/applications/WebBrowser.wgt/scripts/languages.js
@@ -6,7 +6,9 @@
"prev_page":"Previous page",
"next_page":"Next page",
"open":"Open the site",
- "alert":"Cannot open a page! Maybe it's because of a security policy or a wrong url. Also check your internet connection."
+ "alert":"Cannot open a page! Maybe it's because of a security policy or a wrong url. Also check your internet connection.",
+ "error_loading_page": "An error has occured during page's loading",
+ "error_xframe_options" : "This site does not allow its content to be embed from another domain"
},
"ru":{
"previous":"Пред.",
@@ -15,7 +17,9 @@
"prev_page":"Пред. страница",
"next_page":"След. страница",
"open":"Перейти",
- "alert":"Невозможно отобразить страницу! Возможно это из-за политики безопасности сайта или неверного адреса.Также стоит проверить подключение к интернету."
+ "alert":"Невозможно отобразить страницу! Возможно это из-за политики безопасности сайта или неверного адреса.Также стоит проверить подключение к интернету.",
+ "error_loading_page": "An error has occured during page's loading",
+ "error_xframe_options" : "This site does not allow its content to be embed from another domain"
},
"fr":{
"previous":"Précédente",
@@ -24,7 +28,9 @@
"prev_page":"Page précédente",
"next_page":"Page suivante",
"open":"Ouvrez le site",
- "alert":"Impossible d'ouvrir une page! Peut-être c'est à cause d'une politique de sécurité ou une URL erronée. Vérifiez aussi votre connexion internet."
+ "alert":"Impossible d'ouvrir une page! Peut-être c'est à cause d'une politique de sécurité ou une URL erronée. Vérifiez aussi votre connexion internet.",
+ "error_loading_page": "Une erreur est survenue durant le chargement de la page",
+ "error_xframe_options" : "Ce site n'autorise pas l'intégration de son contenu à partir d'un autre domaine"
},
"sk":{
"previous":"Predošlá",
@@ -33,7 +39,9 @@
"prev_page":"Predošlá stránka",
"next_page":"Ďalšia stránka",
"open":"Otvoriť stránku",
- "alert":"Stránka sa nedá otvoriť! Možno je to kvôli spôsobu zabezpečenia alebo nesprávnej internetovej adrese. Skontrolujte aj svoje internetové pripojenie."
+ "alert":"Stránka sa nedá otvoriť! Možno je to kvôli spôsobu zabezpečenia alebo nesprávnej internetovej adrese. Skontrolujte aj svoje internetové pripojenie.",
+ "error_loading_page": "An error has occured during page's loading",
+ "error_xframe_options" : "This site does not allow its content to be embed from another domain"
}
};
diff --git a/resources/linux/application-ubz.png b/resources/linux/application-ubz.png
new file mode 100644
index 00000000..6eff7417
Binary files /dev/null and b/resources/linux/application-ubz.png differ
diff --git a/resources/linux/application-ubz.svg b/resources/linux/application-ubz.svg
new file mode 100644
index 00000000..0320a2c8
--- /dev/null
+++ b/resources/linux/application-ubz.svg
@@ -0,0 +1,36 @@
+
+
+
diff --git a/resources/linux/run.sh b/resources/linux/run.sh
index a179fb4b..c3b1fe85 100644
--- a/resources/linux/run.sh
+++ b/resources/linux/run.sh
@@ -25,4 +25,4 @@ DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
# Add custom libraries to LD_LIBRARY_PATH
# TODO: Remomve the need for this
-env LD_LIBRARY_PATH=$DIR/qtlib:$LD_LIBRARY_PATH QT_PLUGIN_PATH=$DIR/plugins $DIR/OpenBoard
+env LD_LIBRARY_PATH=$DIR/qtlib:$LD_LIBRARY_PATH QT_PLUGIN_PATH=$DIR/plugins $DIR/OpenBoard "$@"
diff --git a/resources/macx/Info.plist b/resources/macx/Info.plist
index db9f96f2..5987de23 100644
--- a/resources/macx/Info.plist
+++ b/resources/macx/Info.plist
@@ -68,6 +68,8 @@
sparkle_public_key.pemNSMicrophoneUsageDescriptionAccès au microphone requis
+ NSAppleEventsUsageDescription
+ Accès au clavier virtuel requisUTExportedTypeDeclarations
diff --git a/resources/style/treeview-branch-closed.png b/resources/style/treeview-branch-closed.png
index be022111..2c566533 100644
Binary files a/resources/style/treeview-branch-closed.png and b/resources/style/treeview-branch-closed.png differ
diff --git a/resources/style/treeview-branch-open.png b/resources/style/treeview-branch-open.png
index 320b81e5..58fa3062 100644
Binary files a/resources/style/treeview-branch-open.png and b/resources/style/treeview-branch-open.png differ
diff --git a/src/adaptors/UBExportPDF.cpp b/src/adaptors/UBExportPDF.cpp
index 177f716d..683716bb 100644
--- a/src/adaptors/UBExportPDF.cpp
+++ b/src/adaptors/UBExportPDF.cpp
@@ -106,7 +106,17 @@ bool UBExportPDF::persistsDocument(UBDocumentProxy* pDocumentProxy, const QStrin
// set background to white, no crossing for PDF output
bool isDark = scene->isDarkBackground();
UBPageBackground pageBackground = scene->pageBackground();
- scene->setBackground(false, UBPageBackground::plain);
+
+ bool exportDark = isDark && UBSettings::settings()->exportBackgroundColor->get().toBool();
+
+ if (UBSettings::settings()->exportBackgroundGrid->get().toBool())
+ {
+ scene->setBackground(exportDark, pageBackground);
+ }
+ else
+ {
+ scene->setBackground(exportDark, UBPageBackground::plain);
+ }
// 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.
diff --git a/src/adaptors/UBMetadataDcSubsetAdaptor.cpp b/src/adaptors/UBMetadataDcSubsetAdaptor.cpp
index 9cbe55eb..54ce6d51 100644
--- a/src/adaptors/UBMetadataDcSubsetAdaptor.cpp
+++ b/src/adaptors/UBMetadataDcSubsetAdaptor.cpp
@@ -125,8 +125,6 @@ void UBMetadataDcSubsetAdaptor::persist(UBDocumentProxy* proxy)
// introduced in UB 4.4
xmlWriter.writeTextElement(UBSettings::uniboardDocumentNamespaceUri, "updated-at", UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTimeUtc()));
- xmlWriter.writeTextElement(UBSettings::uniboardDocumentNamespaceUri, "page-count", QString::number(proxy->pageCount()));
-
xmlWriter.writeEndElement(); //dc:Description
xmlWriter.writeEndElement(); //RDF
@@ -226,11 +224,6 @@ QMap UBMetadataDcSubsetAdaptor::load(QString pPath)
metadata.insert(UBSettings::documentUpdatedAt, xml.readElementText());
updatedAtFound = true;
}
- else if (xml.name() == "page-count"
- && xml.namespaceUri() == UBSettings::uniboardDocumentNamespaceUri)
- {
- metadata.insert(UBSettings::documentPageCount, xml.readElementText());
- }
metadata.insert(UBSettings::documentVersion, docVersion);
}
diff --git a/src/adaptors/UBSvgSubsetAdaptor.cpp b/src/adaptors/UBSvgSubsetAdaptor.cpp
index 62a4e524..1fde7639 100644
--- a/src/adaptors/UBSvgSubsetAdaptor.cpp
+++ b/src/adaptors/UBSvgSubsetAdaptor.cpp
@@ -29,6 +29,7 @@
#include "UBSvgSubsetAdaptor.h"
+#include
#include
#include
#include
@@ -239,6 +240,7 @@ QString UBSvgSubsetAdaptor::uniboardDocumentNamespaceUriFromVersion(int mFileVer
UBGraphicsScene* UBSvgSubsetAdaptor::loadScene(UBDocumentProxy* proxy, const int pageIndex)
{
+ UBApplication::showMessage(QObject::tr("Loading scene (%1/%2)").arg(pageIndex+1).arg(proxy->pageCount()));
QString fileName = proxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.svg", pageIndex);
qDebug() << fileName;
QFile file(fileName);
@@ -355,7 +357,7 @@ UBGraphicsScene* UBSvgSubsetAdaptor::UBSvgSubsetReader::loadScene(UBDocumentProx
time.start();
mScene = 0;
UBGraphicsWidgetItem *currentWidget = 0;
- bool pageDpiSpecified = true;
+ //bool pageDpiSpecified = true;
saveSceneAfterLoading = false;
mFileVersion = 40100; // default to 4.1.0
@@ -443,7 +445,7 @@ UBGraphicsScene* UBSvgSubsetAdaptor::UBSvgSubsetReader::loadScene(UBDocumentProx
else if (proxy->pageDpi() == 0) {
proxy->setPageDpi((UBApplication::desktop()->physicalDpiX() + UBApplication::desktop()->physicalDpiY())/2);
- pageDpiSpecified = false;
+ //pageDpiSpecified = false;
}
bool darkBackground = false;
@@ -909,9 +911,9 @@ UBGraphicsScene* UBSvgSubsetAdaptor::UBSvgSubsetReader::loadScene(UBDocumentProx
if (textDelegate)
{
- QDesktopWidget* desktop = UBApplication::desktop();
- qreal currentDpi = (desktop->physicalDpiX() + desktop->physicalDpiY()) / 2;
- qreal textSizeMultiplier = qreal(proxy->pageDpi())/currentDpi;
+ //QDesktopWidget* desktop = UBApplication::desktop();
+ //qreal currentDpi = (desktop->physicalDpiX() + desktop->physicalDpiY()) / 2;
+ //qreal textSizeMultiplier = qreal(proxy->pageDpi())/currentDpi;
//textDelegate->scaleTextSize(textSizeMultiplier);
}
@@ -2390,8 +2392,9 @@ void UBSvgSubsetAdaptor::UBSvgSubsetWriter::graphicsItemToSvg(QGraphicsItem* ite
mXmlWriter.writeAttribute("x", "0");
mXmlWriter.writeAttribute("y", "0");
- mXmlWriter.writeAttribute("width", QString("%1").arg(item->boundingRect().width()));
- mXmlWriter.writeAttribute("height", QString("%1").arg(item->boundingRect().height()));
+ QRectF rect = item->boundingRect() - QMarginsF(0.5, 0.5, 0.5, 0.5);
+ mXmlWriter.writeAttribute("width", QString("%1").arg(rect.width()));
+ mXmlWriter.writeAttribute("height", QString("%1").arg(rect.height()));
mXmlWriter.writeAttribute("transform", toSvgTransform(item->sceneMatrix()));
@@ -2487,8 +2490,9 @@ void UBSvgSubsetAdaptor::UBSvgSubsetWriter::graphicsWidgetToSvg(UBGraphicsWidget
mXmlWriter.writeStartElement(nsXHtml, "iframe");
mXmlWriter.writeAttribute("style", "border: none");
- mXmlWriter.writeAttribute("width", QString("%1").arg(item->boundingRect().width()));
- mXmlWriter.writeAttribute("height", QString("%1").arg(item->boundingRect().height()));
+ QRectF rect = item->boundingRect() - QMarginsF(0.5, 0.5, 0.5, 0.5);
+ mXmlWriter.writeAttribute("width", QString("%1").arg(rect.width()));
+ mXmlWriter.writeAttribute("height", QString("%1").arg(rect.height()));
QString startFileUrl;
if (item->mainHtmlFileName().startsWith("http://"))
@@ -2817,10 +2821,11 @@ void UBSvgSubsetAdaptor::UBSvgSubsetWriter::curtainItemToSvg(UBGraphicsCurtainIt
*/
mXmlWriter.writeStartElement(UBSettings::uniboardDocumentNamespaceUri, "curtain");
- mXmlWriter.writeAttribute("x", QString("%1").arg(curtainItem->boundingRect().center().x()));
- mXmlWriter.writeAttribute("y", QString("%1").arg(curtainItem->boundingRect().center().y()));
- mXmlWriter.writeAttribute("width", QString("%1").arg(curtainItem->boundingRect().width()));
- mXmlWriter.writeAttribute("height", QString("%1").arg(curtainItem->boundingRect().height()));
+ QRectF rect = curtainItem->boundingRect() - QMarginsF(0.5, 0.5, 0.5, 0.5);
+ mXmlWriter.writeAttribute("x", QString("%1").arg(rect.center().x()));
+ mXmlWriter.writeAttribute("y", QString("%1").arg(rect.center().y()));
+ mXmlWriter.writeAttribute("width", QString("%1").arg(rect.width()));
+ mXmlWriter.writeAttribute("height", QString("%1").arg(rect.height()));
mXmlWriter.writeAttribute("transform", toSvgTransform(curtainItem->sceneMatrix()));
//graphicsItemToSvg(curtainItem);
@@ -2877,10 +2882,11 @@ void UBSvgSubsetAdaptor::UBSvgSubsetWriter::rulerToSvg(UBGraphicsRuler* item)
*/
mXmlWriter.writeStartElement(UBSettings::uniboardDocumentNamespaceUri, "ruler");
- mXmlWriter.writeAttribute("x", QString("%1").arg(item->boundingRect().x()));
- mXmlWriter.writeAttribute("y", QString("%1").arg(item->boundingRect().y()));
- mXmlWriter.writeAttribute("width", QString("%1").arg(item->boundingRect().width()));
- mXmlWriter.writeAttribute("height", QString("%1").arg(item->boundingRect().height()));
+ QRectF rect = item->boundingRect() - QMarginsF(0.5, 0.5, 0.5, 0.5);
+ mXmlWriter.writeAttribute("x", QString("%1").arg(rect.x()));
+ mXmlWriter.writeAttribute("y", QString("%1").arg(rect.y()));
+ mXmlWriter.writeAttribute("width", QString("%1").arg(rect.width()));
+ mXmlWriter.writeAttribute("height", QString("%1").arg(rect.height()));
mXmlWriter.writeAttribute("transform", toSvgTransform(item->sceneMatrix()));
QString zs;
@@ -3005,10 +3011,11 @@ void UBSvgSubsetAdaptor::UBSvgSubsetWriter::compassToSvg(UBGraphicsCompass* item
*/
mXmlWriter.writeStartElement(UBSettings::uniboardDocumentNamespaceUri, "compass");
- mXmlWriter.writeAttribute("x", QString("%1").arg(item->boundingRect().x()));
- mXmlWriter.writeAttribute("y", QString("%1").arg(item->boundingRect().y()));
- mXmlWriter.writeAttribute("width", QString("%1").arg(item->boundingRect().width()));
- mXmlWriter.writeAttribute("height", QString("%1").arg(item->boundingRect().height()));
+ QRectF rect = item->boundingRect() - QMarginsF(0.5, 0.5, 0.5, 0.5);
+ mXmlWriter.writeAttribute("x", QString("%1").arg(rect.x()));
+ mXmlWriter.writeAttribute("y", QString("%1").arg(rect.y()));
+ mXmlWriter.writeAttribute("width", QString("%1").arg(rect.width()));
+ mXmlWriter.writeAttribute("height", QString("%1").arg(rect.height()));
mXmlWriter.writeAttribute("transform", toSvgTransform(item->sceneMatrix()));
QString zs;
@@ -3139,10 +3146,11 @@ void UBSvgSubsetAdaptor::UBSvgSubsetWriter::triangleToSvg(UBGraphicsTriangle *it
*/
mXmlWriter.writeStartElement(UBSettings::uniboardDocumentNamespaceUri, "triangle");
- mXmlWriter.writeAttribute("x", QString("%1").arg(item->boundingRect().x()));
- mXmlWriter.writeAttribute("y", QString("%1").arg(item->boundingRect().y()));
- mXmlWriter.writeAttribute("width", QString("%1").arg(item->boundingRect().width()));
- mXmlWriter.writeAttribute("height", QString("%1").arg(item->boundingRect().height()));
+ QRectF rect = item->boundingRect() - QMarginsF(0.5, 0.5, 0.5, 0.5);
+ mXmlWriter.writeAttribute("x", QString("%1").arg(rect.x()));
+ mXmlWriter.writeAttribute("y", QString("%1").arg(rect.y()));
+ mXmlWriter.writeAttribute("width", QString("%1").arg(rect.width()));
+ mXmlWriter.writeAttribute("height", QString("%1").arg(rect.height()));
mXmlWriter.writeAttribute("transform", toSvgTransform(item->sceneMatrix()));
mXmlWriter.writeAttribute("orientation", UBGraphicsTriangle::orientationToStr(item->getOrientation()));
diff --git a/src/adaptors/UBThumbnailAdaptor.cpp b/src/adaptors/UBThumbnailAdaptor.cpp
index b73f9e57..f01cc27b 100644
--- a/src/adaptors/UBThumbnailAdaptor.cpp
+++ b/src/adaptors/UBThumbnailAdaptor.cpp
@@ -83,8 +83,9 @@ void UBThumbnailAdaptor::generateMissingThumbnails(UBDocumentProxy* proxy)
}
}
-const QPixmap* UBThumbnailAdaptor::get(UBDocumentProxy* proxy, int pageIndex)
+QPixmap UBThumbnailAdaptor::get(UBDocumentProxy* proxy, int pageIndex)
{
+ UBApplication::showMessage(tr("Loading thumbnail (%1/%2)").arg(pageIndex+1).arg(proxy->pageCount()));
QString fileName = proxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.thumbnail.jpg", pageIndex);
QFile file(fileName);
@@ -93,30 +94,21 @@ const QPixmap* UBThumbnailAdaptor::get(UBDocumentProxy* proxy, int pageIndex)
generateMissingThumbnails(proxy);
}
- QPixmap* pix = new QPixmap();
+ QPixmap pix;
if (file.exists())
{
- //Warning. Works only with modified Qt
-#ifdef Q_OS_LINUX
- pix->load(fileName, 0, Qt::AutoColor);
-#else
- pix->load(fileName, 0, Qt::AutoColor);
-#endif
+ pix.load(fileName, 0, Qt::AutoColor);
}
return pix;
}
-void UBThumbnailAdaptor::load(UBDocumentProxy* proxy, QList& list)
+void UBThumbnailAdaptor::load(UBDocumentProxy* proxy, QList>& list)
{
- generateMissingThumbnails(proxy);
-
- foreach(const QPixmap* pm, list){
- delete pm;
- pm = NULL;
- }
list.clear();
for(int i=0; ipageCount(); i++)
- list.append(get(proxy, i));
+ {
+ list.append(std::make_shared(get(proxy, i)));
+ }
}
void UBThumbnailAdaptor::persistScene(UBDocumentProxy* proxy, UBGraphicsScene* pScene, int pageIndex, bool overrideModified)
diff --git a/src/adaptors/UBThumbnailAdaptor.h b/src/adaptors/UBThumbnailAdaptor.h
index 8c36b724..47f8be17 100644
--- a/src/adaptors/UBThumbnailAdaptor.h
+++ b/src/adaptors/UBThumbnailAdaptor.h
@@ -45,8 +45,8 @@ public:
static void persistScene(UBDocumentProxy* proxy, UBGraphicsScene* pScene, int pageIndex, bool overrideModified = false);
- static const QPixmap* get(UBDocumentProxy* proxy, int index);
- static void load(UBDocumentProxy* proxy, QList& list);
+ static QPixmap get(UBDocumentProxy* proxy, int index);
+ static void load(UBDocumentProxy* proxy, QList>& list);
private:
static void generateMissingThumbnails(UBDocumentProxy* proxy);
diff --git a/src/board/UBBoardController.cpp b/src/board/UBBoardController.cpp
index 0ee35ae5..1a02262d 100644
--- a/src/board/UBBoardController.cpp
+++ b/src/board/UBBoardController.cpp
@@ -346,6 +346,8 @@ void UBBoardController::setupToolbar()
, lineWidthChoice, SLOT(setCurrentIndex(int)));
lineWidthChoice->displayText(QVariant(settings->appToolBarDisplayText->get().toBool()));
+ lineWidthChoice->setCurrentIndex(settings->penWidthIndex());
+ lineWidthActions.at(settings->penWidthIndex())->setChecked(true);
mMainWindow->boardToolBar->insertWidget(mMainWindow->actionBackgrounds, lineWidthChoice);
@@ -367,6 +369,7 @@ void UBBoardController::setupToolbar()
eraserWidthChoice->displayText(QVariant(settings->appToolBarDisplayText->get().toBool()));
eraserWidthChoice->setCurrentIndex(settings->eraserWidthIndex());
+ eraserWidthActions.at(settings->eraserWidthIndex())->setChecked(true);
mMainWindow->boardToolBar->insertSeparator(mMainWindow->actionBackgrounds);
@@ -521,6 +524,11 @@ void UBBoardController::addScene()
persistCurrentScene(false,true);
UBDocumentContainer::addPage(mActiveSceneIndex + 1);
+ if (UBApplication::documentController->selectedDocument() == selectedDocument())
+ {
+ UBApplication::documentController->insertThumbPage(mActiveSceneIndex+1);
+ UBApplication::documentController->reloadThumbnails();
+ }
selectedDocument()->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime()));
@@ -580,11 +588,13 @@ void UBBoardController::duplicateScene(int nIndex)
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
persistCurrentScene(false,true);
- QList scIndexes;
- scIndexes << nIndex;
- duplicatePages(scIndexes);
+ duplicatePage(nIndex);
insertThumbPage(nIndex);
- emit documentThumbnailsUpdated(this);
+ if (UBApplication::documentController->selectedDocument() == selectedDocument())
+ {
+ UBApplication::documentController->insertThumbPage(nIndex);
+ UBApplication::documentController->reloadThumbnails();
+ }
emit addThumbnailRequired(this, nIndex + 1);
selectedDocument()->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime()));
@@ -725,11 +735,19 @@ UBGraphicsItem *UBBoardController::duplicateItem(UBItem *item)
case UBMimeType::UNKNOWN:
{
+ QGraphicsItem *copiedItem = dynamic_cast(item);
QGraphicsItem *gitem = dynamic_cast(item->deepCopy());
if (gitem)
{
mActiveScene->addItem(gitem);
+ if (copiedItem)
+ {
+ if (mActiveScene->tools().contains(copiedItem))
+ {
+ mActiveScene->registerTool(gitem);
+ }
+ }
gitem->setPos(itemPos);
mLastCreatedItem = gitem;
@@ -779,6 +797,10 @@ void UBBoardController::deleteScene(int nIndex)
QList scIndexes;
scIndexes << nIndex;
deletePages(scIndexes);
+ if (UBApplication::documentController->selectedDocument() == selectedDocument())
+ {
+ UBApplication::documentController->deleteThumbPage(nIndex);
+ }
selectedDocument()->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime()));
UBMetadataDcSubsetAdaptor::persist(selectedDocument());
@@ -865,7 +887,6 @@ void UBBoardController::showKeyboard(bool show)
UBPlatformUtils::showOSK(show);
else
mPaletteManager->showVirtualKeyboard(show);
-
}
@@ -984,7 +1005,7 @@ void UBBoardController::previousScene()
persistViewPositionOnCurrentScene();
persistCurrentScene();
setActiveDocumentScene(mActiveSceneIndex - 1);
- mControlView->centerOn(mActiveScene->lastCenter());
+ centerOn(mActiveScene->lastCenter());
QApplication::restoreOverrideCursor();
}
@@ -1000,7 +1021,7 @@ void UBBoardController::nextScene()
persistViewPositionOnCurrentScene();
persistCurrentScene();
setActiveDocumentScene(mActiveSceneIndex + 1);
- mControlView->centerOn(mActiveScene->lastCenter());
+ centerOn(mActiveScene->lastCenter());
QApplication::restoreOverrideCursor();
}
@@ -1016,7 +1037,7 @@ void UBBoardController::firstScene()
persistViewPositionOnCurrentScene();
persistCurrentScene();
setActiveDocumentScene(0);
- mControlView->centerOn(mActiveScene->lastCenter());
+ centerOn(mActiveScene->lastCenter());
QApplication::restoreOverrideCursor();
}
@@ -1032,7 +1053,7 @@ void UBBoardController::lastScene()
persistViewPositionOnCurrentScene();
persistCurrentScene();
setActiveDocumentScene(selectedDocument()->pageCount() - 1);
- mControlView->centerOn(mActiveScene->lastCenter());
+ centerOn(mActiveScene->lastCenter());
QApplication::restoreOverrideCursor();
}
@@ -1418,12 +1439,16 @@ UBItem *UBBoardController::downloadFinished(bool pSuccess, QUrl sourceUrl, QUrl
QStringList fileNames;
fileNames << pdfFile.fileName();
result = UBDocumentManager::documentManager()->addFilesToDocument(selectedDocument(), fileNames);
- emit documentThumbnailsUpdated(this);
+ reloadThumbnails();
pdfFile.close();
}
}
- if (result){
+ if (result)
+ {
+ if (UBApplication::documentController->selectedDocument() == selectedDocument())
+ UBApplication::documentController->reloadThumbnails();
+
selectedDocument()->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime()));
}
}
@@ -1618,7 +1643,12 @@ void UBBoardController::moveSceneToIndex(int source, int target)
{
persistCurrentScene(false,true);
- UBDocumentContainer::movePageToIndex(source, target);
+ UBPersistenceManager::persistenceManager()->moveSceneToIndex(selectedDocument(), source, target);
+ UBDocumentContainer::moveThumbPage(source, target);
+ if (UBApplication::documentController->selectedDocument() == selectedDocument())
+ {
+ UBApplication::documentController->moveThumbPage(source, target);
+ }
selectedDocument()->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime()));
UBPersistenceManager::persistenceManager()->persistDocumentMetadata(selectedDocument());
@@ -1632,11 +1662,11 @@ void UBBoardController::moveSceneToIndex(int source, int target)
}
}
-void UBBoardController::findUniquesItems(const QUndoCommand *parent, QSet &itms)
+void UBBoardController::findUniquesItems(const QUndoCommand *parent, QSet &items)
{
if (parent->childCount()) {
for (int i = 0; i < parent->childCount(); i++) {
- findUniquesItems(parent->child(i), itms);
+ findUniquesItems(parent->child(i), items);
}
}
@@ -1657,16 +1687,26 @@ void UBBoardController::findUniquesItems(const QUndoCommand *parent, QSetparentItem() && UBGraphicsGroupContainerItem::Type == item->parentItem()->type()))
- itms.insert(item);
+ if (!items.contains(item) &&
+ !(item->parentItem() && UBGraphicsGroupContainerItem::Type == item->parentItem()->type()) &&
+ !items.contains(item->parentItem())
+ )
+ {
+ items.insert(item);
+ }
}
QSetIterator itRemoved(cmd->GetRemovedList());
while (itRemoved.hasNext())
{
QGraphicsItem* item = itRemoved.next();
- if( !itms.contains(item) && !(item->parentItem() && UBGraphicsGroupContainerItem::Type == item->parentItem()->type()))
- itms.insert(item);
+ if (!items.contains(item) &&
+ !(item->parentItem() && UBGraphicsGroupContainerItem::Type == item->parentItem()->type()) &&
+ !items.contains(item->parentItem())
+ )
+ {
+ items.insert(item);
+ }
}
}
@@ -1867,7 +1907,7 @@ void UBBoardController::documentSceneChanged(UBDocumentProxy* pDocumentProxy, in
if(selectedDocument() == pDocumentProxy)
{
setActiveDocumentScene(mActiveSceneIndex);
- updatePage(pIndex);
+ updateThumbPage(pIndex);
}
}
@@ -1906,7 +1946,12 @@ void UBBoardController::closing()
mIsClosing = true;
lastWindowClosed();
ClearUndoStack();
- showKeyboard(false);
+#ifdef Q_OS_OSX
+ if (!UBPlatformUtils::errorOpeningVirtualKeyboard)
+ showKeyboard(false);
+#else
+ showKeyboard(false);
+#endif
}
void UBBoardController::lastWindowClosed()
@@ -2010,8 +2055,12 @@ void UBBoardController::persistCurrentScene(bool isAnAutomaticBackup, bool force
&& (mActiveSceneIndex >= 0) && mActiveSceneIndex != mMovingSceneIndex
&& (mActiveScene->isModified()))
{
- UBPersistenceManager::persistenceManager()->persistDocumentScene(selectedDocument(), mActiveScene, mActiveSceneIndex);
- updatePage(mActiveSceneIndex);
+ UBPersistenceManager::persistenceManager()->persistDocumentScene(selectedDocument(), mActiveScene, mActiveSceneIndex, isAnAutomaticBackup);
+ updateThumbPage(mActiveSceneIndex);
+ if (UBApplication::documentController->selectedDocument() == selectedDocument())
+ {
+ UBApplication::documentController->updateThumbPage(mActiveSceneIndex);
+ }
}
}
@@ -2142,7 +2191,14 @@ void UBBoardController::stylusToolChanged(int tool)
if(eTool != UBStylusTool::Selector && eTool != UBStylusTool::Text)
{
if(mPaletteManager->mKeyboardPalette->m_isVisible)
+ {
+#ifdef Q_OS_OSX
+ if (!UBPlatformUtils::errorOpeningVirtualKeyboard)
+ UBApplication::mainWindow->actionVirtualKeyboard->activate(QAction::Trigger);
+#else
UBApplication::mainWindow->actionVirtualKeyboard->activate(QAction::Trigger);
+#endif
+ }
}
}
diff --git a/src/board/UBBoardController.h b/src/board/UBBoardController.h
index 360e2e71..2f95ed88 100644
--- a/src/board/UBBoardController.h
+++ b/src/board/UBBoardController.h
@@ -177,7 +177,7 @@ class UBBoardController : public UBDocumentContainer
void notifyPageChanged();
void displayMetaData(QMap metadatas);
- void findUniquesItems(const QUndoCommand *parent, QSet &itms);
+ void findUniquesItems(const QUndoCommand *parent, QSet &items);
void ClearUndoStack();
void setActiveDocumentScene(UBDocumentProxy* pDocumentProxy, int pSceneIndex = 0, bool forceReload = false, bool onImport = false);
diff --git a/src/board/UBBoardPaletteManager.cpp b/src/board/UBBoardPaletteManager.cpp
index 720fbe9f..31605dbd 100644
--- a/src/board/UBBoardPaletteManager.cpp
+++ b/src/board/UBBoardPaletteManager.cpp
@@ -512,16 +512,18 @@ void UBBoardPaletteManager::containerResized()
mKeyboardPalette->adjustSizeAndPosition();
}
- if(mLeftPalette)
+// NOTE @letsfindaway Fixed, but don't see any reason for this.
+// Probably remove.
+ if(mLeftPalette && mLeftPalette->width() > 0)
{
mLeftPalette->resize(mLeftPalette->width()-1, mContainer->height());
- mLeftPalette->resize(mLeftPalette->width(), mContainer->height());
+ mLeftPalette->resize(mLeftPalette->width()+1, mContainer->height());
}
- if(mRightPalette)
+ if(mRightPalette && mRightPalette->width() > 0)
{
mRightPalette->resize(mRightPalette->width()-1, mContainer->height());
- mRightPalette->resize(mRightPalette->width(), mContainer->height());
+ mRightPalette->resize(mRightPalette->width()+1, mContainer->height());
}
}
diff --git a/src/board/UBBoardView.cpp b/src/board/UBBoardView.cpp
index 5ba68364..f60cbd19 100644
--- a/src/board/UBBoardView.cpp
+++ b/src/board/UBBoardView.cpp
@@ -486,8 +486,14 @@ void UBBoardView::handleItemsSelection(QGraphicsItem *item)
if (item)
{
// item has group as first parent - it is any item or UBGraphicsStrokesGroup.
- if(item->parentItem() && UBGraphicsGroupContainerItem::Type == getMovingItem()->parentItem()->type())
- return;
+ if (getMovingItem())
+ {
+ if (getMovingItem()->parentItem())
+ {
+ if(item->parentItem() && UBGraphicsGroupContainerItem::Type == getMovingItem()->parentItem()->type())
+ return;
+ }
+ }
// delegate buttons shouldn't selected
if (DelegateButton::Type == item->type())
@@ -510,6 +516,7 @@ void UBBoardView::handleItemsSelection(QGraphicsItem *item)
if ((UBGraphicsItemType::UserTypesCount > item->type()) && (item->type() > QGraphicsItem::UserType))
{
scene()->deselectAllItemsExcept(item);
+ scene()->updateSelectionFrame();
}
}
}
@@ -653,11 +660,17 @@ bool UBBoardView::itemShouldBeMoved(QGraphicsItem *item)
if (!(mMouseButtonIsPressed || mTabletStylusIsPressed))
return false;
- if (getMovingItem()->data(UBGraphicsItemData::ItemLocked).toBool())
- return false;
+ if (getMovingItem())
+ {
+ if (getMovingItem()->data(UBGraphicsItemData::ItemLocked).toBool())
+ return false;
- if (getMovingItem()->parentItem() && UBGraphicsGroupContainerItem::Type == getMovingItem()->parentItem()->type() && !getMovingItem()->isSelected() && getMovingItem()->parentItem()->isSelected())
- return false;
+ if (getMovingItem()->parentItem())
+ {
+ if (UBGraphicsGroupContainerItem::Type == getMovingItem()->parentItem()->type() && !getMovingItem()->isSelected() && getMovingItem()->parentItem()->isSelected())
+ return false;
+ }
+ }
UBStylusTool::Enum currentTool = (UBStylusTool::Enum)UBDrawingController::drawingController()->stylusTool();
@@ -684,7 +697,6 @@ bool UBBoardView::itemShouldBeMoved(QGraphicsItem *item)
case UBGraphicsAudioItem::Type:
return true;
case UBGraphicsStrokesGroup::Type:
- return false;
case UBGraphicsTextItem::Type:
if (currentTool == UBStylusTool::Play)
return true;
@@ -831,20 +843,29 @@ void UBBoardView::handleItemMouseMove(QMouseEvent *event)
QPointF posAfterMove;
if (getMovingItem())
+ {
posBeforeMove = getMovingItem()->pos();
-
- QGraphicsView::mouseMoveEvent (event);
-
- if (getMovingItem())
+ QGraphicsView::mouseMoveEvent (event);
posAfterMove = getMovingItem()->pos();
+ }
+ else
+ {
+ if (!mMouseButtonIsPressed)
+ {
+ QGraphicsView::mouseMoveEvent(event);
+ }
+ }
mWidgetMoved = ((posAfterMove-posBeforeMove).manhattanLength() != 0);
// a cludge for terminate moving of w3c widgets.
// in some cases w3c widgets catches mouse move and doesn't sends that events to web page,
// at simple - in google map widget - mouse move events doesn't comes to web page from rectangle of wearch bar on bottom right corner of widget.
- if (getMovingItem() && mWidgetMoved && UBGraphicsW3CWidgetItem::Type == getMovingItem()->type())
- getMovingItem()->setPos(posBeforeMove);
+ if (getMovingItem())
+ {
+ if (mWidgetMoved && UBGraphicsW3CWidgetItem::Type == getMovingItem()->type())
+ getMovingItem()->setPos(posBeforeMove);
+ }
}
}
@@ -1270,51 +1291,58 @@ void UBBoardView::mouseReleaseEvent (QMouseEvent *event)
setMovingItem(nullptr);
}
else
- if (getMovingItem() && (!isCppTool(getMovingItem()) || UBGraphicsCurtainItem::Type == getMovingItem()->type()))
+ {
+ if (getMovingItem())
{
- if (suspendedMousePressEvent)
- {
- QGraphicsView::mousePressEvent(suspendedMousePressEvent); // suspendedMousePressEvent is deleted by old Qt event loop
- setMovingItem(NULL);
- delete suspendedMousePressEvent;
- suspendedMousePressEvent = NULL;
- bReleaseIsNeed = true;
- }
- else
+ if (!isCppTool(getMovingItem()) || UBGraphicsCurtainItem::Type == getMovingItem()->type())
{
- if (isUBItem(getMovingItem()) &&
- DelegateButton::Type != getMovingItem()->type() &&
- UBGraphicsDelegateFrame::Type != getMovingItem()->type() &&
- UBGraphicsCache::Type != getMovingItem()->type() &&
- QGraphicsWebView::Type != getMovingItem()->type() && // for W3C widgets as Tools.
- !(!isMultipleSelectionEnabled() && getMovingItem()->parentItem() && UBGraphicsWidgetItem::Type == getMovingItem()->type() && UBGraphicsGroupContainerItem::Type == getMovingItem()->parentItem()->type()))
+ if (suspendedMousePressEvent)
{
- bReleaseIsNeed = false;
- if (getMovingItem()->isSelected() && isMultipleSelectionEnabled())
- getMovingItem()->setSelected(false);
- else
- if (getMovingItem()->parentItem() && getMovingItem()->parentItem()->isSelected() && isMultipleSelectionEnabled())
- getMovingItem()->parentItem()->setSelected(false);
+ QGraphicsView::mousePressEvent(suspendedMousePressEvent); // suspendedMousePressEvent is deleted by old Qt event loop
+ setMovingItem(NULL);
+ delete suspendedMousePressEvent;
+ suspendedMousePressEvent = NULL;
+ bReleaseIsNeed = true;
+ }
+ else
+ {
+ if (isUBItem(getMovingItem()) &&
+ DelegateButton::Type != getMovingItem()->type() &&
+ UBGraphicsDelegateFrame::Type != getMovingItem()->type() &&
+ UBGraphicsCache::Type != getMovingItem()->type() &&
+ QGraphicsWebView::Type != getMovingItem()->type() && // for W3C widgets as Tools.
+ !(!isMultipleSelectionEnabled() && getMovingItem()->parentItem() && UBGraphicsWidgetItem::Type == getMovingItem()->type() && UBGraphicsGroupContainerItem::Type == getMovingItem()->parentItem()->type()))
+ {
+ bReleaseIsNeed = false;
+ if (getMovingItem()->isSelected() && isMultipleSelectionEnabled())
+ getMovingItem()->setSelected(false);
else
- {
- if (getMovingItem()->isSelected())
- bReleaseIsNeed = true;
-
- UBGraphicsTextItem* textItem = dynamic_cast(getMovingItem());
- UBGraphicsMediaItem* movieItem = dynamic_cast(getMovingItem());
- if(textItem)
- textItem->setSelected(true);
- else if(movieItem)
- movieItem->setSelected(true);
+ if (getMovingItem()->parentItem() && getMovingItem()->parentItem()->isSelected() && isMultipleSelectionEnabled())
+ getMovingItem()->parentItem()->setSelected(false);
else
- getMovingItem()->setSelected(true);
- }
+ {
+ if (getMovingItem()->isSelected())
+ bReleaseIsNeed = true;
+
+ UBGraphicsTextItem* textItem = dynamic_cast(getMovingItem());
+ UBGraphicsMediaItem* movieItem = dynamic_cast(getMovingItem());
+ if(textItem)
+ textItem->setSelected(true);
+ else if(movieItem)
+ movieItem->setSelected(true);
+ else
+ getMovingItem()->setSelected(true);
+ }
+ }
}
}
+ else
+ bReleaseIsNeed = true;
}
else
bReleaseIsNeed = true;
+ }
if (bReleaseIsNeed)
{
@@ -1402,9 +1430,13 @@ void UBBoardView::mouseReleaseEvent (QMouseEvent *event)
return;
}
- if (mWidgetMoved) {
- getMovingItem()->setSelected(false);
- setMovingItem(NULL);
+ if (mWidgetMoved)
+ {
+ if (getMovingItem())
+ {
+ getMovingItem()->setSelected(false);
+ setMovingItem(NULL);
+ }
mWidgetMoved = false;
}
else {
diff --git a/src/core/UBApplication.cpp b/src/core/UBApplication.cpp
index b189c3b8..b7d3e0c0 100644
--- a/src/core/UBApplication.cpp
+++ b/src/core/UBApplication.cpp
@@ -81,6 +81,8 @@ const QString UBApplication::mimeTypeUniboardPage = QString("application/vnd.mne
const QString UBApplication::mimeTypeUniboardPageItem = QString("application/vnd.mnemis-uniboard-page-item");
const QString UBApplication::mimeTypeUniboardPageThumbnail = QString("application/vnd.mnemis-uniboard-thumbnail");
+QString UBApplication::fileToOpen = "";
+
#if defined(Q_OS_OSX) || defined(Q_OS_LINUX)
bool bIsMinimized = false;
#endif
@@ -88,7 +90,7 @@ bool bIsMinimized = false;
QObject* UBApplication::staticMemoryCleaner = 0;
-UBApplication::UBApplication(const QString &id, int &argc, char **argv) : QtSingleApplication(id, argc, argv)
+UBApplication::UBApplication(const QString &id, int &argc, char **argv) : SingleApplication(argc, argv)
, mPreferencesController(NULL)
, mApplicationTranslator(NULL)
, mQtGuiTranslator(NULL)
@@ -309,6 +311,14 @@ int UBApplication::exec(const QString& pFileToImport)
boardController->paletteManager()->rightPalette());
+ if (!UBApplication::fileToOpen.isEmpty())
+ {
+ if (!UBApplication::fileToOpen.endsWith("ubx"))
+ applicationController->importFile(UBApplication::fileToOpen);
+ else
+ applicationController->showMessage(tr("Cannot open your UBX file directly. Please import it in Documents mode instead"), false);
+ }
+
connect(applicationController, SIGNAL(mainModeChanged(UBApplicationController::MainMode)),
boardController->paletteManager(), SLOT(slot_changeMainMode(UBApplicationController::MainMode)));
@@ -348,7 +358,12 @@ int UBApplication::exec(const QString& pFileToImport)
boardController->setupLayout();
if (pFileToImport.length() > 0)
- UBApplication::applicationController->importFile(pFileToImport);
+ {
+ if (!pFileToImport.endsWith("ubx"))
+ applicationController->importFile(pFileToImport);
+ else
+ applicationController->showMessage(tr("Cannot open your UBX file directly. Please import it in Documents mode instead"), false);
+ }
if (UBSettings::settings()->appStartMode->get().toInt())
applicationController->showDesktop();
@@ -575,7 +590,21 @@ bool UBApplication::eventFilter(QObject *obj, QEvent *event)
UBPlatformUtils::setFrontProcess();
- applicationController->importFile(fileToOpenEvent->file());
+ if (applicationController)
+ {
+ if (!fileToOpenEvent->file().endsWith("ubx"))
+ applicationController->importFile(fileToOpenEvent->file());
+ else
+ applicationController->showMessage(tr("Cannot open your UBX file directly. Please import it in Documents mode instead"), false);
+ }
+ else
+ {
+ //startup : progressdialog.exec() is called and fileOpenEvent is consumed too early
+ // we store the file and will import it when the documents tree is ready
+
+ UBApplication::fileToOpen = fileToOpenEvent->file();
+ return true;
+ }
}
if (event->type() == QEvent::TabletLeaveProximity)
diff --git a/src/core/UBApplication.h b/src/core/UBApplication.h
index b821ce4a..5473804c 100644
--- a/src/core/UBApplication.h
+++ b/src/core/UBApplication.h
@@ -35,7 +35,7 @@
#include
#include
-#include "qtsingleapplication.h"
+#include "singleapplication/singleapplication.h"
namespace Ui
{
@@ -54,7 +54,7 @@ class UBApplicationController;
class UBDocumentController;
class UBMainWindow;
-class UBApplication : public QtSingleApplication
+class UBApplication : public SingleApplication
{
Q_OBJECT
@@ -86,6 +86,8 @@ class UBApplication : public QtSingleApplication
static const QString mimeTypeUniboardPageItem;
static const QString mimeTypeUniboardPageThumbnail;
+ static QString fileToOpen;
+
static void showMessage(const QString& message, bool showSpinningWheel = false);
static void setDisabled(bool disable);
diff --git a/src/core/UBApplicationController.cpp b/src/core/UBApplicationController.cpp
index ffe0f639..cf03215b 100644
--- a/src/core/UBApplicationController.cpp
+++ b/src/core/UBApplicationController.cpp
@@ -351,11 +351,11 @@ void UBApplicationController::showBoard()
if (mMainMode == Document)
{
- int selectedSceneIndex = UBApplication::documentController->getSelectedItemIndex();
- if (selectedSceneIndex != -1)
- {
- UBApplication::boardController->setActiveDocumentScene(UBApplication::documentController->selectedDocument(), selectedSceneIndex, true);
- }
+// int selectedSceneIndex = UBApplication::documentController->getSelectedItemIndex();
+// if (selectedSceneIndex != -1)
+// {
+// UBApplication::boardController->setActiveDocumentScene(UBApplication::documentController->selectedDocument(), selectedSceneIndex);
+// }
}
mMainMode = Board;
@@ -435,12 +435,12 @@ void UBApplicationController::showDocument()
{
if (UBApplication::boardController->activeScene()->isModified())
UBApplication::boardController->persistCurrentScene();
+
UBApplication::boardController->hide();
}
if (UBApplication::documentController)
{
- emit UBApplication::documentController->reorderDocumentsRequested();
UBApplication::documentController->show();
}
@@ -464,6 +464,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 cd9db4ec..4256379d 100644
--- a/src/core/UBDisplayManager.cpp
+++ b/src/core/UBDisplayManager.cpp
@@ -180,7 +180,7 @@ void UBDisplayManager::setDisplayWidget(QWidget* pDisplayWidget)
}
mDisplayWidget = pDisplayWidget;
mDisplayWidget->setGeometry(mDesktop->screenGeometry(mDisplayScreenIndex));
- if (UBSettings::settings()->appUseMultiscreen->get().toBool())
+ if (numScreens() > 1 && UBSettings::settings()->appUseMultiscreen->get().toBool())
UBPlatformUtils::showFullScreen(mDisplayWidget);
}
}
@@ -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 ac331d94..f451e519 100644
--- a/src/core/UBDocumentManager.cpp
+++ b/src/core/UBDocumentManager.cpp
@@ -286,7 +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);
- UBApplication::boardController->insertThumbPage(pageIndex);
}
UBPersistenceManager::persistenceManager()->persistDocumentMetadata(document);
diff --git a/src/core/UBPersistenceManager.cpp b/src/core/UBPersistenceManager.cpp
index 90a160c4..e163668e 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,52 +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);
+ 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;
- }
-
- QModelIndex parentIndex = mDocumentTreeStructureModel->goTo(docGroupName);
- if (!parentIndex.isValid()) {
- return;
+ return nullptr;
}
- UBDocumentProxy* docProxy = new UBDocumentProxy(fullPath, metadatas); // managed in UBDocumentTreeNode
+ UBDocumentProxy* docProxy = new UBDocumentProxy(fullPath); // managed in UBDocumentTreeNode
foreach(QString key, metadatas.keys()) {
docProxy->setMetaData(key, metadatas.value(key));
}
- if (metadatas.contains(UBSettings::documentPageCount))
- {
- int pageCount = metadatas.value(UBSettings::documentPageCount).toInt();
- if (pageCount == 0)
- pageCount = sceneCount(docProxy);
+ docProxy->setPageCount(sceneCount(docProxy));
- docProxy->setPageCount(pageCount);
- }
- else
- {
- int pageCount = sceneCount(docProxy);
- docProxy->setPageCount(pageCount);
- }
+ docProxy->moveToThread(UBApplication::instance()->thread());
- if (!interactive)
- mDocumentTreeStructureModel->addDocument(docProxy, parentIndex);
- else
- processInteractiveReplacementDialog(docProxy);
+ return docProxy;
}
-}
+
+ return nullptr;
+};
QDialog::DialogCode UBPersistenceManager::processInteractiveReplacementDialog(UBDocumentProxy *pProxy)
{
@@ -246,7 +279,10 @@ QDialog::DialogCode UBPersistenceManager::processInteractiveReplacementDialog(UB
if (mDocumentTreeStructureModel->currentIndex() == replaceIndex)
{
- UBApplication::documentController->selectDocument(pProxy, true, true);
+ if (pProxy->pageCount() > 0)
+ {
+ UBApplication::documentController->selectDocument(pProxy, true, true);
+ }
}
if (replaceProxy) {
@@ -256,7 +292,12 @@ QDialog::DialogCode UBPersistenceManager::processInteractiveReplacementDialog(UB
mDocumentTreeStructureModel->removeRow(i, parentIndex);
}
}
- pProxy->setMetaData(UBSettings::documentName, resultName);
+
+ if (docName != resultName)
+ {
+ pProxy->setMetaData(UBSettings::documentName, resultName);
+ UBMetadataDcSubsetAdaptor::persist(pProxy);
+ }
mDocumentTreeStructureModel->addDocument(pProxy, parentIndex);
}
replaceDialog->setParent(0);
@@ -625,11 +666,6 @@ void UBPersistenceManager::deleteDocumentScenes(UBDocumentProxy* proxy, const QL
if (compactedIndexes.size() == 0)
return;
- foreach(int index, compactedIndexes)
- {
- emit documentSceneWillBeDeleted(proxy, index);
- }
-
QString sourceName = proxy->metaData(UBSettings::documentName).toString();
UBDocumentProxy *trashDocProxy = createDocument(UBSettings::trashedDocumentGroupNamePrefix/* + sourceGroupName*/, sourceName, false);
@@ -650,8 +686,7 @@ void UBPersistenceManager::deleteDocumentScenes(UBDocumentProxy* proxy, const QL
d.mkpath(d.absolutePath());
QFile::copy(source, target);
}
-
- insertDocumentSceneAt(trashDocProxy, scene, trashDocProxy->pageCount());
+ insertDocumentSceneAt(trashDocProxy, scene, trashDocProxy->pageCount(), true, true);
}
}
@@ -817,7 +852,7 @@ void UBPersistenceManager::copyDocumentScene(UBDocumentProxy *from, int fromInde
Q_ASSERT(QFileInfo(thumbTmp).exists());
Q_ASSERT(QFileInfo(thumbTo).exists());
- const QPixmap *pix = new QPixmap(thumbTmp);
+ auto pix = std::make_shared(thumbTmp);
UBDocumentController *ctrl = UBApplication::documentController;
ctrl->addPixmapAt(pix, toIndex);
ctrl->TreeViewSelectionChanged(ctrl->firstSelectedTreeIndex(), QModelIndex());
@@ -828,10 +863,12 @@ void UBPersistenceManager::copyDocumentScene(UBDocumentProxy *from, int fromInde
UBGraphicsScene* UBPersistenceManager::createDocumentSceneAt(UBDocumentProxy* proxy, int index, bool useUndoRedoStack)
{
- int count = sceneCount(proxy);
+ int count = proxy->pageCount();
for(int i = count - 1; i >= index; i--)
+ {
renamePage(proxy, i , i + 1);
+ }
mSceneCache.shiftUpScenes(proxy, index, count -1);
@@ -852,7 +889,7 @@ UBGraphicsScene* UBPersistenceManager::createDocumentSceneAt(UBDocumentProxy* pr
}
-void UBPersistenceManager::insertDocumentSceneAt(UBDocumentProxy* proxy, UBGraphicsScene* scene, int index, bool persist)
+void UBPersistenceManager::insertDocumentSceneAt(UBDocumentProxy* proxy, UBGraphicsScene* scene, int index, bool persist, bool deleting)
{
scene->setDocument(proxy);
@@ -873,7 +910,8 @@ void UBPersistenceManager::insertDocumentSceneAt(UBDocumentProxy* proxy, UBGraph
persistDocumentScene(proxy, scene, index);
}
- emit documentSceneCreated(proxy, index);
+ if (!deleting)
+ emit documentSceneCreated(proxy, index);
}
@@ -939,11 +977,12 @@ void UBPersistenceManager::reassignDocProxy(UBDocumentProxy *newDocument, UBDocu
return mSceneCache.reassignDocProxy(newDocument, oldDocument);
}
-void UBPersistenceManager::persistDocumentScene(UBDocumentProxy* pDocumentProxy, UBGraphicsScene* pScene, const int pSceneIndex)
+void UBPersistenceManager::persistDocumentScene(UBDocumentProxy* pDocumentProxy, UBGraphicsScene* pScene, const int pSceneIndex, bool isAnAutomaticBackup)
{
checkIfDocumentRepositoryExists();
- pScene->deselectAllItems();
+ if (!isAnAutomaticBackup)
+ pScene->deselectAllItems();
generatePathIfNeeded(pDocumentProxy);
@@ -978,6 +1017,7 @@ UBDocumentProxy* UBPersistenceManager::persistDocumentMetadata(UBDocumentProxy*
void UBPersistenceManager::renamePage(UBDocumentProxy* pDocumentProxy, const int sourceIndex, const int targetIndex)
{
+ UBApplication::showMessage(tr("Renaming pages (%1/%2)").arg(sourceIndex).arg(pDocumentProxy->pageCount()));
QFile svg(pDocumentProxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.svg", sourceIndex));
svg.rename(pDocumentProxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.svg", targetIndex));
diff --git a/src/core/UBPersistenceManager.h b/src/core/UBPersistenceManager.h
index 2f5356f3..cdcba56f 100644
--- a/src/core/UBPersistenceManager.h
+++ b/src/core/UBPersistenceManager.h
@@ -103,12 +103,11 @@ class UBPersistenceManager : public QObject
virtual void copyDocumentScene(UBDocumentProxy *from, int fromIndex, UBDocumentProxy *to, int toIndex);
- virtual void persistDocumentScene(UBDocumentProxy* pDocumentProxy,
- UBGraphicsScene* pScene, const int pSceneIndex);
+ virtual void persistDocumentScene(UBDocumentProxy* pDocumentProxy, UBGraphicsScene* pScene, const int pSceneIndex, bool isAnAutomaticBackup = false);
virtual UBGraphicsScene* createDocumentSceneAt(UBDocumentProxy* pDocumentProxy, int index, bool useUndoRedoStack = true);
- virtual void insertDocumentSceneAt(UBDocumentProxy* pDocumentProxy, UBGraphicsScene* scene, int index, bool persist = true);
+ virtual void insertDocumentSceneAt(UBDocumentProxy* pDocumentProxy, UBGraphicsScene* scene, int index, bool persist = true, bool deleting = false);
virtual void moveSceneToIndex(UBDocumentProxy* pDocumentProxy, int source, int target);
@@ -132,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()
@@ -166,7 +166,6 @@ class UBPersistenceManager : public QObject
void documentWillBeDeleted(UBDocumentProxy* pDocumentProxy);
void documentSceneCreated(UBDocumentProxy* pDocumentProxy, int pIndex);
- void documentSceneWillBeDeleted(UBDocumentProxy* pDocumentProxy, int pIndex);
private:
int sceneCount(const UBDocumentProxy* pDocumentProxy);
@@ -189,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/core/UBSceneCache.cpp b/src/core/UBSceneCache.cpp
index c5a110d1..f449c57a 100644
--- a/src/core/UBSceneCache.cpp
+++ b/src/core/UBSceneCache.cpp
@@ -222,6 +222,7 @@ void UBSceneCache::shiftUpScenes(UBDocumentProxy* proxy, int startIncIndex, int
{
for(int i = endIncIndex; i >= startIncIndex; i--)
{
+ UBApplication::showMessage(QObject::tr("Moving cached scenes (%1/%2)").arg(i).arg(endIncIndex));
internalMoveScene(proxy, i, i + 1);
}
}
diff --git a/src/core/UBSettings.cpp b/src/core/UBSettings.cpp
index 23bbb069..c98f1d70 100644
--- a/src/core/UBSettings.cpp
+++ b/src/core/UBSettings.cpp
@@ -61,7 +61,6 @@ QString UBSettings::documentSize = QString("Size");
QString UBSettings::documentIdentifer = QString("ID");
QString UBSettings::documentVersion = QString("Version");
QString UBSettings::documentUpdatedAt = QString("UpdatedAt");
-QString UBSettings::documentPageCount = QString("PageCount");
QString UBSettings::documentDate = QString("date");
QString UBSettings::trashedDocumentGroupNamePrefix = QString("_Trash:");
@@ -73,6 +72,7 @@ QString UBSettings::undoCommandTransactionName = "UndoTransaction";
const int UBSettings::sDefaultFontPixelSize = 36;
const char *UBSettings::sDefaultFontFamily = "Arial";
+const char *UBSettings::sDefaultFontStyleName = "Regular";
QString UBSettings::currentFileVersion = "4.8.0";
@@ -361,9 +361,6 @@ void UBSettings::init()
webShowPageImmediatelyOnMirroredScreen = new UBSetting(this, "Web", "ShowPageImediatelyOnMirroredScreen", defaultShowPageImmediatelyOnMirroredScreen);
webHomePage = new UBSetting(this, "Web", "Homepage", softwareHomeUrl);
- webBookmarksPage = new UBSetting(this, "Web", "BookmarksPage", "http://www.myuniboard.com");
- webAddBookmarkUrl = new UBSetting(this, "Web", "AddBookmarkURL", "http://www.myuniboard.com/bookmarks/save/?url=");
- webShowAddBookmarkButton = new UBSetting(this, "Web", "ShowAddBookmarkButton", false);
pageCacheSize = new UBSetting(this, "App", "PageCacheSize", 20);
@@ -412,6 +409,8 @@ void UBSettings::init()
pdfZoomBehavior = new UBSetting(this, "PDF", "ZoomBehavior", "4");
enableQualityLossToIncreaseZoomPerfs = new UBSetting(this, "PDF", "enableQualityLossToIncreaseZoomPerfs", true);
+ exportBackgroundGrid = new UBSetting(this, "PDF", "ExportBackgroundGrid", false);
+ exportBackgroundColor = new UBSetting(this, "PDF", "ExportBackgroundColor", false);
podcastFramesPerSecond = new UBSetting(this, "Podcast", "FramesPerSecond", 10);
podcastVideoSize = new UBSetting(this, "Podcast", "VideoSize", "Medium");
@@ -871,6 +870,17 @@ void UBSettings::setFontFamily(const QString &family)
}
+QString UBSettings::fontStyleName()
+{
+ return value("Board/FontStyleName", sDefaultFontStyleName).toString();
+}
+
+
+void UBSettings::setFontStyleName(const QString &styleName)
+{
+ setValue("Board/FontStyleName", styleName);
+}
+
int UBSettings::fontPixelSize()
{
return value("Board/FontPixelSize", sDefaultFontPixelSize).toInt();
diff --git a/src/core/UBSettings.h b/src/core/UBSettings.h
index 653eb6dc..6067db5b 100644
--- a/src/core/UBSettings.h
+++ b/src/core/UBSettings.h
@@ -97,6 +97,8 @@ class UBSettings : public QObject
// Text related
QString fontFamily();
void setFontFamily(const QString &family);
+ QString fontStyleName();
+ void setFontStyleName(const QString &family);
int fontPixelSize();
void setFontPixelSize(int pixelSize);
int fontPointSize();
@@ -202,7 +204,6 @@ class UBSettings : public QObject
static QString documentIdentifer;
static QString documentVersion;
static QString documentUpdatedAt;
- static QString documentPageCount;
static QString documentDate;
@@ -328,9 +329,6 @@ class UBSettings : public QObject
UBSetting* webShowPageImmediatelyOnMirroredScreen;
UBSetting* webHomePage;
- UBSetting* webBookmarksPage;
- UBSetting* webAddBookmarkUrl;
- UBSetting* webShowAddBookmarkButton;
UBSetting* pageCacheSize;
@@ -363,6 +361,8 @@ class UBSettings : public QObject
UBSetting* pdfZoomBehavior;
UBSetting* enableQualityLossToIncreaseZoomPerfs;
+ UBSetting* exportBackgroundGrid;
+ UBSetting* exportBackgroundColor;
UBSetting* podcastFramesPerSecond;
UBSetting* podcastVideoSize;
@@ -466,6 +466,7 @@ class UBSettings : public QObject
static const int sDefaultFontPixelSize;
static const char *sDefaultFontFamily;
+ static const char *sDefaultFontStyleName;
static QSettings* getAppSettings();
diff --git a/src/core/main.cpp b/src/core/main.cpp
index ddb0c6ed..10f3f6ff 100644
--- a/src/core/main.cpp
+++ b/src/core/main.cpp
@@ -122,8 +122,8 @@ int main(int argc, char *argv[])
if (f.exists()) {
fileToOpen += args[1];
- if (app.sendMessage(UBSettings::appPingMessage, 20000)) {
- app.sendMessage(fileToOpen, 1000000);
+ if (app.sendMessage(UBSettings::appPingMessage.toUtf8(), 20000)) {
+ app.sendMessage(fileToOpen.toUtf8(), 1000000);
return 0;
}
}
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 ba269aa9..c810fd46 100644
--- a/src/desktop/UBDesktopAnnotationController.cpp
+++ b/src/desktop/UBDesktopAnnotationController.cpp
@@ -129,6 +129,7 @@ UBDesktopAnnotationController::UBDesktopAnnotationController(QObject *parent, UB
connect(mDesktopPalette, SIGNAL(minimizeStart(eMinimizedLocation)), this, SLOT(onDesktopPaletteMinimize()));
connect(mDesktopPalette, SIGNAL(mouseEntered()), mTransparentDrawingScene, SLOT(hideTool()));
connect(mRightPalette, SIGNAL(mouseEntered()), mTransparentDrawingScene, SLOT(hideTool()));
+ connect(mRightPalette, SIGNAL(pageSelectionChangedRequired()), this, SLOT(updateBackground()));
connect(mTransparentDrawingView, SIGNAL(resized(QResizeEvent*)), this, SLOT(onTransparentWidgetResized()));
@@ -515,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());
@@ -555,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
@@ -609,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
@@ -664,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
@@ -966,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/UBDocumentContainer.cpp b/src/document/UBDocumentContainer.cpp
index 456c37a7..86e857a7 100644
--- a/src/document/UBDocumentContainer.cpp
+++ b/src/document/UBDocumentContainer.cpp
@@ -40,10 +40,7 @@ UBDocumentContainer::UBDocumentContainer(QObject * parent)
UBDocumentContainer::~UBDocumentContainer()
{
- foreach(const QPixmap* pm, mDocumentThumbs){
- delete pm;
- pm = NULL;
- }
+
}
void UBDocumentContainer::setDocument(UBDocumentProxy* document, bool forceReload)
@@ -52,6 +49,7 @@ void UBDocumentContainer::setDocument(UBDocumentProxy* document, bool forceReloa
{
mCurrentDocument = document;
+ clearThumbPage();
reloadThumbnails();
emit documentSet(mCurrentDocument);
}
@@ -67,16 +65,20 @@ void UBDocumentContainer::duplicatePages(QList& pageIndexes)
}
}
-bool UBDocumentContainer::movePageToIndex(int source, int target)
+void UBDocumentContainer::duplicatePage(int index)
{
- //on document view
- UBPersistenceManager::persistenceManager()->moveSceneToIndex(mCurrentDocument, source, target);
- deleteThumbPage(source);
- insertThumbPage(target);
- emit documentThumbnailsUpdated(this);
- //on board thumbnails view
+ UBPersistenceManager::persistenceManager()->duplicateDocumentScene(mCurrentDocument, index);
+}
+
+void UBDocumentContainer::moveThumbPage(int source, int target)
+{
+ mDocumentThumbs.move(source, target);
+
+ //on board thumbnails view (UBDocumentNavigator)
+ emit documentPageMoved(source, target);
+
+ //on board thumbnails view (UBoardThumbnailsView)
emit moveThumbnailRequired(source, target);
- return true;
}
void UBDocumentContainer::deletePages(QList& pageIndexes)
@@ -86,33 +88,25 @@ void UBDocumentContainer::deletePages(QList& pageIndexes)
foreach(int index, pageIndexes)
{
deleteThumbPage(index - offset);
- emit removeThumbnailRequired(index - offset);
offset++;
-
}
- emit documentThumbnailsUpdated(this);
}
void UBDocumentContainer::addPage(int index)
{
UBPersistenceManager::persistenceManager()->createDocumentSceneAt(mCurrentDocument, index);
insertThumbPage(index);
-
- emit documentThumbnailsUpdated(this);
- emit addThumbnailRequired(this, index);
}
-void UBDocumentContainer::addPixmapAt(const QPixmap *pix, int index)
+void UBDocumentContainer::addPixmapAt(std::shared_ptr pix, int index)
{
mDocumentThumbs.insert(index, pix);
- emit documentThumbnailsUpdated(this);
}
void UBDocumentContainer::clearThumbPage()
{
- qDeleteAll(mDocumentThumbs);
mDocumentThumbs.clear();
}
@@ -124,41 +118,47 @@ void UBDocumentContainer::initThumbPage()
insertThumbPage(i);
}
-void UBDocumentContainer::updatePage(int index)
-{
- updateThumbPage(index);
- emit documentThumbnailsUpdated(this);
-}
-
void UBDocumentContainer::deleteThumbPage(int index)
{
mDocumentThumbs.removeAt(index);
+
+ //on board thumbnails view (UBDocumentNavigator)
+ emit documentPageRemoved(index);
+
+ //on board thumbnails view (UBoardThumbnailsView)
+ emit removeThumbnailRequired(index);
}
void UBDocumentContainer::updateThumbPage(int index)
{
if (mDocumentThumbs.size() > index)
{
- mDocumentThumbs[index] = UBThumbnailAdaptor::get(mCurrentDocument, index);
+ QPixmap pixmap = UBThumbnailAdaptor::get(mCurrentDocument, index);
+ mDocumentThumbs[index] = std::make_shared(pixmap);
+
emit documentPageUpdated(index);
}
- else
- {
- qDebug() << "error [updateThumbPage] : index > mDocumentThumbs' size.";
- }
}
void UBDocumentContainer::insertThumbPage(int index)
{
- mDocumentThumbs.insert(index, UBThumbnailAdaptor::get(mCurrentDocument, index));
+ QPixmap newPixmap = UBThumbnailAdaptor::get(mCurrentDocument, index);
+ mDocumentThumbs.insert(index, std::make_shared(newPixmap));
+
+ emit documentPageInserted(index);
+ emit addThumbnailRequired(this, index);
+}
+
+void UBDocumentContainer::insertExistingThumbPage(int index, std::shared_ptr thumbnailPixmap)
+{
+ mDocumentThumbs.insert(index, thumbnailPixmap);
+
+ emit documentPageInserted(index);
+ emit addThumbnailRequired(this, index);
}
void UBDocumentContainer::reloadThumbnails()
{
- if (mCurrentDocument)
- {
- UBThumbnailAdaptor::load(mCurrentDocument, mDocumentThumbs);
- }
emit documentThumbnailsUpdated(this);
}
@@ -174,6 +174,5 @@ int UBDocumentContainer::sceneIndexFromPage(int page)
void UBDocumentContainer::addEmptyThumbPage()
{
- const QPixmap* pThumb = new QPixmap();
- mDocumentThumbs.append(pThumb);
+ mDocumentThumbs.append(std::shared_ptr());
}
diff --git a/src/document/UBDocumentContainer.h b/src/document/UBDocumentContainer.h
index 497861b0..e02556b5 100644
--- a/src/document/UBDocumentContainer.h
+++ b/src/document/UBDocumentContainer.h
@@ -45,8 +45,9 @@ class UBDocumentContainer : public QObject
void pureSetDocument(UBDocumentProxy *document) {mCurrentDocument = document;}
UBDocumentProxy* selectedDocument(){return mCurrentDocument;}
- int pageCount(){return mCurrentDocument->pageCount();}
- const QPixmap* pageAt(int index)
+ QList>& documentThumbs() { return mDocumentThumbs; }
+ int pageCount() const{return mCurrentDocument->pageCount();}
+ std::shared_ptr pageAt(int index)
{
if (index < mDocumentThumbs.size())
return mDocumentThumbs[index];
@@ -60,38 +61,41 @@ class UBDocumentContainer : public QObject
static int sceneIndexFromPage(int sceneIndex);
void duplicatePages(QList& pageIndexes);
- bool movePageToIndex(int source, int target);
+ void duplicatePage(int index);
void deletePages(QList& pageIndexes);
- void clearThumbPage();
- void initThumbPage();
- void addPage(int index);
- void addPixmapAt(const QPixmap *pix, int index);
- void updatePage(int index);
- void addEmptyThumbPage();
- void reloadThumbnails();
- void insertThumbPage(int index);
- private:
- UBDocumentProxy* mCurrentDocument;
- QList mDocumentThumbs;
+ void addPage(int index);
+ void addPixmapAt(std::shared_ptr pix, int index);
+ virtual void reloadThumbnails();
- protected:
+ void clearThumbPage();
+ void initThumbPage();
+ void insertExistingThumbPage(int index, std::shared_ptr thumbnailPixmap);
+ void insertThumbPage(int index);
+ void addEmptyThumbPage();
void deleteThumbPage(int index);
void updateThumbPage(int index);
+ void moveThumbPage(int source, int target);
+
+ private:
+ UBDocumentProxy* mCurrentDocument;
+ QList> mDocumentThumbs;
signals:
void documentSet(UBDocumentProxy* document);
+ void documentPageInserted(int index);
void documentPageUpdated(int index);
+ void documentPageRemoved(int index);
+ void documentPageMoved(int from, int to);
+ void documentThumbnailsUpdated(UBDocumentContainer* source);
void initThumbnailsRequired(UBDocumentContainer* source);
void addThumbnailRequired(UBDocumentContainer* source, int index);
void removeThumbnailRequired(int index);
void moveThumbnailRequired(int from, int to);
void updateThumbnailsRequired();
-
- void documentThumbnailsUpdated(UBDocumentContainer* source);
};
diff --git a/src/document/UBDocumentController.cpp b/src/document/UBDocumentController.cpp
index 5f7bef20..f2b7c477 100644
--- a/src/document/UBDocumentController.cpp
+++ b/src/document/UBDocumentController.cpp
@@ -664,7 +664,7 @@ QMimeData *UBDocumentTreeModel::mimeData (const QModelIndexList &indexes) const
#if defined(Q_OS_OSX)
#if (QT_VERSION < QT_VERSION_CHECK(5, 15, 0))
- if (QOperatingSystemVersion::current().minorVersion() < 15) /* < Mojave */
+ if (QOperatingSystemVersion::current().majorVersion() == 10 && QOperatingSystemVersion::current().minorVersion() < 15) /* <= Mojave */
mimeData->setUrls(urlList);
#endif
#else
@@ -1034,6 +1034,16 @@ QString UBDocumentTreeModel::virtualPathForIndex(const QModelIndex &pIndex) cons
return virtualDirForIndex(pIndex) + "/" + curNode->nodeName();
}
+QList UBDocumentTreeModel::nodeChildrenFromIndex(const QModelIndex &pIndex) const
+{
+ UBDocumentTreeNode *node = nodeFromIndex(pIndex);
+
+ if (node)
+ return node->children();
+ else
+ return QList();
+}
+
QStringList UBDocumentTreeModel::nodeNameList(const QModelIndex &pIndex, bool distinctNodeType) const
{
QStringList result;
@@ -1331,6 +1341,7 @@ UBDocumentTreeView::UBDocumentTreeView(QWidget *parent) : QTreeView(parent)
{
setObjectName("UBDocumentTreeView");
setRootIsDecorated(true);
+ setSelectionBehavior(SelectRows);
}
void UBDocumentTreeView::setSelectedAndExpanded(const QModelIndex &pIndex, bool pExpand, bool pEdit)
@@ -1348,9 +1359,9 @@ void UBDocumentTreeView::setSelectedAndExpanded(const QModelIndex &pIndex, bool
? QItemSelectionModel::Select
: QItemSelectionModel::Deselect;
- setCurrentIndex(pExpand
- ? indexCurrentDoc
- : QModelIndex());
+ setCurrentIndex(indexCurrentDoc);
+
+ selectionModel()->setCurrentIndex(proxy->mapFromSource(indexCurrentDoc), QItemSelectionModel::SelectCurrent);
selectionModel()->select(proxy->mapFromSource(indexCurrentDoc), QItemSelectionModel::Rows | sel);
@@ -1359,7 +1370,7 @@ void UBDocumentTreeView::setSelectedAndExpanded(const QModelIndex &pIndex, bool
indexCurrentDoc = indexCurrentDoc.parent();
}
- scrollTo(proxy->mapFromSource(pIndex), QAbstractItemView::PositionAtCenter);
+ scrollTo(proxy->mapFromSource(pIndex));
if (pEdit)
edit(proxy->mapFromSource(pIndex));
@@ -1387,6 +1398,12 @@ void UBDocumentTreeView::hSliderRangeChanged(int min, int max)
}
}
+void UBDocumentTreeView::mousePressEvent(QMouseEvent *event)
+{
+ QTreeView::mousePressEvent(event);
+ UBApplication::documentController->clearThumbnailsSelection();
+}
+
void UBDocumentTreeView::dragEnterEvent(QDragEnterEvent *event)
{
QTreeView::dragEnterEvent(event);
@@ -1539,18 +1556,25 @@ void UBDocumentTreeView::dropEvent(QDropEvent *event)
Q_ASSERT(QFileInfo(thumbTmp).exists());
Q_ASSERT(QFileInfo(thumbTo).exists());
- const QPixmap *pix = new QPixmap(thumbTmp);
- UBDocumentController *ctrl = UBApplication::documentController;
- ctrl->addPixmapAt(pix, toIndex);
- ctrl->TreeViewSelectionChanged(ctrl->firstSelectedTreeIndex(), QModelIndex());
+
+ auto pix = std::make_shared(thumbTmp);
+ UBApplication::documentController->insertExistingThumbPage(toIndex, pix);
+ if (UBApplication::documentController->selectedDocument() == targetDocProxy)
+ {
+ UBApplication::documentController->reloadThumbnails();
+ }
+ if (UBApplication::boardController->selectedDocument() == targetDocProxy)
+ {
+ UBApplication::boardController->insertThumbPage(toIndex);
+ }
}
QApplication::restoreOverrideCursor();
- UBApplication::applicationController->showMessage(tr("%1 pages copied", "", total).arg(total), false);
docModel->setHighLighted(QModelIndex());
}
+ UBApplication::applicationController->showMessage(tr("%1 pages copied", "", total).arg(total), false);
}
else
{
@@ -1569,7 +1593,7 @@ void UBDocumentTreeView::dropEvent(QDropEvent *event)
QTreeView::dropEvent(event);
- UBApplication::documentController->updateActions();
+ UBApplication::documentController->pageSelectionChanged();
}
void UBDocumentTreeView::paintEvent(QPaintEvent *event)
@@ -1645,10 +1669,15 @@ UBDocumentTreeItemDelegate::UBDocumentTreeItemDelegate(QObject *parent)
void UBDocumentTreeItemDelegate::commitAndCloseEditor()
{
- QLineEdit *lineEditor = qobject_cast(sender());
- if (lineEditor) {
- emit commitData(lineEditor);
+ QLineEdit *lineEditor = dynamic_cast(sender());
+ if (lineEditor)
+ {
+ if (lineEditor->hasAcceptableInput())
+ {
+ emit commitData(lineEditor);
//emit closeEditor(lineEditor);
+ }
+
emit UBApplication::documentController->reorderDocumentsRequested();
}
}
@@ -1656,14 +1685,20 @@ void UBDocumentTreeItemDelegate::commitAndCloseEditor()
void UBDocumentTreeItemDelegate::processChangedText(const QString &str) const
{
QLineEdit *editor = qobject_cast(sender());
- if (!editor) {
- return;
- }
-
- if (!validateString(str)) {
- editor->setStyleSheet("background-color: #FFB3C8;");
- } else {
- editor->setStyleSheet("background-color: #FFFFFF;");
+ if (editor)
+ {
+ if (editor->validator())
+ {
+ int pos = 0;
+ if (editor->validator()->validate(const_cast(str), pos) != QValidator::Acceptable)
+ {
+ editor->setStyleSheet("background-color: #FFB3C8;");
+ }
+ else
+ {
+ editor->setStyleSheet("background-color: #FFFFFF;");
+ }
+ }
}
}
@@ -1678,16 +1713,41 @@ QWidget *UBDocumentTreeItemDelegate::createEditor(QWidget *parent, const QStyleO
//N/C - NNE - 20140407 : Add the test for the index column.
if(index.column() == 0){
mExistingFileNames.clear();
- const UBDocumentTreeModel *indexModel = qobject_cast(index.model());
- if (indexModel) {
- mExistingFileNames = indexModel->nodeNameList(index.parent());
- mExistingFileNames.removeOne(index.data().toString());
+ const UBDocumentTreeModel *docModel = 0;
+
+ const UBSortFilterProxyModel *proxy = dynamic_cast(index.model());
+
+ if(proxy){
+ docModel = dynamic_cast(proxy->sourceModel());
+ }else{
+ docModel = dynamic_cast(index.model());
}
- QLineEdit *nameEditor = new QLineEdit(parent);
- connect(nameEditor, SIGNAL(editingFinished()), this, SLOT(commitAndCloseEditor()));
- connect(nameEditor, SIGNAL(textChanged(QString)), this, SLOT(processChangedText(QString)));
- return nameEditor;
+ QModelIndex sourceIndex = proxy->mapToSource(index);
+
+ if (docModel)
+ {
+ mExistingFileNames = docModel->nodeNameList(sourceIndex.parent());
+ mExistingFileNames.removeOne(sourceIndex.data().toString());
+
+ UBDocumentTreeNode* sourceNode = docModel->nodeFromIndex(sourceIndex);
+
+ if (sourceNode)
+ {
+ QLineEdit *nameEditor = new QLineEdit(parent);
+ QList nodeChildren = docModel->nodeChildrenFromIndex(sourceIndex.parent());
+ nodeChildren.removeOne(sourceNode);
+
+ UBValidator* validator = new UBValidator(nodeChildren, sourceNode->nodeType());
+ nameEditor->setValidator(validator);
+ connect(nameEditor, SIGNAL(editingFinished()), this, SLOT(commitAndCloseEditor()));
+ connect(nameEditor, SIGNAL(textChanged(QString)), this, SLOT(processChangedText(QString)));
+
+ return nameEditor;
+ }
+ }
+
+ return nullptr;
}
//N/C - NNe - 20140407 : the other column are not editable.
@@ -1706,8 +1766,17 @@ void UBDocumentTreeItemDelegate::setEditorData(QWidget *editor, const QModelInde
void UBDocumentTreeItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
QLineEdit *lineEditor = qobject_cast(editor);
- if (validateString(lineEditor->text())) {
- model->setData(index, lineEditor->text());
+ if (lineEditor)
+ {
+ int pos;
+ QString input = lineEditor->text();
+ if (lineEditor->validator())
+ {
+ if (lineEditor->validator()->validate(input, pos) == QValidator::Acceptable)
+ {
+ model->setData(index, input);
+ }
+ }
}
}
@@ -1738,6 +1807,10 @@ UBDocumentController::UBDocumentController(UBMainWindow* mainWindow)
setupToolbar();
connect(this, SIGNAL(exportDone()), mMainWindow, SLOT(onExportDone()));
connect(this, SIGNAL(documentThumbnailsUpdated(UBDocumentContainer*)), this, SLOT(refreshDocumentThumbnailsView(UBDocumentContainer*)));
+ //connect(this, SIGNAL(documentPageInserted(int)), this, SLOT(insertThumbnail(int)));
+ connect(this, SIGNAL(documentPageUpdated(int)), this, SLOT(updateThumbnail(int)));
+ connect(this, SIGNAL(documentPageRemoved(int)), this, SLOT(removeThumbnail(int)));
+ connect(this, SIGNAL(documentPageMoved(int, int)), this, SLOT(moveThumbnail(int, int)));
connect(this, SIGNAL(reorderDocumentsRequested()), this, SLOT(reorderDocuments()));
}
@@ -1760,11 +1833,27 @@ void UBDocumentController::createNewDocument()
? docModel->virtualPathForIndex(selectedIndex)
: docModel->virtualDirForIndex(selectedIndex);
- UBDocumentProxy *document = pManager->createDocument(groupName);
+
+ QDateTime now = QDateTime::currentDateTime();
+ QString documentName = "";
+ if (docModel->isCatalog(selectedIndex))
+ {
+ documentName = docModel->adjustNameForParentIndex(now.toString(Qt::SystemLocaleShortDate), selectedIndex);
+ }
+ else
+ {
+ documentName = docModel->adjustNameForParentIndex(now.toString(Qt::SystemLocaleShortDate), selectedIndex.parent());
+ }
+
+
+ UBDocumentProxy *document = pManager->createDocument(groupName, documentName);
+
selectDocument(document, true, false, true);
if (document)
pManager->mDocumentTreeStructureModel->markDocumentAsNew(document);
+
+ pageSelectionChanged();
}
void UBDocumentController::selectDocument(UBDocumentProxy* proxy, bool setAsCurrentDocument, const bool onImport, const bool editMode)
@@ -1775,19 +1864,26 @@ void UBDocumentController::selectDocument(UBDocumentProxy* proxy, bool setAsCurr
return;
}
- if (setAsCurrentDocument) {
+ if (setAsCurrentDocument)
+ {
UBPersistenceManager::persistenceManager()->mDocumentTreeStructureModel->setCurrentDocument(proxy);
QModelIndex indexCurrentDoc = UBPersistenceManager::persistenceManager()->mDocumentTreeStructureModel->indexForProxy(proxy);
- mDocumentUI->documentTreeView->setSelectedAndExpanded(indexCurrentDoc, true, editMode);
+ if (indexCurrentDoc.isValid())
+ {
+ mDocumentUI->documentTreeView->setSelectedAndExpanded(indexCurrentDoc, true, editMode);
- if (proxy != mBoardController->selectedDocument()) // only if wanted Document is different from document actually on Board, // ALTI/AOU - 20140217
+ if (proxy != mBoardController->selectedDocument()) // only if wanted Document is different from document actually on Board, // ALTI/AOU - 20140217
+ {
+ //issue 1629 - NNE - 20131105 : When set a current document, change in the board controller
+ mBoardController->setActiveDocumentScene(proxy, 0, true, onImport);
+ }
+ }
+ else
{
- //issue 1629 - NNE - 20131105 : When set a current document, change in the board controller
- mBoardController->setActiveDocumentScene(proxy, 0, true, onImport);
+ qWarning() << "an issue occured while trying to select current index in document tree";
}
}
- mSelectionType = Document;
setDocument(proxy);
}
@@ -1807,6 +1903,8 @@ void UBDocumentController::createNewDocumentGroup()
QModelIndex newIndex = docModel->addCatalog(newFolderName, parentIndex);
mDocumentUI->documentTreeView->setSelectedAndExpanded(newIndex, true, true);
+
+ pageSelectionChanged();
}
@@ -1849,7 +1947,8 @@ void UBDocumentController::TreeViewSelectionChanged(const QModelIndex ¤t,
//We have just to pass a null proxy to disable the display of thumbnail
UBDocumentProxy *currentDocumentProxy = 0;
- if(current_index.isValid() && mDocumentUI->documentTreeView->selectionModel()->selectedRows(0).size() == 1){
+ if(current_index.isValid() && mDocumentUI->documentTreeView->selectionModel()->selectedRows(0).size() == 1)
+ {
currentDocumentProxy = docModel->proxyData(current_index);
setDocument(currentDocumentProxy, false);
}
@@ -1864,8 +1963,6 @@ void UBDocumentController::TreeViewSelectionChanged(const QModelIndex ¤t,
}
mCurrentIndexMoved = false;
}
-
- itemSelectionChanged(docModel->isCatalog(current_index) ? Folder : Document);
}
//N/C - NNE - 20140402 : workaround for using a proxy model
@@ -2093,11 +2190,6 @@ void UBDocumentController::setupViews()
connect(mDocumentUI->thumbnailWidget, SIGNAL(mouseDoubleClick(QGraphicsItem*,int)), this, SLOT(thumbnailPageDoubleClicked(QGraphicsItem*,int)));
connect(mDocumentUI->thumbnailWidget, SIGNAL(mouseClick(QGraphicsItem*, int)), this, SLOT(pageClicked(QGraphicsItem*, int)));
- connect(mDocumentUI->thumbnailWidget->scene(), SIGNAL(selectionChanged()), this, SLOT(pageSelectionChanged()));
-
- connect(UBPersistenceManager::persistenceManager(), SIGNAL(documentSceneCreated(UBDocumentProxy*, int)), this, SLOT(documentSceneChanged(UBDocumentProxy*, int)));
- connect(UBPersistenceManager::persistenceManager(), SIGNAL(documentSceneWillBeDeleted(UBDocumentProxy*, int)), this, SLOT(documentSceneChanged(UBDocumentProxy*, int)));
-
mDocumentUI->thumbnailWidget->setBackgroundBrush(UBSettings::documentViewLightColor);
#ifdef Q_WS_MACX
@@ -2161,8 +2253,9 @@ void UBDocumentController::sortDocuments(int kind, int order)
mDocumentUI->documentTreeView->hideColumn(2);
}
}
-}
+ mDocumentUI->documentTreeView->setSelectedAndExpanded(firstSelectedTreeIndex(), true);
+}
void UBDocumentController::onSortOrderChanged(bool order)
{
@@ -2222,10 +2315,9 @@ void UBDocumentController::show()
{
selectDocument(mBoardController->selectedDocument());
- //to be sure thumbnails will be up-to-date
- reloadThumbnails();
+ reorderDocuments();
- updateActions();
+ pageSelectionChanged();
if(!mToolsPalette)
setupPalettes();
@@ -2299,7 +2391,10 @@ void UBDocumentController::duplicateSelectedItem()
if (selectedSceneIndexes.count() > 0)
{
duplicatePages(selectedSceneIndexes);
- emit documentThumbnailsUpdated(this);
+ if (selectedDocument() == selectedDocumentProxy())
+ {
+ reloadThumbnails();
+ }
selectedDocument()->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime()));
UBMetadataDcSubsetAdaptor::persist(selectedDocument());
int selectedThumbnail = selectedSceneIndexes.last() + selectedSceneIndexes.size();
@@ -2307,8 +2402,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
@@ -2326,6 +2424,7 @@ void UBDocumentController::duplicateSelectedItem()
}
emit reorderDocumentsRequested();
+ pageSelectionChanged();
}
void UBDocumentController::deleteSelectedItem()
@@ -2346,7 +2445,7 @@ void UBDocumentController::deleteSelectedItem()
deleteSingleItem(indexes.at(0), docModel);
}
- updateActions();
+ pageSelectionChanged();
}
void UBDocumentController::deleteMultipleItems(QModelIndexList indexes, UBDocumentTreeModel* docModel)
@@ -2370,8 +2469,8 @@ void UBDocumentController::deleteMultipleItems(QModelIndexList indexes, UBDocume
for (int i =0; i < indexes.size(); i++)
{
deleteIndexAndAssociatedData(indexes.at(i));
- emit documentThumbnailsUpdated(this);
}
+ emit documentThumbnailsUpdated(this);
break;
}
case EmptyFolder:
@@ -2762,9 +2861,16 @@ void UBDocumentController::deleteIndexAndAssociatedData(const QModelIndex &pInde
}
//N/C - NNE - 20140408
- if(pIndex.column() == 0){
+ UBDocumentProxy *proxyData = nullptr;
+ if(pIndex.column() == 0)
+ {
if (docModel->isDocument(pIndex)) {
- UBDocumentProxy *proxyData = docModel->proxyData(pIndex);
+ proxyData = docModel->proxyData(pIndex);
+
+ if (selectedDocument() == proxyData)
+ {
+ setDocument(nullptr);
+ }
if (proxyData) {
UBPersistenceManager::persistenceManager()->deleteDocument(proxyData);
@@ -2772,7 +2878,25 @@ void UBDocumentController::deleteIndexAndAssociatedData(const QModelIndex &pInde
}
}
- docModel->removeRow(pIndex.row(), pIndex.parent());
+ if (proxyData)
+ {
+ // need to recall indexForProxy as rows could have changed when performing a multiple deletion
+ QModelIndex indexForProxy = docModel->indexForProxy(proxyData);
+ if (!docModel->removeRow(indexForProxy.row(), indexForProxy.parent()))
+ {
+ qDebug() << "could not remove row (r:" << indexForProxy.row() << "p:" << indexForProxy.parent() << ")";
+ }
+ }
+ else
+ {
+ if (docModel->isCatalog(pIndex))
+ {
+ if (!docModel->removeRow(pIndex.row(), pIndex.parent()))
+ {
+ qDebug() << "could not remove row (r:" << pIndex.row() << "p:" << pIndex.parent() << ")";
+ }
+ }
+ }
}
@@ -2846,6 +2970,7 @@ void UBDocumentController::importFile()
if (createdDocument) {
selectDocument(createdDocument, true, true, true);
+ pageSelectionChanged();
} else {
showMessage(tr("Failed to import file ... "));
@@ -2888,6 +3013,10 @@ void UBDocumentController::addFolderOfImages()
document->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime()));
UBMetadataDcSubsetAdaptor::persist(document);
reloadThumbnails();
+ if (selectedDocument() == UBApplication::boardController->selectedDocument())
+ UBApplication::boardController->reloadThumbnails();
+
+ pageSelectionChanged();
}
}
}
@@ -2901,7 +3030,6 @@ void UBDocumentController::addFileToDocument()
if (document)
{
addFileToDocument(document);
- reloadThumbnails();
}
}
@@ -2934,6 +3062,11 @@ 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();
+
+ pageSelectionChanged();
}
else
{
@@ -2949,19 +3082,46 @@ bool UBDocumentController::addFileToDocument(UBDocumentProxy* document)
void UBDocumentController::moveSceneToIndex(UBDocumentProxy* proxy, int source, int target)
{
- if (UBDocumentContainer::movePageToIndex(source, target))
- {
- proxy->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime()));
- UBMetadataDcSubsetAdaptor::persist(proxy);
+ UBPersistenceManager::persistenceManager()->moveSceneToIndex(proxy, source, target);
- mDocumentUI->thumbnailWidget->hightlightItem(target);
+ proxy->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime()));
+ UBMetadataDcSubsetAdaptor::persist(proxy);
- mBoardController->setActiveDocumentScene(target);
- mBoardController->reloadThumbnails();
+ UBDocumentContainer::moveThumbPage(source, target);
+ if (UBApplication::boardController->selectedDocument() == selectedDocument())
+ {
+ UBApplication::boardController->moveThumbPage(source, target);
}
+ mDocumentUI->thumbnailWidget->hightlightItem(target);
+
+ //mBoardController->setActiveDocumentScene(target);
+}
+
+void UBDocumentController::insertThumbnail(int index, const QPixmap& pix)
+{
+ QGraphicsPixmapItem *newThumbnail = new UBSceneThumbnailPixmap(pix, selectedDocument(), index); // deleted by the tree widget
+
+ mDocumentUI->thumbnailWidget->insertThumbnail(index, newThumbnail);
+}
+
+void UBDocumentController::updateThumbnail(int index)
+{
+ auto pix = UBApplication::boardController->pageAt(index);
+
+ mDocumentUI->thumbnailWidget->updateThumbnailPixmap(index, *pix);
}
+void UBDocumentController::removeThumbnail(int index)
+{
+ mDocumentUI->thumbnailWidget->removeThumbnail(index);
+}
+
+void UBDocumentController::moveThumbnail(int from, int to)
+{
+ mDocumentUI->thumbnailWidget->moveThumbnail(from, to);
+}
+
void UBDocumentController::thumbnailViewResized()
{
int maxWidth = qMin(UBSettings::maxThumbnailWidth, mDocumentUI->thumbnailWidget->width());
@@ -2989,19 +3149,12 @@ void UBDocumentController::pageSelectionChanged()
itemSelectionChanged(Folder);
else
itemSelectionChanged(None);
-
- updateActions();
}
void UBDocumentController::documentSceneChanged(UBDocumentProxy* proxy, int pSceneIndex)
{
Q_UNUSED(pSceneIndex);
- if (proxy == selectedDocumentProxy())
- {
- reloadThumbnails();
- }
-
QModelIndexList sel = mDocumentUI->documentTreeView->selectionModel()->selectedRows(0);
QModelIndex selection;
@@ -3082,7 +3235,6 @@ void UBDocumentController::addToDocument()
UBMetadataDcSubsetAdaptor::persist(mBoardController->selectedDocument());
mBoardController->reloadThumbnails();
- emit UBApplication::boardController->documentThumbnailsUpdated(this);
UBApplication::applicationController->showBoard();
mBoardController->setActiveDocumentScene(newActiveSceneIndex);
@@ -3191,6 +3343,10 @@ void UBDocumentController::addImages()
document->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime()));
UBMetadataDcSubsetAdaptor::persist(document);
reloadThumbnails();
+ if (selectedDocument() == UBApplication::boardController->selectedDocument())
+ UBApplication::boardController->reloadThumbnails();
+
+ pageSelectionChanged();
}
}
}
@@ -3260,16 +3416,6 @@ void UBDocumentController::focusChanged(QWidget *old, QWidget *current)
else
mSelectionType = None;
}
- else
- {
- if (old != mDocumentUI->thumbnailWidget &&
- old != mDocumentUI->documentTreeView &&
- old != mDocumentUI->documentZoomSlider)
- {
- if (current && (current->metaObject()->className() != QPushButton::staticMetaObject.className()))
- mSelectionType = None;
- }
- }
}
void UBDocumentController::updateActions()
@@ -3335,6 +3481,7 @@ void UBDocumentController::updateActions()
updateExportSubActions(selectedIndex);
bool firstSceneSelected = false;
+ bool everyPageSelected = false;
if (docSelected) {
mMainWindow->actionDuplicate->setEnabled(!trashSelected);
@@ -3372,22 +3519,77 @@ void UBDocumentController::updateActions()
switch (static_cast(deletionForSelection)) {
case MoveToTrash :
+ if (mSelectionType == Folder)
+ {
+ mMainWindow->actionDelete->setIcon(QIcon(":/images/trash-folder.png"));
+ mMainWindow->actionDelete->setText(tr("Delete"));
+ }
+ else if (mSelectionType == Document)
+ {
+ mMainWindow->actionDelete->setIcon(QIcon(":/images/trash-document.png"));
+ mMainWindow->actionDelete->setText(tr("Trash"));
+ }
+ else if (mSelectionType == Page)
+ {
+ mMainWindow->actionDelete->setIcon(QIcon(":/images/trash-document-page.png"));
+ mMainWindow->actionDelete->setText(tr("Trash"));
+ }
+ else
+ {//can happen ?
+ mMainWindow->actionDelete->setIcon(QIcon(":/images/trash.png"));
+ mMainWindow->actionDelete->setText(tr("Trash"));
+ }
+ break;
case DeletePage :
- mMainWindow->actionDelete->setIcon(QIcon(":/images/trash.png"));
+ mMainWindow->actionDelete->setIcon(QIcon(":/images/trash-document-page.png"));
mMainWindow->actionDelete->setText(tr("Trash"));
break;
case CompleteDelete :
- mMainWindow->actionDelete->setIcon(QIcon(":/images/toolbar/deleteDocument.png"));
- mMainWindow->actionDelete->setText(tr("Delete"));
+ if (mSelectionType == Folder)
+ {
+ mMainWindow->actionDelete->setIcon(QIcon(":/images/trash-delete-folder.png"));
+ mMainWindow->actionDelete->setText(tr("Delete"));
+ }
+ else
+ {
+ mMainWindow->actionDelete->setIcon(QIcon(":/images/trash-delete-document.png"));
+ mMainWindow->actionDelete->setText(tr("Delete"));
+ }
break;
case EmptyFolder :
- mMainWindow->actionDelete->setIcon(QIcon(":/images/trash.png"));
- mMainWindow->actionDelete->setText(tr("Empty"));
+ if (firstSelectedTreeIndex() == docModel->myDocumentsIndex())
+ {
+ mMainWindow->actionDelete->setIcon(QIcon(":/images/trash-my-documents.png"));
+ mMainWindow->actionDelete->setText(tr("Empty"));
+ }
+ else
+ {
+ mMainWindow->actionDelete->setIcon(QIcon(":/images/trash-folder.png"));
+ mMainWindow->actionDelete->setText(tr("Delete"));
+ }
break;
case EmptyTrash :
- mMainWindow->actionDelete->setIcon(QIcon(":/images/toolbar/deleteDocument.png"));
+ mMainWindow->actionDelete->setIcon(QIcon(":/images/trash-empty.png"));
mMainWindow->actionDelete->setText(tr("Empty"));
break;
+ case NoDeletion :
+ default:
+ if (mSelectionType == Folder)
+ {
+ mMainWindow->actionDelete->setIcon(QIcon(":/images/trash-delete-folder.png"));
+ mMainWindow->actionDelete->setText(tr("Delete"));
+ }
+ else if (mSelectionType == Document)
+ {
+ mMainWindow->actionDelete->setIcon(QIcon(":/images/trash-delete-document.png"));
+ mMainWindow->actionDelete->setText(tr("Delete"));
+ }
+ else if (mSelectionType == Page)
+ {
+ mMainWindow->actionDelete->setIcon(QIcon(":/images/trash-document-page.png"));
+ mMainWindow->actionDelete->setText(tr("Delete"));
+ }
+ break;
}
mMainWindow->actionDocumentAdd->setEnabled((docSelected || pageSelected) && !trashSelected);
@@ -3445,7 +3647,12 @@ void UBDocumentController::deletePages(QList itemsToDelete)
}
}
UBDocumentContainer::deletePages(sceneIndexes);
- emit UBApplication::boardController->documentThumbnailsUpdated(this);
+ if (mBoardController->selectedDocument() == selectedDocument())
+ {
+ std::sort(sceneIndexes.begin(), sceneIndexes.end(), std::greater<>());
+ for (auto index : sceneIndexes)
+ mBoardController->deleteThumbPage(index);
+ }
proxy->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime()));
UBMetadataDcSubsetAdaptor::persist(proxy);
@@ -3462,7 +3669,6 @@ void UBDocumentController::deletePages(QList itemsToDelete)
mDocumentUI->thumbnailWidget->selectItemAt(minIndex);
mBoardController->setActiveDocumentScene(minIndex);
- mBoardController->reloadThumbnails();
}
}
@@ -3514,7 +3720,12 @@ UBDocumentController::deletionTypeForSelection(LastSelectedElementType pTypeSele
, UBDocumentTreeModel *docModel) const
{
- if (pTypeSelection == Page) {
+ if (pTypeSelection == Page)
+ {
+ if (everySceneSelected())
+ {
+ return NoDeletion;
+ }
if (!firstAndOnlySceneSelected()) {
return DeletePage;
}
@@ -3541,11 +3752,24 @@ UBDocumentController::deletionTypeForSelection(LastSelectedElementType pTypeSele
return NoDeletion;
}
+bool UBDocumentController::everySceneSelected() const
+{
+ QList selection = mDocumentUI->thumbnailWidget->selectedItems();
+ if (selection.count() > 0)
+ {
+ UBSceneThumbnailPixmap* p = dynamic_cast(selection.at(0));
+ if (p)
+ {
+ return (selection.count() == p->proxy()->pageCount());
+ }
+ }
+ return false;
+}
+
bool UBDocumentController::firstAndOnlySceneSelected() const
{
- bool firstSceneSelected = false;
QList selection = mDocumentUI->thumbnailWidget->selectedItems();
- for(int i = 0; i < selection.count() && !firstSceneSelected; i += 1)
+ for(int i = 0; i < selection.count(); i += 1)
{
UBSceneThumbnailPixmap* p = dynamic_cast(selection.at(i));
if (p)
@@ -3568,7 +3792,7 @@ bool UBDocumentController::firstAndOnlySceneSelected() const
return false;
}
-void UBDocumentController:: refreshDocumentThumbnailsView(UBDocumentContainer*)
+void UBDocumentController:: refreshDocumentThumbnailsView(UBDocumentContainer* source)
{
UBDocumentTreeModel *docModel = UBPersistenceManager::persistenceManager()->mDocumentTreeStructureModel;
UBDocumentProxy *currentDocumentProxy = selectedDocument();
@@ -3581,14 +3805,14 @@ void UBDocumentController:: refreshDocumentThumbnailsView(UBDocumentContainer*)
, QList()
, QStringList()
, UBApplication::mimeTypeUniboardPage);
+
+ QApplication::restoreOverrideCursor();
return;
}
- QList thumbs;
-
if (currentDocumentProxy)
{
- UBThumbnailAdaptor::load(currentDocumentProxy, thumbs);
+ UBThumbnailAdaptor::load(currentDocumentProxy, documentThumbs());
}
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
@@ -3604,7 +3828,9 @@ void UBDocumentController:: refreshDocumentThumbnailsView(UBDocumentContainer*)
{
for (int i = 0; i < currentDocumentProxy->pageCount(); i++)
{
- const QPixmap* pix = thumbs.at(i);
+ UBApplication::showMessage(tr("Refreshing Document Thumbnails View (%1/%2)").arg(i+1).arg(source->selectedDocument()->pageCount()));
+
+ auto pix = documentThumbs().at(i);
QGraphicsPixmapItem *pixmapItem = new UBSceneThumbnailPixmap(*pix, currentDocumentProxy, i); // deleted by the tree widget
if (currentDocumentProxy == mBoardController->selectedDocument() && mBoardController->activeSceneIndex() == i)
@@ -3635,11 +3861,9 @@ void UBDocumentController:: refreshDocumentThumbnailsView(UBDocumentContainer*)
if (selection)
{
- disconnect(mDocumentUI->thumbnailWidget->scene(), SIGNAL(selectionChanged()), this, SLOT(pageSelectionChanged()));
- UBSceneThumbnailPixmap *currentScene = dynamic_cast(selection);
- if (currentScene)
- mDocumentUI->thumbnailWidget->hightlightItem(currentScene->sceneIndex());
- connect(mDocumentUI->thumbnailWidget->scene(), SIGNAL(selectionChanged()), this, SLOT(pageSelectionChanged()));
+ UBSceneThumbnailPixmap *currentSceneThumbnailPixmap = dynamic_cast(selection);
+ if (currentSceneThumbnailPixmap)
+ mDocumentUI->thumbnailWidget->hightlightItem(currentSceneThumbnailPixmap->sceneIndex());
}
QApplication::restoreOverrideCursor();
@@ -3657,6 +3881,8 @@ void UBDocumentController::createNewDocumentInUntitledFolder()
if (document)
pManager->mDocumentTreeStructureModel->markDocumentAsNew(document);
+
+ pageSelectionChanged();
}
void UBDocumentController::collapseAll()
@@ -3692,3 +3918,9 @@ void UBDocumentController::expandAll()
mDocumentUI->documentTreeView->setAnimated(true);
}
+
+void UBDocumentController::clearThumbnailsSelection()
+{
+ mDocumentUI->thumbnailWidget->clearSelection();
+ pageSelectionChanged();
+}
diff --git a/src/document/UBDocumentController.h b/src/document/UBDocumentController.h
index a67908be..03c76e92 100644
--- a/src/document/UBDocumentController.h
+++ b/src/document/UBDocumentController.h
@@ -210,6 +210,7 @@ public:
QString virtualDirForIndex(const QModelIndex &pIndex) const;
QString virtualPathForIndex(const QModelIndex &pIndex) const;
QStringList nodeNameList(const QModelIndex &pIndex, bool distinctNodeType = false) const;
+ QList nodeChildrenFromIndex(const QModelIndex &pIndex) const;
bool newNodeAllowed(const QModelIndex &pSelectedIndex) const;
QModelIndex goTo(const QString &dir);
bool inTrash(const QModelIndex &index) const;
@@ -305,6 +306,7 @@ public slots:
void hSliderRangeChanged(int min, int max);
protected:
+ void mousePressEvent(QMouseEvent *event) override;
void dragEnterEvent(QDragEnterEvent *event);
void dragLeaveEvent(QDragLeaveEvent *event);
void dragMoveEvent(QDragMoveEvent *event);
@@ -321,6 +323,32 @@ private:
void updateIndexEnvirons(const QModelIndex &index);
};
+class UBValidator : public QValidator
+{
+ const QList mExistingNodes;
+ UBDocumentTreeNode::Type mEditedNodeType;
+
+ public:
+ UBValidator(const QList existingNodes, UBDocumentTreeNode::Type editedNodeType, QObject *parent = nullptr)
+ : QValidator(parent)
+ , mExistingNodes(existingNodes)
+ , mEditedNodeType(editedNodeType)
+ {
+
+ }
+
+ QValidator::State validate(QString &input, int &pos) const
+ {
+ for (auto node : mExistingNodes)
+ {
+ if (node->nodeName() == input && node->nodeType() == mEditedNodeType)
+ return QValidator::Intermediate;
+ }
+
+ return QValidator::Acceptable;
+ }
+};
+
class UBDocumentTreeItemDelegate : public QStyledItemDelegate
{
Q_OBJECT
@@ -401,6 +429,7 @@ class UBDocumentController : public UBDocumentContainer
, const QModelIndex &selectedIndex
, UBDocumentTreeModel *docModel) const;
bool firstAndOnlySceneSelected() const;
+ bool everySceneSelected() const;
QWidget *mainWidget() const {return mDocumentWidget;}
//issue 1629 - NNE - 20131212
@@ -429,6 +458,8 @@ class UBDocumentController : public UBDocumentContainer
QModelIndex findNextSiblingNotSelected(const QModelIndex &index, QItemSelectionModel *selectionModel);
bool parentIsSelected(const QModelIndex& child, QItemSelectionModel *selectionModel);
+ void clearThumbnailsSelection();
+
signals:
void exportDone();
void reorderDocumentsRequested();
@@ -461,7 +492,6 @@ class UBDocumentController : public UBDocumentContainer
void copy();
void paste();
void focusChanged(QWidget *old, QWidget *current);
- void updateActions();
void updateExportSubActions(const QModelIndex &selectedIndex);
void currentIndexMoved(const QModelIndex &newIndex, const QModelIndex &PreviousIndex);
@@ -472,6 +502,11 @@ class UBDocumentController : public UBDocumentContainer
void collapseAll();
void expandAll();
+ void updateThumbnail(int index);
+ void removeThumbnail(int index);
+ void moveThumbnail(int from, int to);
+ void insertThumbnail(int index, const QPixmap& pix);
+
protected:
virtual void setupViews();
virtual void setupToolbar();
@@ -515,6 +550,8 @@ protected:
void TreeViewSelectionChanged(const QModelIndex ¤t, const QModelIndex &previous);
void TreeViewSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
+ void pageSelectionChanged();
+
private slots:
void documentZoomSliderValueChanged (int value);
void itemSelectionChanged(LastSelectedElementType newSelection);
@@ -522,7 +559,7 @@ protected:
void exportDocumentSet();
void thumbnailViewResized();
- void pageSelectionChanged();
+ void updateActions();
void documentSceneChanged(UBDocumentProxy* proxy, int pSceneIndex);
diff --git a/src/document/UBDocumentProxy.cpp b/src/document/UBDocumentProxy.cpp
index 0bf6e565..6f9aa711 100644
--- a/src/document/UBDocumentProxy.cpp
+++ b/src/document/UBDocumentProxy.cpp
@@ -56,6 +56,7 @@ UBDocumentProxy::UBDocumentProxy(const UBDocumentProxy &rValue) :
mPageCount = rValue.mPageCount;
}
+
UBDocumentProxy::UBDocumentProxy(const QString& pPersistancePath)
: mPageCount(0)
, mPageDpi(0)
@@ -67,17 +68,6 @@ UBDocumentProxy::UBDocumentProxy(const QString& pPersistancePath)
}
-UBDocumentProxy::UBDocumentProxy(const QString& pPersistancePath, QMap metadatas)
- : mPageCount(0)
- , mPageDpi(0)
-{
- init();
- setPersistencePath(pPersistancePath);
-
- mMetaDatas = metadatas;
-}
-
-
void UBDocumentProxy::init()
{
setMetaData(UBSettings::documentGroupName, "");
diff --git a/src/document/UBDocumentProxy.h b/src/document/UBDocumentProxy.h
index dfff6908..cb507dec 100644
--- a/src/document/UBDocumentProxy.h
+++ b/src/document/UBDocumentProxy.h
@@ -49,7 +49,6 @@ class UBDocumentProxy : public QObject
UBDocumentProxy();
UBDocumentProxy(const UBDocumentProxy &rValue);
UBDocumentProxy(const QString& pPersistencePath);
- UBDocumentProxy(const QString& pPersistencePath, QMap metadatas);
virtual ~UBDocumentProxy();
diff --git a/src/domain/UBGraphicsDelegateFrame.cpp b/src/domain/UBGraphicsDelegateFrame.cpp
index 36334510..e0970eb5 100644
--- a/src/domain/UBGraphicsDelegateFrame.cpp
+++ b/src/domain/UBGraphicsDelegateFrame.cpp
@@ -103,11 +103,10 @@ UBGraphicsDelegateFrame::UBGraphicsDelegateFrame(UBGraphicsItemDelegate* pDelega
mRotateButton->setCursor(UBResources::resources()->rotateCursor);
mRotateButton->setVisible(mDelegate->testUBFlags(GF_REVOLVABLE));
- updateResizeCursors();
-
setAntiScale(1.0);
positionHandles();
+ updateResizeCursors();
this->setAcceptHoverEvents(true);
}
@@ -839,6 +838,7 @@ void UBGraphicsDelegateFrame::positionHandles()
resetTransform();
setTransform(QTransform::fromTranslate(center.x(), center.y()), true);
setTransform(QTransform().rotate(-angle), true);
+ mAngle = angle;
setTransform(QTransform::fromTranslate(-center.x(), -center.y()), true);
//TODO: combine these transforms into one
diff --git a/src/domain/UBGraphicsItemDelegate.cpp b/src/domain/UBGraphicsItemDelegate.cpp
index bb19e2ca..458f0115 100644
--- a/src/domain/UBGraphicsItemDelegate.cpp
+++ b/src/domain/UBGraphicsItemDelegate.cpp
@@ -328,12 +328,15 @@ void UBGraphicsItemDelegate::postpaint(QPainter *painter, const QStyleOptionGrap
{
Q_UNUSED(widget)
if (option->state & QStyle::State_Selected && !controlsExist()) {
- painter->save();
- painter->setPen(Qt::NoPen);
- painter->setBrush(QColor(0x88, 0x88, 0x88, 0x77));
- painter->drawRect(option->rect);
+ if (UBStylusTool::Play != UBDrawingController::drawingController()->stylusTool())
+ {
+ painter->save();
+ painter->setPen(Qt::NoPen);
+ painter->setBrush(QColor(0x88, 0x88, 0x88, 0x77));
+ painter->drawRect(option->rect);
- painter->restore();
+ painter->restore();
+ }
}
}
@@ -1304,7 +1307,7 @@ void MediaTimer::setNumDigits(int numDigits)
} else {
if (numDigits == ndigits) // no change
return;
- register int i;
+ int i;
int dif;
if (numDigits > ndigits) { // expand
dif = numDigits - ndigits;
diff --git a/src/domain/UBGraphicsItemUndoCommand.cpp b/src/domain/UBGraphicsItemUndoCommand.cpp
index 7653a054..8ad68b22 100644
--- a/src/domain/UBGraphicsItemUndoCommand.cpp
+++ b/src/domain/UBGraphicsItemUndoCommand.cpp
@@ -128,7 +128,7 @@ void UBGraphicsItemUndoCommand::undo()
QGraphicsItem* item = itRemoved.next();
if (item)
{
- if (UBItemLayerType::FixedBackground == item->data(UBGraphicsItemData::ItemLayerType))
+ if (itemLayerType::BackgroundItem == item->data(UBGraphicsItemData::itemLayerType))
mScene->setAsBackgroundObject(item);
else
mScene->addItem(item);
@@ -246,7 +246,11 @@ void UBGraphicsItemUndoCommand::redo()
polygonItem->strokesGroup()->removeFromGroup(polygonItem);
}
- mScene->removeItem(item);
+
+ if (itemLayerType::BackgroundItem == item->data(UBGraphicsItemData::itemLayerType))
+ mScene->setAsBackgroundObject(nullptr);
+ else
+ mScene->removeItem(item);
if (bApplyTransform)
item->setTransform(t);
diff --git a/src/domain/UBGraphicsMediaItem.cpp b/src/domain/UBGraphicsMediaItem.cpp
index 47b025cb..8ec7da2e 100644
--- a/src/domain/UBGraphicsMediaItem.cpp
+++ b/src/domain/UBGraphicsMediaItem.cpp
@@ -68,6 +68,7 @@ UBGraphicsMediaItem::UBGraphicsMediaItem(const QUrl& pMediaFileUrl, QGraphicsIte
, mMuted(sIsMutedByDefault)
, mMutedByUserAction(sIsMutedByDefault)
, mStopped(false)
+ , mFirstLoad(true)
, mMediaFileUrl(pMediaFileUrl)
, mLinkedImage(NULL)
, mInitialPos(0)
@@ -135,8 +136,8 @@ UBGraphicsVideoItem::UBGraphicsVideoItem(const QUrl &pMediaFileUrl, QGraphicsIte
* 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->setVideoOutput(mVideoItem);
+ mHasVideoOutput = true;
mMediaObject->setNotifyInterval(50);
@@ -175,12 +176,12 @@ QVariant UBGraphicsMediaItem::itemChange(GraphicsItemChange change, const QVaria
|| (change == QGraphicsItem::ItemVisibleChange))
{
if (mMediaObject && (!isEnabled() || !isVisible() || !scene()))
- mMediaObject->pause();
+ pause();
}
else if (change == QGraphicsItem::ItemSceneHasChanged)
{
if (!scene())
- mMediaObject->stop();
+ stop();
else {
QString absoluteMediaFilename;
@@ -225,6 +226,16 @@ bool UBGraphicsMediaItem::isStopped() const
return mStopped;
}
+bool UBGraphicsMediaItem::firstLoad() const
+{
+ return mFirstLoad;
+}
+
+void UBGraphicsMediaItem::setFirstLoad(bool firstLoad)
+{
+ mFirstLoad = firstLoad;
+}
+
qint64 UBGraphicsMediaItem::mediaDuration() const
{
return mMediaObject->duration();
@@ -333,7 +344,7 @@ UBGraphicsScene* UBGraphicsMediaItem::scene()
void UBGraphicsMediaItem::activeSceneChanged()
{
if (UBApplication::boardController->activeScene() != scene())
- mMediaObject->pause();
+ pause();
}
@@ -374,17 +385,19 @@ void UBGraphicsMediaItem::togglePlayPause()
}
if (mMediaObject->state() == QMediaPlayer::StoppedState)
- mMediaObject->play();
+ {
+ play();
+ }
else if (mMediaObject->state() == QMediaPlayer::PlayingState) {
if ((mMediaObject->duration() - mMediaObject->position()) <= 0) {
- mMediaObject->stop();
- mMediaObject->play();
+ stop();
+ play();
}
else {
- mMediaObject->pause();
+ pause();
if(scene())
scene()->setModified(true);
}
@@ -392,14 +405,14 @@ void UBGraphicsMediaItem::togglePlayPause()
else if (mMediaObject->state() == QMediaPlayer::PausedState) {
if ((mMediaObject->duration() - mMediaObject->position()) <= 0)
- mMediaObject->stop();
+ stop();
- mMediaObject->play();
+ play();
}
else if ( mMediaObject->mediaStatus() == QMediaPlayer::LoadingMedia) {
mMediaObject->setMedia(mediaFileUrl());
- mMediaObject->play();
+ play();
}
}
@@ -427,6 +440,7 @@ void UBGraphicsMediaItem::mediaError(QMediaPlayer::Error errorCode)
if (!mErrorString.isEmpty() ) {
UBApplication::showMessage(mErrorString);
qDebug() << mErrorString;
+ mErrorString.clear();
}
}
diff --git a/src/domain/UBGraphicsMediaItem.h b/src/domain/UBGraphicsMediaItem.h
index 5f2ba757..5ec5eb08 100644
--- a/src/domain/UBGraphicsMediaItem.h
+++ b/src/domain/UBGraphicsMediaItem.h
@@ -88,6 +88,8 @@ public:
bool isPlaying() const { return (mMediaObject->state() == QMediaPlayer::PlayingState); }
bool isPaused() const { return (mMediaObject->state() == QMediaPlayer::PausedState); }
bool isStopped() const;
+ bool firstLoad() const;
+ void setFirstLoad(bool firstLoad);
QRectF boundingRect() const;
@@ -140,6 +142,7 @@ protected:
bool mMutedByUserAction;
static bool sIsMutedByDefault;
bool mStopped;
+ bool mFirstLoad;
QUrl mMediaFileUrl;
QString mMediaSource;
diff --git a/src/domain/UBGraphicsMediaItemDelegate.cpp b/src/domain/UBGraphicsMediaItemDelegate.cpp
index 4ab1a298..c510a59d 100644
--- a/src/domain/UBGraphicsMediaItemDelegate.cpp
+++ b/src/domain/UBGraphicsMediaItemDelegate.cpp
@@ -242,17 +242,26 @@ void UBGraphicsMediaItemDelegate::mediaStatusChanged(QMediaPlayer::MediaStatus s
if (status == QMediaPlayer::LoadedMedia)
mMediaControl->totalTimeChanged(delegated()->mediaDuration());
- // At the beginning of the video, play/pause to load and display the first frame
+ // At the beginning of the video, play/pause to load and display the first frame (not working on OSX)
+#ifndef Q_OS_OSX
if ((status == QMediaPlayer::LoadedMedia || status == QMediaPlayer::BufferedMedia)
&& delegated()->mediaPosition() == delegated()->initialPos()
- && !delegated()->isStopped()) {
+ && !delegated()->isStopped()
+ && delegated()->firstLoad()
+ )
+ {
delegated()->play();
delegated()->pause();
+ delegated()->setFirstLoad(false);
}
+#endif
// At the end of the video, make sure the progress bar doesn't autohide
if (status == QMediaPlayer::EndOfMedia)
+ {
+ delegated()->setFirstLoad(true);
showToolBar(false);
+ }
// in most cases, the only necessary action is to update the play/pause state
@@ -265,6 +274,9 @@ void UBGraphicsMediaItemDelegate::mediaStateChanged(QMediaPlayer::State state)
// Possible states are StoppedState, PlayingState and PausedState
// updatePlayPauseState handles this functionality
+ if (state == QMediaPlayer::StoppedState)
+ delegated()->setMediaPos(0);
+
updatePlayPauseState();
}
@@ -280,8 +292,11 @@ void UBGraphicsMediaItemDelegate::updatePlayPauseState()
void UBGraphicsMediaItemDelegate::updateTicker(qint64 time)
{
- mMediaControl->totalTimeChanged(delegated()->mediaDuration());
- mMediaControl->updateTicker(time);
+ if (!delegated()->isStopped())
+ {
+ mMediaControl->totalTimeChanged(delegated()->mediaDuration());
+ mMediaControl->updateTicker(time);
+ }
}
diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp
index 327b43c2..1f82c089 100644
--- a/src/domain/UBGraphicsScene.cpp
+++ b/src/domain/UBGraphicsScene.cpp
@@ -840,6 +840,8 @@ void UBGraphicsScene::drawMarkerCircle(const QPointF &pPoint)
void UBGraphicsScene::drawPenCircle(const QPointF &pPoint)
{
+ QCursor cursor;
+
if (mPenCircle && UBSettings::settings()->showPenPreviewCircle->get().toBool() &&
UBSettings::settings()->currentPenWidth() >= UBSettings::settings()->penPreviewFromSize->get().toInt()) {
qreal penDiameter = UBSettings::settings()->currentPenWidth();
@@ -849,20 +851,20 @@ void UBGraphicsScene::drawPenCircle(const QPointF &pPoint)
mPenCircle->setRect(QRectF(pPoint.x() - penRadius, pPoint.y() - penRadius,
penDiameter, penDiameter));
-
- if (controlView())
- if (controlView()->viewport())
- controlView()->viewport()->setCursor(QCursor (Qt::BlankCursor));
-
mPenCircle->show();
+ cursor = Qt::BlankCursor;
}
else
{
- if (controlView())
- if (controlView()->viewport())
- controlView()->viewport()->setCursor(UBResources::resources()->penCursor);
+ cursor = UBResources::resources()->penCursor;
}
+ if (!UBDrawingController::drawingController()->mActiveRuler)
+ {
+ // set cursor only if no active ruler
+ if (controlView() && controlView()->viewport())
+ controlView()->viewport()->setCursor(cursor);
+ }
}
void UBGraphicsScene::hideMarkerCircle()
@@ -1335,9 +1337,12 @@ void UBGraphicsScene::updateSelectionFrame()
mSelectionFrame->setEnclosedItems(QList());
UBGraphicsItemDelegate *itemDelegate = UBGraphicsItem::Delegate(selItems.first());
- itemDelegate->createControls();
- selItems.first()->setVisible(true);
- itemDelegate->showControls();
+ if (itemDelegate)
+ {
+ itemDelegate->createControls();
+ selItems.first()->setVisible(true);
+ itemDelegate->showControls();
+ }
} break;
default: {
@@ -1473,6 +1478,7 @@ void UBGraphicsScene::clearContent(clearCase pCase)
if(mBackgroundObject){
removeItem(mBackgroundObject);
removedItems << mBackgroundObject;
+ mBackgroundObject = nullptr;
}
break;
@@ -1930,9 +1936,12 @@ UBGraphicsTextItem* UBGraphicsScene::addTextWithFont(const QString& pString, con
UBGraphicsTextItem *UBGraphicsScene::addTextHtml(const QString &pString, const QPointF& pTopLeft)
{
UBGraphicsTextItem *textItem = new UBGraphicsTextItem();
+
textItem->setPlainText("");
textItem->setHtml(UBTextTools::cleanHtml(pString));
+ textItem->initFontProperties();
+
addItem(textItem);
textItem->show();
@@ -2377,6 +2386,9 @@ void UBGraphicsScene::changeMagnifierMode(int mode)
{
if(magniferControlViewWidget)
magniferControlViewWidget->setDrawingMode(mode);
+
+ if(magniferDisplayViewWidget)
+ magniferDisplayViewWidget->setDrawingMode(mode);
}
void UBGraphicsScene::resizedMagnifier(qreal newPercent)
@@ -2463,9 +2475,53 @@ void UBGraphicsScene::setRenderingQuality(UBItem::RenderingQuality pRenderingQua
}
}
+QList UBGraphicsScene::relativeDependenciesOfItem(QGraphicsItem* item) const
+{
+ QList relativePaths;
+
+ UBGraphicsVideoItem *videoItem = dynamic_cast (item);
+ if (videoItem){
+ QString completeFileName = QFileInfo(videoItem->mediaFileUrl().toLocalFile()).fileName();
+ QString path = UBPersistenceManager::videoDirectory + "/";
+ relativePaths << QUrl(path + completeFileName);
+ return relativePaths;
+ }
+
+ UBGraphicsAudioItem *audioItem = dynamic_cast (item);
+ if (audioItem){
+ QString completeFileName = QFileInfo(audioItem->mediaFileUrl().toLocalFile()).fileName();
+ QString path = UBPersistenceManager::audioDirectory + "/";
+ relativePaths << QUrl(path + completeFileName);
+ return relativePaths;
+ }
+
+ UBGraphicsWidgetItem* widget = dynamic_cast(item);
+ if(widget){
+ QString widgetPath = UBPersistenceManager::widgetDirectory + "/" + widget->uuid().toString() + ".wgt";
+ QString screenshotPath = UBPersistenceManager::widgetDirectory + "/" + widget->uuid().toString().remove("{").remove("}") + ".png";
+ relativePaths << QUrl(widgetPath);
+ relativePaths << QUrl(screenshotPath);
+ return relativePaths;
+ }
+
+ UBGraphicsPixmapItem* pixmapItem = dynamic_cast(item);
+ if(pixmapItem){
+ relativePaths << QUrl(UBPersistenceManager::imageDirectory + "/" + pixmapItem->uuid().toString() + ".png");
+ return relativePaths;
+ }
+
+ UBGraphicsSvgItem* svgItem = dynamic_cast(item);
+ if(svgItem){
+ relativePaths << QUrl(UBPersistenceManager::imageDirectory + "/" + svgItem->uuid().toString() + ".svg");
+ return relativePaths;
+ }
+
+ return relativePaths;
+}
+
QList UBGraphicsScene::relativeDependencies() const
{
- QList relativePathes;
+ QList relativePaths;
QListIterator itItems(mFastAccessItems);
@@ -2473,45 +2529,19 @@ QList UBGraphicsScene::relativeDependencies() const
{
QGraphicsItem* item = itItems.next();
- 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;
- }
-
- UBGraphicsWidgetItem* widget = qgraphicsitem_cast(item);
- if(widget){
- QString widgetPath = UBPersistenceManager::widgetDirectory + "/" + widget->uuid().toString() + ".wgt";
- QString screenshotPath = UBPersistenceManager::widgetDirectory + "/" + widget->uuid().toString().remove("{").remove("}") + ".png";
- relativePathes << QUrl(widgetPath);
- relativePathes << QUrl(screenshotPath);
- continue;
- }
-
- UBGraphicsPixmapItem* pixmapItem = qgraphicsitem_cast(item);
- if(pixmapItem){
- relativePathes << QUrl(UBPersistenceManager::imageDirectory + "/" + pixmapItem->uuid().toString() + ".png");
- continue;
- }
-
- UBGraphicsSvgItem* svgItem = qgraphicsitem_cast(item);
- if(svgItem){
- relativePathes << QUrl(UBPersistenceManager::imageDirectory + "/" + svgItem->uuid().toString() + ".svg");
- continue;
+ UBGraphicsGroupContainerItem* groupItem = dynamic_cast(item);
+ if(groupItem)
+ {
+ for (auto child : groupItem->childItems())
+ {
+ relativePaths << relativeDependenciesOfItem(child);
+ }
}
+ else
+ relativePaths << relativeDependenciesOfItem(item);
}
- return relativePathes;
+ return relativePaths;
}
QSize UBGraphicsScene::nominalSize()
diff --git a/src/domain/UBGraphicsScene.h b/src/domain/UBGraphicsScene.h
index 6a22f14f..82e3a982 100644
--- a/src/domain/UBGraphicsScene.h
+++ b/src/domain/UBGraphicsScene.h
@@ -303,6 +303,7 @@ class UBGraphicsScene: public UBCoreGraphicsScene, public UBItem
virtual void setRenderingQuality(UBItem::RenderingQuality pRenderingQuality, UBItem::CacheBehavior cacheBehavior);
+ QList relativeDependenciesOfItem(QGraphicsItem* item) const;
QList relativeDependencies() const;
QSize nominalSize();
diff --git a/src/domain/UBGraphicsTextItem.cpp b/src/domain/UBGraphicsTextItem.cpp
index 5a96dff6..7e850169 100644
--- a/src/domain/UBGraphicsTextItem.cpp
+++ b/src/domain/UBGraphicsTextItem.cpp
@@ -81,6 +81,64 @@ UBGraphicsTextItem::~UBGraphicsTextItem()
{
}
+void UBGraphicsTextItem::initFontProperties()
+{
+ QTextCursor curCursor = textCursor();
+ QTextCharFormat format;
+ QFont font(createDefaultFont());
+
+ font.setPointSize(UBSettings::settings()->fontPointSize());
+ format.setFont(font);
+ if (UBSettings::settings()->isDarkBackground())
+ {
+ if (UBGraphicsTextItem::lastUsedTextColor == Qt::black)
+ UBGraphicsTextItem::lastUsedTextColor = Qt::white;
+ }
+ else
+ {
+ if (UBGraphicsTextItem::lastUsedTextColor == Qt::white)
+ UBGraphicsTextItem::lastUsedTextColor = Qt::black;
+ }
+
+ setDefaultTextColor(UBGraphicsTextItem::lastUsedTextColor);
+ format.setForeground(QBrush(UBGraphicsTextItem::lastUsedTextColor));
+ curCursor.mergeCharFormat(format);
+ setTextCursor(curCursor);
+ setFont(font);
+
+ adjustSize();
+ contentsChanged();
+}
+
+QFont UBGraphicsTextItem::createDefaultFont()
+{
+ QFont font;
+
+ QString fFamily = UBSettings::settings()->fontFamily();
+ if (!fFamily.isEmpty())
+ font.setFamily(fFamily);
+
+ QString fStyleName = UBSettings::settings()->fontStyleName();
+ if (!fStyleName .isEmpty())
+ font.setStyleName(fStyleName);
+
+ bool bold = UBSettings::settings()->isBoldFont();
+ if (bold)
+ font.setWeight(QFont::Bold);
+
+ bool italic = UBSettings::settings()->isItalicFont();
+ if (italic)
+ font.setItalic(true);
+
+
+ int pointSize = UBSettings::settings()->fontPointSize();
+ if (pointSize > 0) {
+ font.setPointSize(pointSize);
+ }
+
+ return font;
+}
+
void UBGraphicsTextItem::recolor()
{
UBGraphicsTextItemDelegate * del = dynamic_cast(Delegate());
diff --git a/src/domain/UBGraphicsTextItem.h b/src/domain/UBGraphicsTextItem.h
index 584a593c..8c51adef 100644
--- a/src/domain/UBGraphicsTextItem.h
+++ b/src/domain/UBGraphicsTextItem.h
@@ -100,6 +100,8 @@ class UBGraphicsTextItem : public QGraphicsTextItem, public UBItem, public UBRes
void activateTextEditor(bool activate);
void setSelected(bool selected);
void recolor();
+ void initFontProperties();
+ QFont createDefaultFont();
QString mTypeTextHereLabel;
diff --git a/src/domain/UBGraphicsTextItemDelegate.cpp b/src/domain/UBGraphicsTextItemDelegate.cpp
index a385b3ac..b925ae49 100644
--- a/src/domain/UBGraphicsTextItemDelegate.cpp
+++ b/src/domain/UBGraphicsTextItemDelegate.cpp
@@ -110,32 +110,6 @@ UBGraphicsTextItemDelegate::UBGraphicsTextItemDelegate(UBGraphicsTextItem* pDele
, delta(5)
{
delegated()->setData(UBGraphicsItemData::ItemEditable, QVariant(true));
- delegated()->setPlainText("");
-
- QTextCursor curCursor = delegated()->textCursor();
- QTextCharFormat format;
- QFont font(createDefaultFont());
-
- font.setPointSize(UBSettings::settings()->fontPointSize());
- format.setFont(font);
- if (UBSettings::settings()->isDarkBackground())
- {
- if (UBGraphicsTextItem::lastUsedTextColor == Qt::black)
- UBGraphicsTextItem::lastUsedTextColor = Qt::white;
- }
- else
- {
- if (UBGraphicsTextItem::lastUsedTextColor == Qt::white)
- UBGraphicsTextItem::lastUsedTextColor = Qt::black;
- }
- delegated()->setDefaultTextColor(UBGraphicsTextItem::lastUsedTextColor);
- format.setForeground(QBrush(UBGraphicsTextItem::lastUsedTextColor));
- curCursor.mergeCharFormat(format);
- delegated()->setTextCursor(curCursor);
- delegated()->setFont(font);
-
- delegated()->adjustSize();
- delegated()->contentsChanged();
connect(delegated()->document(), SIGNAL(cursorPositionChanged(QTextCursor)), this, SLOT(onCursorPositionChanged(QTextCursor)));
connect(delegated()->document(), SIGNAL(modificationChanged(bool)), this, SLOT(onModificationChanged(bool)));
@@ -146,31 +120,6 @@ UBGraphicsTextItemDelegate::~UBGraphicsTextItemDelegate()
// NOOP
}
-QFont UBGraphicsTextItemDelegate::createDefaultFont()
-{
- QTextCharFormat textFormat;
-
- QString fFamily = UBSettings::settings()->fontFamily();
- if (!fFamily.isEmpty())
- textFormat.setFontFamily(fFamily);
-
- bool bold = UBSettings::settings()->isBoldFont();
- if (bold)
- textFormat.setFontWeight(QFont::Bold);
-
- bool italic = UBSettings::settings()->isItalicFont();
- if (italic)
- textFormat.setFontItalic(true);
-
- QFont font(fFamily, -1, bold ? QFont::Bold : -1, italic);
- int pointSize = UBSettings::settings()->fontPointSize();
- if (pointSize > 0) {
- font.setPointSize(pointSize);
- }
-
- return font;
-}
-
void UBGraphicsTextItemDelegate::createControls()
{
UBGraphicsItemDelegate::createControls();
@@ -336,6 +285,7 @@ void UBGraphicsTextItemDelegate::pickFont()
QFontDialog fontDialog(static_cast(UBApplication::boardController->controlView()));
fontDialog.setOption(QFontDialog::DontUseNativeDialog);
+
fontDialog.setCurrentFont(delegated()->textCursor().charFormat().font());
customize(fontDialog);
@@ -343,6 +293,7 @@ void UBGraphicsTextItemDelegate::pickFont()
{
QFont selectedFont = fontDialog.selectedFont();
UBSettings::settings()->setFontFamily(selectedFont.family());
+ UBSettings::settings()->setFontStyleName(selectedFont.styleName());
UBSettings::settings()->setBoldFont(selectedFont.bold());
UBSettings::settings()->setItalicFont(selectedFont.italic());
UBSettings::settings()->setFontPointSize(selectedFont.pointSize());
diff --git a/src/domain/UBGraphicsTextItemDelegate.h b/src/domain/UBGraphicsTextItemDelegate.h
index 76aaf8f3..30c64849 100644
--- a/src/domain/UBGraphicsTextItemDelegate.h
+++ b/src/domain/UBGraphicsTextItemDelegate.h
@@ -158,7 +158,6 @@ class UBGraphicsTextItemDelegate : public UBGraphicsItemDelegate
void restoreTextCursorFormats();
- QFont createDefaultFont();
QAction *mEditableAction;
struct selectionData_t {
selectionData_t()
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/frameworks/UBPlatformUtils.cpp b/src/frameworks/UBPlatformUtils.cpp
index b5335f8f..74a17b95 100644
--- a/src/frameworks/UBPlatformUtils.cpp
+++ b/src/frameworks/UBPlatformUtils.cpp
@@ -66,7 +66,9 @@ UBKeyboardLocale::~UBKeyboardLocale()
int UBPlatformUtils::nKeyboardLayouts;
UBKeyboardLocale** UBPlatformUtils::keyboardLayouts;
-
+#ifdef Q_OS_OSX
+bool UBPlatformUtils::errorOpeningVirtualKeyboard = false;
+#endif
UBKeyboardLocale** UBPlatformUtils::getKeyboardLayouts(int& nCount)
{
nCount = nKeyboardLayouts;
diff --git a/src/frameworks/UBPlatformUtils.h b/src/frameworks/UBPlatformUtils.h
index 8e6b91ed..6d8ad70c 100644
--- a/src/frameworks/UBPlatformUtils.h
+++ b/src/frameworks/UBPlatformUtils.h
@@ -213,6 +213,8 @@ public:
#ifdef Q_OS_OSX
static void SetMacLocaleByIdentifier(const QString& id);
static void toggleFinder(const bool on);
+
+ static bool errorOpeningVirtualKeyboard;
#endif
};
diff --git a/src/frameworks/UBPlatformUtils_mac.mm b/src/frameworks/UBPlatformUtils_mac.mm
index ae5c5956..3138861f 100644
--- a/src/frameworks/UBPlatformUtils_mac.mm
+++ b/src/frameworks/UBPlatformUtils_mac.mm
@@ -31,6 +31,7 @@
#include "core/UBApplication.h"
#include "core/UBSettings.h"
#include "frameworks/UBFileSystemUtils.h"
+#include "gui/UBMainWindow.h"
#include
@@ -622,35 +623,109 @@ void UBPlatformUtils::showFullScreen(QWidget *pWidget)
void UBPlatformUtils::showOSK(bool show)
{
- @autoreleasepool {
- CFDictionaryRef properties = (CFDictionaryRef)[NSDictionary
- dictionaryWithObject: @"com.apple.KeyboardViewer"
- forKey: (NSString *)kTISPropertyInputSourceID];
+ if (QOperatingSystemVersion::current().majorVersion() == 10 && QOperatingSystemVersion::current().minorVersion() < 15) /* < Catalina */
+ {
+ @autoreleasepool {
+ CFDictionaryRef properties = (CFDictionaryRef)[NSDictionary
+ dictionaryWithObject: @"com.apple.KeyboardViewer"
+ forKey: (NSString *)kTISPropertyInputSourceID];
+
+ NSArray *sources = (NSArray *)TISCreateInputSourceList(properties, true);
- NSArray *sources = (NSArray *)TISCreateInputSourceList(properties, true);
+ if ([sources count] > 0) {
+ TISInputSourceRef osk = (TISInputSourceRef)[sources objectAtIndex: 0];
- if ([sources count] > 0) {
- TISInputSourceRef osk = (TISInputSourceRef)[sources objectAtIndex: 0];
+ OSStatus result;
+ if (show) {
+ TISEnableInputSource(osk);
+ result = TISSelectInputSource(osk);
+ }
+ else {
+ TISDisableInputSource(osk);
+ result = TISDeselectInputSource(osk);
+ }
- OSStatus result;
- if (show) {
- TISEnableInputSource(osk);
- result = TISSelectInputSource(osk);
+ if (result == paramErr) {
+ qWarning() << "Unable to select input source";
+ UBApplication::showMessage(tr("Unable to activate system on-screen keyboard"));
+ }
}
+
else {
- TISDisableInputSource(osk);
- result = TISDeselectInputSource(osk);
+ qWarning() << "System OSK not found";
+ UBApplication::showMessage(tr("System on-screen keyboard not found"));
}
+ }
+ }
+ else
+ {
+ NSString *source =
+ @"tell application \"System Events\"\n\
+ if application process \"TextInputMenuAgent\" exists then\n\
+ tell application process \"TextInputMenuAgent\"\n\
+ tell menu bar item 1 of menu bar 2\n\
+ ignoring application responses\n\
+ click\n\
+ delay 0.5\n\
+ end ignoring\n\
+ end tell\n\
+ end tell\n\
+ end if\n\
+ end tell\n\
+ do shell script \"killall 'System Events'\"\n";
+
+ source = [source stringByAppendingString:@"if application \"Assistive Control\" is"];
+
+ if (show)
+ {
+ source = [source stringByAppendingString:@" not"];
+ }
+
+ source = [source stringByAppendingString:@" running then\n\
+ tell application \"System Events\"\n\
+ tell application process \"TextInputMenuAgent\"\n\
+ tell menu 1 of menu bar item 1 of menu bar 2\n\
+ set nbItems to count menu items\n\
+ if (nbItems = 4)\n\
+ -- only one language so items are\n\
+ -- 1. emojis&symbols n-2. keyboard n-1. separator n.preferences\n\
+ click menu item (nbItems-2)\n\
+ else\n\
+ -- items are ... n-4. access keyboard n-3. separator n-2 display names n-1. separator n. preferences\n\
+ -- target is in fourth position from bottom\n\
+ click menu item (nbItems - 4)\n\
+ end if\n\
+ end tell\n\
+ end tell\n\
+ end tell\n\
+ end if"];
+
+ NSAppleScript *script = [[[NSAppleScript alloc] initWithSource:source] autorelease];
+ NSDictionary *errorInfo = nil;
+ [script executeAndReturnError:&errorInfo];
+
+ if(errorInfo!=nil)
+ {
+ errorOpeningVirtualKeyboard = true;
- if (result == paramErr) {
- qWarning() << "Unable to select input source";
- UBApplication::showMessage(tr("Unable to activate system on-screen keyboard"));
+ NSAlert *alert = [[NSAlert alloc] init];
+
+ if (alert != nil)
+ {
+ alert.messageText = errorInfo.allValues[0];
+ [alert runModal];
+ [alert release];
+
+ //restore action state to previous one as it failed
+ if (show)
+ UBApplication::mainWindow->actionVirtualKeyboard->setChecked(false);
+ else
+ UBApplication::mainWindow->actionVirtualKeyboard->setChecked(true);
}
}
-
- else {
- qWarning() << "System OSK not found";
- UBApplication::showMessage(tr("System on-screen keyboard not found"));
+ else
+ {
+ errorOpeningVirtualKeyboard = false;
}
}
}
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));
}
}
}
diff --git a/src/gui/UBDocumentNavigator.cpp b/src/gui/UBDocumentNavigator.cpp
index 1fa0a6db..73bf9724 100644
--- a/src/gui/UBDocumentNavigator.cpp
+++ b/src/gui/UBDocumentNavigator.cpp
@@ -83,7 +83,10 @@ UBDocumentNavigator::UBDocumentNavigator(QWidget *parent, const char *name):QGra
setFrameShadow(QFrame::Plain);
connect(UBApplication::boardController, SIGNAL(documentThumbnailsUpdated(UBDocumentContainer*)), this, SLOT(generateThumbnails(UBDocumentContainer*)));
- connect(UBApplication::boardController, SIGNAL(documentPageUpdated(int)), this, SLOT(updateSpecificThumbnail(int)));
+ connect(UBApplication::boardController, SIGNAL(documentPageInserted(int)), this, SLOT(insertThumbnail(int)));
+ connect(UBApplication::boardController, SIGNAL(documentPageUpdated(int)), this, SLOT(updateThumbnail(int)));
+ connect(UBApplication::boardController, SIGNAL(documentPageRemoved(int)), this, SLOT(removeThumbnail(int)));
+ connect(UBApplication::boardController, SIGNAL(documentPageMoved(int, int)), this, SLOT(moveThumbnail(int, int)));
connect(UBApplication::boardController, SIGNAL(pageSelectionChanged(int)), this, SLOT(onScrollToSelectedPage(int)));
connect(&mLongPressTimer, SIGNAL(timeout()), this, SLOT(longPressTimeout()), Qt::UniqueConnection);
@@ -133,29 +136,53 @@ void UBDocumentNavigator::generateThumbnails(UBDocumentContainer* source)
for(int i = 0; i < source->selectedDocument()->pageCount(); i++)
{
- //claudio This is a very bad hack and shows a architectural problem
- // source->selectedDocument()->pageCount() != source->pageCount()
- if(i>=source->pageCount() || !source->pageAt(i))
- source->insertThumbPage(i);
+ UBApplication::showMessage(tr("Generating thumbnails for board (%1/%2)").arg(i+1).arg(source->selectedDocument()->pageCount()));
- const QPixmap* pix = source->pageAt(i);
- Q_ASSERT(!pix->isNull());
- int pageIndex = UBDocumentContainer::pageFromSceneIndex(i);
+ bool found = false;
+ if (UBApplication::documentController)
+ {
+ if (UBApplication::documentController->selectedDocument() == source->selectedDocument())
+ {
- UBSceneThumbnailNavigPixmap* pixmapItem = new UBSceneThumbnailNavigPixmap(*pix, source->selectedDocument(), i);
+ if (UBApplication::documentController->pageAt(i))
+ {
+ found = true;
+ //thumbnail has already been loaded on the documentController so we don't need to do it again
+ source->insertExistingThumbPage(i, UBApplication::documentController->pageAt(i));
+ }
+ }
+ }
- QString label = tr("Page %0").arg(pageIndex);
- UBThumbnailTextItem *labelItem = new UBThumbnailTextItem(label);
+ if (!found)
+ {
+ //claudio This is a very bad hack and shows a architectural problem
+ // source->selectedDocument()->pageCount() != source->pageCount()
+ if(i>=source->pageCount() || !source->pageAt(i))
+ {
+ source->insertThumbPage(i);
+ }
+ else
+ {
+ auto pix = source->pageAt(i);
+ Q_ASSERT(!pix->isNull());
+ int pageIndex = UBDocumentContainer::pageFromSceneIndex(i);
+
+ UBSceneThumbnailNavigPixmap* pixmapItem = new UBSceneThumbnailNavigPixmap(*pix, source->selectedDocument(), i);
+
+ QString label = tr("Page %0").arg(pageIndex);
+ UBThumbnailTextItem *labelItem = new UBThumbnailTextItem(label);
- UBImgTextThumbnailElement thumbWithText(pixmapItem, labelItem);
- thumbWithText.setBorder(border());
- mThumbsWithLabels.append(thumbWithText);
+ UBImgTextThumbnailElement thumbWithText(pixmapItem, labelItem);
+ thumbWithText.setBorder(border());
+ mThumbsWithLabels.append(thumbWithText);
- if (lastClickedIndex == i)
- mLastClickedThumbnail = pixmapItem;
+ if (lastClickedIndex == i)
+ mLastClickedThumbnail = pixmapItem;
- mScene->addItem(pixmapItem);
- mScene->addItem(labelItem);
+ mScene->addItem(pixmapItem);
+ mScene->addItem(labelItem);
+ }
+ }
}
if (selectedIndex >= 0 && selectedIndex < mThumbsWithLabels.count())
@@ -191,24 +218,83 @@ void UBDocumentNavigator::onScrollToSelectedPage(int index)
* \brief Refresh the given thumbnail
* @param iPage as the given page related thumbnail
*/
-void UBDocumentNavigator::updateSpecificThumbnail(int iPage)
+void UBDocumentNavigator::updateThumbnail(int index)
{
- const QPixmap* pix = UBApplication::boardController->pageAt(iPage);
- UBSceneThumbnailNavigPixmap* newItem = new UBSceneThumbnailNavigPixmap(*pix, UBApplication::boardController->selectedDocument(), iPage);
+ auto pix = UBApplication::boardController->pageAt(index);
+ UBSceneThumbnailNavigPixmap* newItem = new UBSceneThumbnailNavigPixmap(*pix, UBApplication::boardController->selectedDocument(), index);
// Get the old thumbnail
- UBSceneThumbnailNavigPixmap* oldItem = mThumbsWithLabels.at(iPage).getThumbnail();
- if(NULL != oldItem)
+ UBSceneThumbnailNavigPixmap* oldItem = mThumbsWithLabels.at(index).getThumbnail();
+ if(oldItem)
{
+ if (oldItem->isSelected())
+ mScene->removeItem(oldItem->selectionItem());
mScene->removeItem(oldItem);
mScene->addItem(newItem);
- mThumbsWithLabels[iPage].setThumbnail(newItem);
+ mThumbsWithLabels[index].setThumbnail(newItem);
if (mLastClickedThumbnail == oldItem)
mLastClickedThumbnail = newItem;
+ if (mSelectedThumbnail == oldItem)
+ mSelectedThumbnail = newItem;
delete oldItem;
oldItem = NULL;
}
+ refreshScene();
+}
+
+void UBDocumentNavigator::removeThumbnail(int index)
+{
+ //remove selectionItem
+ if (mThumbsWithLabels.at(index).getThumbnail()->isSelected())
+ mScene->removeItem(mThumbsWithLabels.at(index).getThumbnail()->selectionItem());
+
+ mScene->removeItem(mThumbsWithLabels.at(index).getCaption());
+ mScene->removeItem(mThumbsWithLabels.at(index).getThumbnail());
+
+ mThumbsWithLabels.removeAt(index);
+
+ //update thumbs page number accordingly
+ for (int i=0; i < mThumbsWithLabels.length(); i++)
+ {
+ mThumbsWithLabels.at(i).getThumbnail()->setSceneIndex(i);
+ mThumbsWithLabels.at(i).getCaption()->setText(tr("Page %0").arg(i+1));
+ }
+
+ refreshScene();
+}
+
+void UBDocumentNavigator::insertThumbnail(int index)
+{
+ auto pix = UBApplication::boardController->pageAt(index);
+ UBSceneThumbnailNavigPixmap* pixmapItem = new UBSceneThumbnailNavigPixmap(*pix, UBApplication::boardController->selectedDocument(), index);
+
+ QString label = tr("Page %0").arg(index+1);
+ UBThumbnailTextItem *labelItem = new UBThumbnailTextItem(label);
+ labelItem->setWidth(mThumbnailWidth);
+
+ UBImgTextThumbnailElement thumbWithText(pixmapItem, labelItem);
+ thumbWithText.setBorder(border());
+
+ mThumbsWithLabels.insert(index, thumbWithText);
+
+ if (mLastClickedThumbnail)
+ {
+ if (mLastClickedThumbnail->sceneIndex() == index)
+ mLastClickedThumbnail = pixmapItem;
+ }
+
+ //sceneIndex is 0-based while pageNumber is 1-based
+ for (int i=0; i < mThumbsWithLabels.size(); i++)
+ {
+ mThumbsWithLabels.at(i).getThumbnail()->setSceneIndex(i);
+ mThumbsWithLabels.at(i).getCaption()->setPageNumber(i+1);
+ }
+
+ mScene->addItem(pixmapItem);
+ mScene->addItem(labelItem);
+
+ refreshScene();
}
/**
@@ -285,11 +371,11 @@ void UBDocumentNavigator::resizeEvent(QResizeEvent *event)
// Update the thumbnails width
mThumbnailWidth = (width() > mThumbnailMinWidth) ? width() - 2*border() : mThumbnailMinWidth;
- if(mSelectedThumbnail)
- ensureVisible(mSelectedThumbnail);
-
// Refresh the scene
refreshScene();
+
+ if(mSelectedThumbnail)
+ ensureVisible(mSelectedThumbnail);
}
/**
@@ -302,7 +388,6 @@ void UBDocumentNavigator::mousePressEvent(QMouseEvent *event)
if (!event->isAccepted())
{
- mLongPressTimer.start();
mLastPressedMousePos = event->pos();
mLastClickedThumbnail = clickedThumbnail(mLastPressedMousePos);
@@ -314,6 +399,19 @@ void UBDocumentNavigator::mousePressEvent(QMouseEvent *event)
UBApplication::boardController->setActiveDocumentScene(mLastClickedThumbnail->sceneIndex());
UBApplication::boardController->centerOn(UBApplication::boardController->activeScene()->lastCenter());
}
+
+ mLongPressTimer.start();
+ }
+}
+
+void UBDocumentNavigator::clearSelection()
+{
+ for (auto item : mScene->items())
+ {
+ if (item->type() == QGraphicsRectItem::Type && item != mDropBar)
+ {
+ mScene->removeItem(item);
+ }
}
}
@@ -518,8 +616,6 @@ void UBDocumentNavigator::dragMoveEvent(QDragMoveEvent *event)
int thumbnailHeight = mThumbnailWidth / UBSettings::minScreenRatio;
QRectF thumbnailArea(0, scenePos.y() - thumbnailHeight/2, mThumbnailWidth, thumbnailHeight);
- ensureVisible(thumbnailArea);
-
UBSceneThumbnailNavigPixmap* item = dynamic_cast(itemAt(position.toPoint()));
if (item)
{
@@ -543,7 +639,7 @@ void UBDocumentNavigator::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
@@ -552,11 +648,14 @@ void UBDocumentNavigator::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));
}
}
}
}
+
+ ensureVisible(thumbnailArea);
+
event->acceptProposedAction();
}
@@ -566,8 +665,12 @@ void UBDocumentNavigator::dropEvent(QDropEvent *event)
if (mDropSource && mDropTarget)
{
- if (mDropSource->sceneIndex() != mDropTarget->sceneIndex())
- UBApplication::boardController->moveSceneToIndex(mDropSource->sceneIndex(), mDropTarget->sceneIndex());
+ int sourceIndex = mDropSource->sceneIndex();
+ int targetIndex = mDropTarget->sceneIndex();
+ if (sourceIndex != targetIndex)
+ {
+ UBApplication::boardController->moveSceneToIndex(sourceIndex, targetIndex);
+ }
}
mDropSource = NULL;
@@ -577,3 +680,17 @@ void UBDocumentNavigator::dropEvent(QDropEvent *event)
mDropBar->setRect(QRectF());
mDropBar->hide();
}
+
+void UBDocumentNavigator::moveThumbnail(int from, int to)
+{
+ mThumbsWithLabels.move(from, to);
+
+ //sceneIndex is 0-based while pageNumber is 1-based
+ for (int i=0; i < mThumbsWithLabels.size(); i++)
+ {
+ mThumbsWithLabels.at(i).getThumbnail()->setSceneIndex(i);
+ mThumbsWithLabels.at(i).getCaption()->setPageNumber(i+1);
+ }
+
+ refreshScene();
+}
diff --git a/src/gui/UBDocumentNavigator.h b/src/gui/UBDocumentNavigator.h
index 9e29a2c9..1a252a6e 100644
--- a/src/gui/UBDocumentNavigator.h
+++ b/src/gui/UBDocumentNavigator.h
@@ -53,12 +53,16 @@ public:
int nbColumns();
void setThumbnailMinWidth(int width);
int thumbnailMinWidth();
+ void clearSelection();
UBSceneThumbnailNavigPixmap* clickedThumbnail(const QPoint pos) const;
public slots:
void onScrollToSelectedPage(int index);// { if (mCrntItem) centerOn(mCrntItem); }
void generateThumbnails(UBDocumentContainer* source);
- void updateSpecificThumbnail(int iPage);
+ void insertThumbnail(int index);
+ void updateThumbnail(int index);
+ void removeThumbnail(int index);
+ void moveThumbnail(int from, int to);
void longPressTimeout();
void mousePressAndHoldEvent();
diff --git a/src/gui/UBDocumentThumbnailWidget.cpp b/src/gui/UBDocumentThumbnailWidget.cpp
index 44cf9ebe..aeb2f473 100644
--- a/src/gui/UBDocumentThumbnailWidget.cpp
+++ b/src/gui/UBDocumentThumbnailWidget.cpp
@@ -58,7 +58,6 @@ UBDocumentThumbnailWidget::~UBDocumentThumbnailWidget()
// NOOP
}
-
void UBDocumentThumbnailWidget::mouseMoveEvent(QMouseEvent *event)
{
if (!dragEnabled())
@@ -297,6 +296,64 @@ bool UBDocumentThumbnailWidget::dragEnabled() const
return mDragEnabled;
}
+void UBDocumentThumbnailWidget::updateThumbnailPixmap(int index, const QPixmap& newThumbnail)
+{
+ if (index >= 0 && index < mGraphicItems.length())
+ {
+ UBSceneThumbnailPixmap *thumbnail = dynamic_cast(mGraphicItems.at(index));
+ if (thumbnail)
+ {
+ thumbnail->setPixmap(newThumbnail);
+ }
+ }
+}
+
+void UBDocumentThumbnailWidget::removeThumbnail(int sceneIndex)
+{
+ if (sceneIndex >= 0 && sceneIndex < mGraphicItems.length())
+ {
+ QGraphicsItem* thumbnailItem = mGraphicItems.at(sceneIndex);
+ QGraphicsItem* textItem = mLabelsItems.at(sceneIndex);
+ UBSceneThumbnailPixmap *thumbnail = dynamic_cast(thumbnailItem);
+ if (thumbnail)
+ {
+ if (thumbnail->isSelected())
+ scene()->removeItem(thumbnail->selectionItem());
+
+ mGraphicItems.removeAt(sceneIndex);
+ if (thumbnailItem)
+ scene()->removeItem(thumbnailItem);
+
+ mLabelsItems.removeAt(sceneIndex);
+ if (textItem)
+ scene()->removeItem(textItem);
+ }
+ refreshScene();
+ }
+}
+
+void UBDocumentThumbnailWidget::insertThumbnail(int index, QGraphicsPixmapItem* newThumbnail)
+{
+ if (!mGraphicItems.contains(newThumbnail)) //sometimes, refreshDocumentThumbnailsView is called before
+ {
+ auto thumbnailTextItem = new UBThumbnailTextItem(index);
+ mGraphicItems.insert(index, newThumbnail);
+ mLabelsItems.insert(index, thumbnailTextItem);
+ }
+
+ refreshScene();
+}
+
+void UBDocumentThumbnailWidget::moveThumbnail(int from, int to)
+{
+ UBSceneThumbnailPixmap *thumbnail = dynamic_cast(mGraphicItems.at(from));
+ if (thumbnail)
+ {
+ mGraphicItems.move(from, to);
+ }
+ refreshScene();
+}
+
void UBDocumentThumbnailWidget::hightlightItem(int index)
{
if (0 <= index && index < mLabelsItems.length())
diff --git a/src/gui/UBDocumentThumbnailWidget.h b/src/gui/UBDocumentThumbnailWidget.h
index e08b464d..5ac9e620 100644
--- a/src/gui/UBDocumentThumbnailWidget.h
+++ b/src/gui/UBDocumentThumbnailWidget.h
@@ -48,9 +48,11 @@ class UBDocumentThumbnailWidget: public UBThumbnailWidget
void hightlightItem(int index);
public slots:
- virtual void setGraphicsItems(const QList& pGraphicsItems,
- const QList& pItemPaths, const QStringList pLabels = QStringList(),
- const QString& pMimeType = QString(""));
+ void updateThumbnailPixmap(int index, const QPixmap& newThumbnail);
+ void removeThumbnail(int index);
+ void moveThumbnail(int from, int to);
+ void insertThumbnail(int index, QGraphicsPixmapItem *newThumbnail);
+ virtual void setGraphicsItems(const QList& pGraphicsItems, const QList& pItemPaths, const QStringList pLabels = QStringList(), const QString& pMimeType = QString(""));
signals:
void sceneDropped(UBDocumentProxy* proxy, int source, int target);
diff --git a/src/gui/UBThumbnailWidget.cpp b/src/gui/UBThumbnailWidget.cpp
index b31bdd1e..779974bc 100644
--- a/src/gui/UBThumbnailWidget.cpp
+++ b/src/gui/UBThumbnailWidget.cpp
@@ -67,13 +67,11 @@ UBThumbnailWidget::UBThumbnailWidget(QWidget* parent)
setAlignment(Qt::AlignLeft | Qt::AlignTop);
- connect(&mThumbnailsScene, SIGNAL(selectionChanged()), this, SLOT(sceneSelectionChanged()));
}
UBThumbnailWidget::~UBThumbnailWidget()
{
- disconnect(&mThumbnailsScene, SIGNAL(selectionChanged()));
}
@@ -108,7 +106,6 @@ void UBThumbnailWidget::setGraphicsItems(const QList& pGraphicsI
{
mThumbnailsScene.removeItem(it, true);
}
-
// set lasso to 0 as it has been cleared as well
mLassoRectItem = 0;
@@ -136,6 +133,12 @@ void UBThumbnailWidget::setGraphicsItems(const QList& pGraphicsI
mLastSelectedThumbnail = 0;
}
+void UBThumbnailWidget::insertThumbnailToScene(QGraphicsPixmapItem* newThumbnail, UBThumbnailTextItem* thumbnailTextItem)
+{
+ mThumbnailsScene.addItem(newThumbnail);
+ mThumbnailsScene.addItem(thumbnailTextItem);
+}
+
void UBThumbnailWidget::refreshScene()
{
@@ -156,6 +159,10 @@ void UBThumbnailWidget::refreshScene()
{
QGraphicsItem* item = mGraphicItems.at(i);
+ UBSceneThumbnailPixmap *thumbnail = dynamic_cast(item);
+ if (thumbnail)
+ thumbnail->setSceneIndex(i);
+
qreal scaleWidth = mThumbnailWidth / item->boundingRect().width();
qreal scaleHeight = thumbnailHeight / item->boundingRect().height();
@@ -192,8 +199,10 @@ void UBThumbnailWidget::refreshScene()
if (mLabelsItems.size() > i)
{
+ mLabelsItems.at(i)->setWidth(mThumbnailWidth);
+ mLabelsItems.at(i)->setPageNumber(i+1);
QFontMetrics fm(mLabelsItems.at(i)->font(), this);
- QString elidedText = fm.elidedText(mLabels.at(i), Qt::ElideRight, mThumbnailWidth);
+ QString elidedText = fm.elidedText(mLabelsItems.at(i)->toPlainText(), Qt::ElideRight, mThumbnailWidth);
mLabelsItems.at(i)->setPlainText(elidedText);
mLabelsItems.at(i)->setWidth(fm.width(elidedText) + 2 * mLabelsItems.at(i)->document()->documentMargin());
@@ -223,6 +232,11 @@ QList UBThumbnailWidget::selectedItems()
return sortedSelectedItems;
}
+void UBThumbnailWidget::clearSelection()
+{
+ mThumbnailsScene.clearSelection();
+}
+
void UBThumbnailWidget::mousePressEvent(QMouseEvent *event)
{
@@ -301,7 +315,6 @@ void UBThumbnailWidget::mousePressEvent(QMouseEvent *event)
}
mSelectionSpan = index2 - index1;
selectItems(qMin(index1, index2), mSelectionSpan < 0 ? - mSelectionSpan + 1 : mSelectionSpan + 1);
- return;
}
}
}
@@ -320,8 +333,9 @@ void UBThumbnailWidget::mousePressEvent(QMouseEvent *event)
if (!mLastSelectedThumbnail && mGraphicItems.count() > 0)
mLastSelectedThumbnail = dynamic_cast(mGraphicItems.at(0));
mSelectionSpan = 0;
- return;
}
+
+ UBApplication::documentController->pageSelectionChanged();
}
diff --git a/src/gui/UBThumbnailWidget.h b/src/gui/UBThumbnailWidget.h
index c286f00d..9b1a3cbb 100644
--- a/src/gui/UBThumbnailWidget.h
+++ b/src/gui/UBThumbnailWidget.h
@@ -66,6 +66,7 @@ class UBThumbnailWidget : public QGraphicsView
QList selectedItems();
void selectItemAt(int pIndex, bool extend = false);
void unselectItemAt(int pIndex);
+ void clearSelection();
qreal thumbnailWidth()
{
@@ -81,6 +82,7 @@ class UBThumbnailWidget : public QGraphicsView
void setThumbnailWidth(qreal pThumbnailWidth);
void setSpacing(qreal pSpacing);
virtual void setGraphicsItems(const QList& pGraphicsItems, const QList& pItemPaths, const QStringList pLabels = QStringList(), const QString& pMimeType = QString(""));
+ void insertThumbnailToScene(QGraphicsPixmapItem* newThumbnail, UBThumbnailTextItem* thumbnailTextItem);
void refreshScene();
void sceneSelectionChanged();
@@ -184,7 +186,6 @@ class UBThumbnail
item->sceneBoundingRect().height() + 10);
mSelectionItem->show();
-
}
else
{
@@ -199,6 +200,7 @@ class UBThumbnail
void setRow(int row) { mRow = row; }
UBThumbnailTextItem *label(){return mLabel;}
void setLabel(UBThumbnailTextItem *label){mLabel = label;}
+ QGraphicsRectItem* selectionItem(){ return mSelectionItem; }
protected:
QGraphicsRectItem *mSelectionItem;
@@ -255,6 +257,18 @@ class UBThumbnailTextItem : public QGraphicsTextItem
}
}
+ void setPageNumber(int i)
+ {
+ mUnelidedText = tr("Page %0").arg(i);
+ computeText();
+ }
+
+ void setText(const QString& text)
+ {
+ mUnelidedText = text;
+ computeText();
+ }
+
void computeText()
{
QFontMetricsF fm(font());
@@ -339,6 +353,11 @@ class UBSceneThumbnailPixmap : public UBThumbnailPixmap
return mSceneIndex;
}
+ void setSceneIndex(int i)
+ {
+ mSceneIndex = i;
+ }
+
void highlight()
{
//NOOP
diff --git a/src/gui/UBWebToolsPalette.cpp b/src/gui/UBWebToolsPalette.cpp
index dcca8fce..3149dc79 100644
--- a/src/gui/UBWebToolsPalette.cpp
+++ b/src/gui/UBWebToolsPalette.cpp
@@ -49,7 +49,7 @@ UBWebToolsPalette::UBWebToolsPalette(QWidget *parent)
{
QList actions;
- actions << UBApplication::mainWindow->actionWebTrapFlash;
+ actions << UBApplication::mainWindow->actionCaptureWebContent;
actions << UBApplication::mainWindow->actionWebCustomCapture;
actions << UBApplication::mainWindow->actionWebWindowCapture;
diff --git a/src/pdf/XPDFRenderer.cpp b/src/pdf/XPDFRenderer.cpp
index a81616b8..56826565 100644
--- a/src/pdf/XPDFRenderer.cpp
+++ b/src/pdf/XPDFRenderer.cpp
@@ -95,6 +95,8 @@ XPDFRenderer::XPDFRenderer(const QString &filename, bool importingFile)
}
#ifdef USE_XPDF
mDocument = new PDFDoc(new GString(filename.toLocal8Bit()), 0, 0, 0); // the filename GString is deleted on PDFDoc desctruction
+#elif POPPLER_VERSION_MAJOR > 22 || (POPPLER_VERSION_MAJOR == 22 && POPPLER_VERSION_MINOR >= 3)
+ mDocument = new PDFDoc(std::make_unique(filename.toLocal8Bit()));
#else
mDocument = new PDFDoc(new GooString(filename.toLocal8Bit()), 0, 0, 0); // the filename GString is deleted on PDFDoc desctruction
#endif
diff --git a/src/pdf/pdf.pri b/src/pdf/pdf.pri
index 9be1b7fe..82b7bf50 100644
--- a/src/pdf/pdf.pri
+++ b/src/pdf/pdf.pri
@@ -1,4 +1,3 @@
-
HEADERS += src/pdf/GraphicsPDFItem.h \
src/pdf/PDFRenderer.h \
src/pdf/UBWebPluginPDFWidget.h \
@@ -8,4 +7,4 @@ SOURCES += src/pdf/GraphicsPDFItem.cpp \
src/pdf/PDFRenderer.cpp \
src/pdf/UBWebPluginPDFWidget.cpp \
src/pdf/XPDFRenderer.cpp
-
\ No newline at end of file
+
diff --git a/src/qtsingleapplication/INSTALL.TXT b/src/qtsingleapplication/INSTALL.TXT
deleted file mode 100644
index bbb74a9d..00000000
--- a/src/qtsingleapplication/INSTALL.TXT
+++ /dev/null
@@ -1,254 +0,0 @@
-INSTALLATION INSTRUCTIONS
-
-These instructions refer to the package you are installing as
-some-package.tar.gz or some-package.zip. The .zip file is intended for use
-on Windows.
-
-The directory you choose for the installation will be referred to as
-your-install-dir.
-
-Note to Qt Visual Studio Integration users: In the instructions below,
-instead of building from command line with nmake, you can use the menu
-command 'Qt->Open Solution from .pro file' on the .pro files in the
-example and plugin directories, and then build from within Visual
-Studio.
-
-Unpacking and installation
---------------------------
-
-1. Unpacking the archive (if you have not done so already).
-
- On Unix and Mac OS X (in a terminal window):
-
- cd your-install-dir
- gunzip some-package.tar.gz
- tar xvf some-package.tar
-
- This creates the subdirectory some-package containing the files.
-
- On Windows:
-
- Unpack the .zip archive by right-clicking it in explorer and
- choosing "Extract All...". If your version of Windows does not
- have zip support, you can use the infozip tools available
- from www.info-zip.org.
-
- If you are using the infozip tools (in a command prompt window):
- cd your-install-dir
- unzip some-package.zip
-
-2. Configuring the package.
-
- The configure script is called "configure" on unix/mac and
- "configure.bat" on Windows. It should be run from a command line
- after cd'ing to the package directory.
-
- You can choose whether you want to use the component by including
- its source code directly into your project, or build the component
- as a dynamic shared library (DLL) that is loaded into the
- application at run-time. The latter may be preferable for
- technical or licensing (LGPL) reasons. If you want to build a DLL,
- run the configure script with the argument "-library". Also see
- the note about usage below.
-
- (Components that are Qt plugins, e.g. styles and image formats,
- are by default built as a plugin DLL.)
-
- The configure script will prompt you in some cases for further
- information. Answer these questions and carefully read the license text
- before accepting the license conditions. The package cannot be used if
- you do not accept the license conditions.
-
-3. Building the component and examples (when required).
-
- If a DLL is to be built, or if you would like to build the
- examples, next give the commands
-
- qmake
- make [or nmake if your are using Microsoft Visual C++]
-
- The example program(s) can be found in the directory called
- "examples" or "example".
-
- Components that are Qt plugins, e.g. styles and image formats, are
- ready to be used as soon as they are built, so the rest of this
- installation instruction can be skipped.
-
-4. Building the Qt Designer plugin (optional).
-
- Some of the widget components are provided with plugins for Qt
- Designer. To build and install the plugin, cd into the
- some-package/plugin directory and give the commands
-
- qmake
- make [or nmake if your are using Microsoft Visual C++]
-
- Restart Qt Designer to make it load the new widget plugin.
-
- Note: If you are using the built-in Qt Designer from the Qt Visual
- Studio Integration, you will need to manually copy the plugin DLL
- file, i.e. copy
- %QTDIR%\plugins\designer\some-component.dll
- to the Qt Visual Studio Integration plugin path, typically:
- C:\Program Files\Trolltech\Qt VS Integration\plugins
-
- Note: If you for some reason are using a Qt Designer that is built
- in debug mode, you will need to build the plugin in debug mode
- also. Edit the file plugin.pro in the plugin directory, changing
- 'release' to 'debug' in the CONFIG line, before running qmake.
-
-
-
-Solutions components are intended to be used directly from the package
-directory during development, so there is no 'make install' procedure.
-
-
-Using a component in your project
----------------------------------
-
-To use this component in your project, add the following line to the
-project's .pro file (or do the equivalent in your IDE):
-
- include(your-install-dir/some-package/src/some-package.pri)
-
-This adds the package's sources and headers to the SOURCES and HEADERS
-project variables respectively (or, if the component has been
-configured as a DLL, it adds that library to the LIBS variable), and
-updates INCLUDEPATH to contain the package's src
-directory. Additionally, the .pri file may include some dependencies
-needed by the package.
-
-To include a header file from the package in your sources, you can now
-simply use:
-
- #include
-
-or alternatively, in pre-Qt 4 style:
-
- #include
-
-Refer to the documentation to see the classes and headers this
-components provides.
-
-
-
-Install documentation (optional)
---------------------------------
-
-The HTML documentation for the package's classes is located in the
-your-install-dir/some-package/doc/html/index.html. You can open this
-file and read the documentation with any web browser.
-
-To install the documentation into Qt Assistant (for Qt version 4.4 and
-later):
-
-1. In Assistant, open the Edit->Preferences dialog and choose the
- Documentation tab. Click the Add... button and select the file
- your-install-dir/some-package/doc/html/some-package.qch
-
-For Qt versions prior to 4.4, do instead the following:
-
-1. The directory your-install-dir/some-package/doc/html contains a
- file called some-package.dcf. Execute the following commands in a
- shell, command prompt or terminal window:
-
- cd your-install-dir/some-package/doc/html/
- assistant -addContentFile some-package.dcf
-
-The next time you start Qt Assistant, you can access the package's
-documentation.
-
-
-Removing the documentation from assistant
------------------------------------------
-
-If you have installed the documentation into Qt Assistant, and want to uninstall it, do as follows, for Qt version 4.4 and later:
-
-1. In Assistant, open the Edit->Preferences dialog and choose the
- Documentation tab. In the list of Registered Documentation, select
- the item com.nokia.qtsolutions.some-package_version, and click
- the Remove button.
-
-For Qt versions prior to 4.4, do instead the following:
-
-1. The directory your-install-dir/some-package/doc/html contains a
- file called some-package.dcf. Execute the following commands in a
- shell, command prompt or terminal window:
-
- cd your-install-dir/some-package/doc/html/
- assistant -removeContentFile some-package.dcf
-
-
-
-Using the component as a DLL
-----------------------------
-
-1. Normal components
-
- The shared library (DLL) is built and placed in the
- some-package/lib directory. It is intended to be used directly
- from there during development. When appropriate, both debug and
- release versions are built, since the run-time linker will in some
- cases refuse to load a debug-built DLL into a release-built
- application or vice versa.
-
- The following steps are taken by default to help the dynamic
- linker to locate the DLL at run-time (during development):
-
- Unix: The some-package.pri file will add linker instructions to
- add the some-package/lib directory to the rpath of the
- executable. (When distributing, or if your system does not support
- rpath, you can copy the shared library to another place that is
- searched by the dynamic linker, e.g. the "lib" directory of your
- Qt installation.)
-
- Mac: The full path to the library is hardcoded into the library
- itself, from where it is copied into the executable at link time,
- and ready by the dynamic linker at run-time. (When distributing,
- you will want to edit these hardcoded paths in the same way as for
- the Qt DLLs. Refer to the document "Deploying an Application on
- Mac OS X" in the Qt Reference Documentation.)
-
- Windows: the .dll file(s) are copied into the "bin" directory of
- your Qt installation. The Qt installation will already have set up
- that directory to be searched by the dynamic linker.
-
-
-2. Plugins
-
- For Qt Solutions plugins (e.g. image formats), both debug and
- release versions of the plugin are built by default when
- appropriate, since in some cases the release Qt library will not
- load a debug plugin, and vice versa. The plugins are automatically
- copied into the plugins directory of your Qt installation when
- built, so no further setup is required.
-
- Plugins may also be built statically, i.e. as a library that will be
- linked into your application executable, and so will not need to
- be redistributed as a separate plugin DLL to end users. Static
- building is required if Qt itself is built statically. To do it,
- just add "static" to the CONFIG variable in the plugin/plugin.pro
- file before building. Refer to the "Static Plugins" section in the
- chapter "How to Create Qt Plugins" for explanation of how to use a
- static plugin in your application. The source code of the example
- program(s) will also typically contain the relevant instructions
- as comments.
-
-
-
-Uninstalling
-------------
-
- The following command will remove any fils that have been
- automatically placed outside the package directory itself during
- installation and building
-
- make distclean [or nmake if your are using Microsoft Visual C++]
-
- If Qt Assistant documentation or Qt Designer plugins have been
- installed, they can be uninstalled manually, ref. above.
-
-
-Enjoy! :)
-
-- The Qt Solutions Team.
diff --git a/src/qtsingleapplication/README.TXT b/src/qtsingleapplication/README.TXT
deleted file mode 100644
index 06abb095..00000000
--- a/src/qtsingleapplication/README.TXT
+++ /dev/null
@@ -1,33 +0,0 @@
-Qt Solutions Component: Single Application
-
-The QtSingleApplication component provides support for
-applications that can be only started once per user.
-
-
-
-Version history:
-
-2.0: - Version 1.3 ported to Qt 4.
-
-2.1: - Fix compilation problem on Mac.
-
-2.2: - Really fix the Mac compilation problem.
- - Mac: fix crash due to wrong object releasing.
- - Mac: Fix memory leak.
-
-2.3: - Windows: Force creation of internal widget to make it work
- with Qt 4.2.
-
-2.4: - Fix the system for automatic window raising on message
- reception. NOTE: minor API change.
-
-2.5: - Mac: Fix isRunning() to work and report correctly.
-
-2.6: - - initialize() is now obsolete, no longer necessary to call
- it
- - - Fixed race condition where multiple instances migth be started
- - - QtSingleCoreApplication variant provided for non-GUI (console)
- usage
- - Complete reimplementation. Visible changes:
- - LGPL release.
-
diff --git a/src/qtsingleapplication/buildlib/buildlib.pro b/src/qtsingleapplication/buildlib/buildlib.pro
deleted file mode 100644
index 37dddcda..00000000
--- a/src/qtsingleapplication/buildlib/buildlib.pro
+++ /dev/null
@@ -1,13 +0,0 @@
-TEMPLATE=lib
-CONFIG += qt dll qtsingleapplication-buildlib
-mac:CONFIG += absolute_library_soname
-win32|mac:!wince*:!win32-msvc:!macx-xcode:CONFIG += debug_and_release build_all
-include(../src/qtsingleapplication.pri)
-TARGET = $$QTSINGLEAPPLICATION_LIBNAME
-DESTDIR = $$QTSINGLEAPPLICATION_LIBDIR
-win32 {
- DLLDESTDIR = $$[QT_INSTALL_BINS]
- QMAKE_DISTCLEAN += $$[QT_INSTALL_BINS]\\$${QTSINGLEAPPLICATION_LIBNAME}.dll
-}
-target.path = $$DESTDIR
-INSTALLS += target
diff --git a/src/qtsingleapplication/common.pri b/src/qtsingleapplication/common.pri
deleted file mode 100644
index 924c57c8..00000000
--- a/src/qtsingleapplication/common.pri
+++ /dev/null
@@ -1,14 +0,0 @@
-exists(config.pri):infile(config.pri, SOLUTIONS_LIBRARY, yes): CONFIG += qtsingleapplication-uselib
-
-TEMPLATE += fakelib
-greaterThan(QT_MAJOR_VERSION, 5)|\
- if(equals(QT_MAJOR_VERSION, 5):greaterThan(QT_MINOR_VERSION, 4))|\
- if(equals(QT_MAJOR_VERSION, 5):equals(QT_MINOR_VERSION, 4):greaterThan(QT_PATCH_VERSION, 1)) {
- QTSINGLEAPPLICATION_LIBNAME = $$qt5LibraryTarget(QtSolutions_SingleApplication-head)
-} else {
- QTSINGLEAPPLICATION_LIBNAME = $$qtLibraryTarget(QtSolutions_SingleApplication-head)
-}
-TEMPLATE -= fakelib
-
-QTSINGLEAPPLICATION_LIBDIR = $$PWD/lib
-unix:qtsingleapplication-uselib:!qtsingleapplication-buildlib:QMAKE_RPATHDIR += $$QTSINGLEAPPLICATION_LIBDIR
diff --git a/src/qtsingleapplication/configure b/src/qtsingleapplication/configure
deleted file mode 100755
index 3c4edfff..00000000
--- a/src/qtsingleapplication/configure
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/bin/sh
-
-if [ "x$1" != "x" -a "x$1" != "x-library" ]; then
- echo "Usage: $0 [-library]"
- echo
- echo "-library: Build the component as a dynamic library (DLL). Default is to"
- echo " include the component source code directly in the application."
- echo
- exit 0
-fi
-
-rm -f config.pri
-if [ "x$1" = "x-library" ]; then
- echo "Configuring to build this component as a dynamic library."
- echo "SOLUTIONS_LIBRARY = yes" > config.pri
-fi
-
-echo
-echo "This component is now configured."
-echo
-echo "To build the component library (if requested) and example(s),"
-echo "run qmake and your make command."
-echo
-echo "To remove or reconfigure, run make distclean."
-echo
diff --git a/src/qtsingleapplication/configure.bat b/src/qtsingleapplication/configure.bat
deleted file mode 100644
index 69efec35..00000000
--- a/src/qtsingleapplication/configure.bat
+++ /dev/null
@@ -1,80 +0,0 @@
-:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-::
-:: Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-:: Contact: http://www.qt-project.org/legal
-::
-:: This file is part of the Qt Solutions component.
-::
-:: $QT_BEGIN_LICENSE:BSD$
-:: You may use this file under the terms of the BSD license as follows:
-::
-:: "Redistribution and use in source and binary forms, with or without
-:: modification, are permitted provided that the following conditions are
-:: met:
-:: * Redistributions of source code must retain the above copyright
-:: notice, this list of conditions and the following disclaimer.
-:: * Redistributions in binary form must reproduce the above copyright
-:: notice, this list of conditions and the following disclaimer in
-:: the documentation and/or other materials provided with the
-:: distribution.
-:: * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
-:: of its contributors may be used to endorse or promote products derived
-:: from this software without specific prior written permission.
-::
-::
-:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-:: "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-:: LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-:: A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-:: OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-:: LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-:: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-:: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-:: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-:: OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-::
-:: $QT_END_LICENSE$
-::
-:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-
-@echo off
-
-rem
-rem "Main"
-rem
-
-if not "%1"=="" (
- if not "%1"=="-library" (
- call :PrintUsage
- goto EOF
- )
-)
-
-if exist config.pri. del config.pri
-if "%1"=="-library" (
- echo Configuring to build this component as a dynamic library.
- echo SOLUTIONS_LIBRARY = yes > config.pri
-)
-
-echo .
-echo This component is now configured.
-echo .
-echo To build the component library (if requested) and example(s),
-echo run qmake and your make or nmake command.
-echo .
-echo To remove or reconfigure, run make (nmake) distclean.
-echo .
-goto EOF
-
-:PrintUsage
-echo Usage: configure.bat [-library]
-echo .
-echo -library: Build the component as a dynamic library (DLL). Default is to
-echo include the component source directly in the application.
-echo A DLL may be preferable for technical or licensing (LGPL) reasons.
-echo .
-goto EOF
-
-
-:EOF
diff --git a/src/qtsingleapplication/doc/html/classic.css b/src/qtsingleapplication/doc/html/classic.css
deleted file mode 100644
index b8cae8e1..00000000
--- a/src/qtsingleapplication/doc/html/classic.css
+++ /dev/null
@@ -1,284 +0,0 @@
-BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV {
- font-family: Arial, Geneva, Helvetica, sans-serif;
-}
-H1 {
- text-align: center;
- font-size: 160%;
-}
-H2 {
- font-size: 120%;
-}
-H3 {
- font-size: 100%;
-}
-
-h3.fn,span.fn
-{
- background-color: #eee;
- border-width: 1px;
- border-style: solid;
- border-color: #ddd;
- font-weight: bold;
- padding: 6px 0px 6px 10px;
- margin: 42px 0px 0px 0px;
-}
-
-hr {
- border: 0;
- color: #a0a0a0;
- background-color: #ccc;
- height: 1px;
- width: 100%;
- text-align: left;
- margin: 34px 0px 34px 0px;
-}
-
-table.valuelist {
- border-width: 1px 1px 1px 1px;
- border-style: solid;
- border-color: #dddddd;
- border-collapse: collapse;
- background-color: #f0f0f0;
-}
-
-table.indextable {
- border-width: 1px 1px 1px 1px;
- border-style: solid;
- border-collapse: collapse;
- background-color: #f0f0f0;
- border-color:#555;
- font-size: 100%;
-}
-
-table td.largeindex {
- border-width: 1px 1px 1px 1px;
- border-collapse: collapse;
- background-color: #f0f0f0;
- border-color:#555;
- font-size: 120%;
-}
-
-table.valuelist th {
- border-width: 1px 1px 1px 2px;
- padding: 4px;
- border-style: solid;
- border-color: #666;
- color:white;
- background-color:#666;
-}
-
-th.titleheader {
- border-width: 1px 0px 1px 0px;
- padding: 2px;
- border-style: solid;
- border-color: #666;
- color:white;
- background-color:#555;
- background-image:url('images/gradient.png')};
- background-repeat: repeat-x;
- font-size: 100%;
-}
-
-
-th.largeheader {
- border-width: 1px 0px 1px 0px;
- padding: 4px;
- border-style: solid;
- border-color: #444;
- color:white;
- background-color:#555555;
- font-size: 120%;
-}
-
-p {
-
- margin-left: 4px;
- margin-top: 8px;
- margin-bottom: 8px;
-}
-
-a:link
-{
- color: #0046ad;
- text-decoration: none
-}
-
-a:visited
-{
- color: #672967;
- text-decoration: none
-}
-
-a.obsolete
-{
- color: #661100;
- text-decoration: none
-}
-
-a.compat
-{
- color: #661100;
- text-decoration: none
-}
-
-a.obsolete:visited
-{
- color: #995500;
- text-decoration: none
-}
-
-a.compat:visited
-{
- color: #995500;
- text-decoration: none
-}
-
-body
-{
- background: #ffffff;
- color: black
-}
-
-table.generic, table.annotated
-{
- border-width: 1px;
- border-color:#bbb;
- border-style:solid;
- border-collapse:collapse;
-}
-
-table td.memItemLeft {
- width: 180px;
- padding: 2px 0px 0px 8px;
- margin: 4px;
- border-width: 1px;
- border-color: #E0E0E0;
- border-style: none;
- font-size: 100%;
- white-space: nowrap
-}
-
-table td.memItemRight {
- padding: 2px 8px 0px 8px;
- margin: 4px;
- border-width: 1px;
- border-color: #E0E0E0;
- border-style: none;
- font-size: 100%;
-}
-
-table tr.odd {
- background: #f0f0f0;
- color: black;
-}
-
-table tr.even {
- background: #e4e4e4;
- color: black;
-}
-
-table.annotated th {
- padding: 3px;
- text-align: left
-}
-
-table.annotated td {
- padding: 3px;
-}
-
-table tr pre
-{
- padding-top: 0px;
- padding-bottom: 0px;
- padding-left: 0px;
- padding-right: 0px;
- border: none;
- background: none
-}
-
-tr.qt-style
-{
- background: #96E066;
- color: black
-}
-
-body pre
-{
- padding: 0.2em;
- border: #e7e7e7 1px solid;
- background: #f1f1f1;
- color: black
-}
-
-table tr.qt-code pre
-{
- padding: 0.2em;
- border: #e7e7e7 1px solid;
- background: #f1f1f1;
- color: black
-}
-
-span.preprocessor, span.preprocessor a
-{
- color: darkblue;
-}
-
-span.comment
-{
- color: darkred;
- font-style: italic
-}
-
-span.string,span.char
-{
- color: darkgreen;
-}
-
-.title
-{
- text-align: center
-}
-
-.subtitle
-{
- font-size: 0.8em
-}
-
-.small-subtitle
-{
- font-size: 0.65em
-}
-
-.qmlitem {
- padding: 0;
-}
-
-.qmlname {
- white-space: nowrap;
-}
-
-.qmltype {
- text-align: center;
- font-size: 160%;
-}
-
-.qmlproto {
- background-color: #eee;
- border-width: 1px;
- border-style: solid;
- border-color: #ddd;
- font-weight: bold;
- padding: 6px 10px 6px 10px;
- margin: 42px 0px 0px 0px;
-}
-
-.qmlreadonly {
- float: right;
- color: red
-}
-
-.qmldoc {
-}
-
-*.qmlitem p {
-}
diff --git a/src/qtsingleapplication/doc/html/images/qt-logo.png b/src/qtsingleapplication/doc/html/images/qt-logo.png
deleted file mode 100644
index 794162f5..00000000
Binary files a/src/qtsingleapplication/doc/html/images/qt-logo.png and /dev/null differ
diff --git a/src/qtsingleapplication/doc/html/index.html b/src/qtsingleapplication/doc/html/index.html
deleted file mode 100644
index af9dab10..00000000
--- a/src/qtsingleapplication/doc/html/index.html
+++ /dev/null
@@ -1,48 +0,0 @@
-
-
-
-
-
- Single Application
-
-
-
-
The QtSingleApplication component provides support for applications that can be only started once per user.
-
For some applications it is useful or even critical that they are started only once by any user. Future attempts to start the application should activate any already running instance, and possibly perform requested actions, e.g. loading a file, in that instance.
-
The QtSingleApplication class provides an interface to detect a running instance, and to send command strings to that instance. For console (non-GUI) applications, the QtSingleCoreApplication variant is provided, which avoids dependency on QtGui.
The application in this example loads or prints the documents passed as commandline parameters to further instances of this application.
-
/****************************************************************************
- **
- ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
- ** Contact: http://www.qt-project.org/legal
- **
- ** This file is part of the Qt Solutions component.
- **
- ** You may use this file under the terms of the BSD license as follows:
- **
- ** "Redistribution and use in source and binary forms, with or without
- ** modification, are permitted provided that the following conditions are
- ** met:
- ** * Redistributions of source code must retain the above copyright
- ** notice, this list of conditions and the following disclaimer.
- ** * Redistributions in binary form must reproduce the above copyright
- ** notice, this list of conditions and the following disclaimer in
- ** the documentation and/or other materials provided with the
- ** distribution.
- ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
- ** the names of its contributors may be used to endorse or promote
- ** products derived from this software without specific prior written
- ** permission.
- **
- ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
- **
- ****************************************************************************/
-
- #include <qtsingleapplication.h>
- #include <QtCore/QFile>
- #include <QtGui/QMainWindow>
- #include <QtGui/QPrinter>
- #include <QtGui/QPainter>
- #include <QtGui/QTextEdit>
- #include <QtGui/QMdiArea>
- #include <QtCore/QTextStream>
-
- class MainWindow : public QMainWindow
- {
- Q_OBJECT
- public:
- MainWindow();
-
- public slots:
- void handleMessage(const QString& message);
-
- signals:
- void needToShow();
-
- private:
- QMdiArea *workspace;
- };
-
The user interface in this application is a QMainWindow subclass with a QMdiArea as the central widget. It implements a slot handleMessage() that will be connected to the messageReceived() signal of the QtSingleApplication class.
The handleMessage() slot interprets the message passed in as a filename that can be prepended with /print to indicate that the file should just be printed rather than loaded.
#include "main.moc"
-
- int main(int argc, char **argv)
- {
- QtSingleApplication instance("File loader QtSingleApplication example", argc, argv);
- QString message;
- for (int a = 1; a < argc; ++a) {
- message += argv[a];
- if (a < argc-1)
- message += " ";
- }
-
- if (instance.sendMessage(message))
- return 0;
-
The main entry point function creates a QtSingleApplication object, and creates a message to send to a running instance of the application. If the message was sent successfully the process exits immediately.
If the message could not be sent the application starts up. Note that false is passed to the call to setActivationWindow() to prevent automatic activation for every message received, e.g. when the application should just print a file. Instead, the message handling function determines whether activation is requested, and signals that by emitting the needToShow() signal. This is then simply connected directly to QtSingleApplication's activateWindow() slot.
The application in this example has a log-view that displays messages sent by further instances of the same application.
-
The example demonstrates the use of the QtSingleApplication class to detect and communicate with a running instance of the application using the sendMessage() API. The messageReceived() signal is used to display received messages in a QTextEdit log.
-
/****************************************************************************
- **
- ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
- ** Contact: http://www.qt-project.org/legal
- **
- ** This file is part of the Qt Solutions component.
- **
- ** You may use this file under the terms of the BSD license as follows:
- **
- ** "Redistribution and use in source and binary forms, with or without
- ** modification, are permitted provided that the following conditions are
- ** met:
- ** * Redistributions of source code must retain the above copyright
- ** notice, this list of conditions and the following disclaimer.
- ** * Redistributions in binary form must reproduce the above copyright
- ** notice, this list of conditions and the following disclaimer in
- ** the documentation and/or other materials provided with the
- ** distribution.
- ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
- ** the names of its contributors may be used to endorse or promote
- ** products derived from this software without specific prior written
- ** permission.
- **
- ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
- **
- ****************************************************************************/
-
- #include <qtsingleapplication.h>
- #include <QtGui/QTextEdit>
-
- class TextEdit : public QTextEdit
- {
- Q_OBJECT
- public:
- TextEdit(QWidget *parent = 0)
- : QTextEdit(parent)
- {}
- public slots:
- void append(const QString &str)
- {
- QTextEdit::append(str);
- }
- };
-
- #include "main.moc"
-
- int main(int argc, char **argv)
- {
- QtSingleApplication instance(argc, argv);
-
The example has only the main entry point function. A QtSingleApplication object is created immediately.
-
if (instance.sendMessage("Wake up!"))
- return 0;
-
If another instance of this application is already running, sendMessage() will succeed, and this instance just exits immediately.
The logview object is also set as the application's activation window. Every time a message is received, the window will be raised and activated automatically.
-
The messageReceived() signal is also connected to the QTextEdit's append() slot. Every message received from further instances of this application will be displayed in the log.
The QtSingleApplication class provides an API to detect and communicate with running instances of an application.
-
This class allows you to create applications where only one instance should be running at a time. I.e., if the user tries to launch another instance, the already running instance will be activated instead. Another usecase is a client-server system, where the first started instance will assume the role of server, and the later instances will act as clients of that server.
-
By default, the full path of the executable file is used to determine whether two processes are instances of the same application. You can also provide an explicit identifier string that will be compared instead.
-
The application should create the QtSingleApplication object early in the startup phase, and call isRunning() to find out if another instance of this application is already running. If isRunning() returns false, it means that no other instance is running, and this instance has assumed the role as the running instance. In this case, the application should continue with the initialization of the application user interface before entering the event loop with exec(), as normal.
-
The messageReceived() signal will be emitted when the running application receives messages from another instance of the same application. When a message is received it might be helpful to the user to raise the application so that it becomes visible. To facilitate this, QtSingleApplication provides the setActivationWindow() function and the activateWindow() slot.
-
If isRunning() returns true, another instance is already running. It may be alerted to the fact that another instance has started by using the sendMessage() function. Also data such as startup parameters (e.g. the name of the file the user wanted this new instance to open) can be passed to the running instance with this function. Then, the application should terminate (or enter client mode).
-
If isRunning() returns true, but sendMessage() fails, that is an indication that the running instance is frozen.
-
Here's an example that shows how to convert an existing application to use QtSingleApplication. It is very simple and does not make use of all QtSingleApplication's functionality (see the examples for that).
Once this QtSingleApplication instance is destroyed (normally when the process exits or crashes), when the user next attempts to run the application this instance will not, of course, be encountered. The next instance to call isRunning() or sendMessage() will assume the role as the new running instance.
-
For console (non-GUI) applications, QtSingleCoreApplication may be used instead of this class, to avoid the dependency on the QtGui library.
Special constructor for X11, ref. the documentation of QApplication's corresponding constructor. The application identifier will be QCoreApplication::applicationFilePath(). dpy, argc, argv, visual, and cmap are passed on to the QApplication constructor.
Special constructor for X11, ref. the documentation of QApplication's corresponding constructor. The application identifier will be appId. dpy, argc, argv, visual, and cmap are passed on to the QApplication constructor.
De-minimizes, raises, and activates this application's activation window. This function does nothing if no activation window has been set.
-
This is a convenience function to show the user that this application instance has been activated when he has tried to start another instance.
-
This function should typically be called in response to the messageReceived() signal. By default, that will happen automatically, if an activation window has been set.
Tries to send the text message to the currently running instance. The QtSingleApplication object in the running instance will emit the messageReceived() signal when it receives the message.
-
This function returns true if the message has been sent to, and processed by, the current instance. If there is no instance currently running, or if the running instance fails to process the message within timeout milliseconds, this function return false.
Sets the activation window of this application to aw. The activation window is the widget that will be activated by activateWindow(). This is typically the application's main window.
-
If activateOnMessage is true (the default), the window will be activated automatically every time a message is received, just prior to the messageReceived() signal being emitted.
/****************************************************************************
- **
- ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
- ** Contact: http://www.qt-project.org/legal
- **
- ** This file is part of the Qt Solutions component.
- **
- ** You may use this file under the terms of the BSD license as follows:
- **
- ** "Redistribution and use in source and binary forms, with or without
- ** modification, are permitted provided that the following conditions are
- ** met:
- ** * Redistributions of source code must retain the above copyright
- ** notice, this list of conditions and the following disclaimer.
- ** * Redistributions in binary form must reproduce the above copyright
- ** notice, this list of conditions and the following disclaimer in
- ** the documentation and/or other materials provided with the
- ** distribution.
- ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
- ** the names of its contributors may be used to endorse or promote
- ** products derived from this software without specific prior written
- ** permission.
- **
- ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
- **
- ****************************************************************************/
-
- #include "qtsinglecoreapplication.h"
- #include <QtCore/QDebug>
-
- void report(const QString& msg)
- {
- qDebug("[%i] %s", (int)QCoreApplication::applicationPid(), qPrintable(msg));
- }
-
- class MainClass : public QObject
- {
- Q_OBJECT
- public:
- MainClass()
- : QObject()
- {}
-
- public slots:
- void handleMessage(const QString& message)
- {
- report( "Message received: \"" + message + "\"");
- }
- };
-
- int main(int argc, char **argv)
- {
- report("Starting up");
-
- QtSingleCoreApplication app(argc, argv);
-
- if (app.isRunning()) {
- QString msg(QString("Hi master, I am %1.").arg(QCoreApplication::applicationPid()));
- bool sentok = app.sendMessage(msg, 2000);
- QString rep("Another instance is running, so I will exit.");
- rep += sentok ? " Message sent ok." : " Message sending failed; the other instance may be frozen.";
- report(rep);
- return 0;
- } else {
- report("No other instance is running; so I will.");
- MainClass mainObj;
- QObject::connect(&app, SIGNAL(messageReceived(const QString&)),
- &mainObj, SLOT(handleMessage(const QString&)));
- return app.exec();
- }
- }
-
- #include "main.moc"
The API and usage is identical to QtSingleApplication, except that functions relating to the "activation window" are not present, for obvious reasons. Please refer to the QtSingleApplication documentation for explanation of the usage.
-
A QtSingleCoreApplication instance can communicate to a QtSingleApplication instance if they share the same application id. Hence, this class can be used to create a light-weight command-line tool that sends commands to a GUI application.
Tries to send the text message to the currently running instance. The QtSingleCoreApplication object in the running instance will emit the messageReceived() signal when it receives the message.
-
This function returns true if the message has been sent to, and processed by, the current instance. If there is no instance currently running, or if the running instance fails to process the message within timeout milliseconds, this function return false.
-
diff --git a/src/qtsingleapplication/doc/images/qt-logo.png b/src/qtsingleapplication/doc/images/qt-logo.png
deleted file mode 100644
index 794162f5..00000000
Binary files a/src/qtsingleapplication/doc/images/qt-logo.png and /dev/null differ
diff --git a/src/qtsingleapplication/doc/index.qdoc b/src/qtsingleapplication/doc/index.qdoc
deleted file mode 100644
index 6a2a768a..00000000
--- a/src/qtsingleapplication/doc/index.qdoc
+++ /dev/null
@@ -1,87 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the Qt Solutions component.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
-** of its contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-/*!
- \page index.html
- \title Single Application
-
- \section1 Description
-
- The QtSingleApplication component provides support
- for applications that can be only started once per user.
-
-
-
- For some applications it is useful or even critical that they are started
- only once by any user. Future attempts to start the application should
- activate any already running instance, and possibly perform requested
- actions, e.g. loading a file, in that instance.
-
- The QtSingleApplication class provides an interface to detect a running
- instance, and to send command strings to that instance.
- For console (non-GUI) applications, the QtSingleCoreApplication variant is provided, which avoids dependency on QtGui.
-
-
-
-
- \section1 Classes
- \list
- \i QtSingleApplication \i QtSingleCoreApplication\endlist
-
- \section1 Examples
- \list
- \i \link qtsingleapplication-example-trivial.html A Trivial Example \endlink \i \link qtsingleapplication-example-loader.html Loading Documents \endlink \i \link qtsinglecoreapplication-example-console.html A Non-GUI Example \endlink \endlist
-
-
-
-
-
-
- \section1 Tested platforms
- \list
- \i Qt 4.4, 4.5 / Windows XP / MSVC.NET 2005
- \i Qt 4.4, 4.5 / Linux / gcc
- \i Qt 4.4, 4.5 / MacOS X 10.5 / gcc
- \endlist
-
-
-
-
-*/
diff --git a/src/qtsingleapplication/examples/console/console.pro b/src/qtsingleapplication/examples/console/console.pro
deleted file mode 100644
index e0390e23..00000000
--- a/src/qtsingleapplication/examples/console/console.pro
+++ /dev/null
@@ -1,5 +0,0 @@
-TEMPLATE = app
-CONFIG += console
-SOURCES += main.cpp
-include(../../src/qtsinglecoreapplication.pri)
-QT -= gui
diff --git a/src/qtsingleapplication/examples/console/console.qdoc b/src/qtsingleapplication/examples/console/console.qdoc
deleted file mode 100644
index 77b0d736..00000000
--- a/src/qtsingleapplication/examples/console/console.qdoc
+++ /dev/null
@@ -1,65 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the Qt Solutions component.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
-** of its contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-/*! \page qtsinglecoreapplication-example-console.html
- \title A non-GUI example
-
- This example shows how to use the single-application functionality
- in a console application. It does not require the \c QtGui library
- at all.
-
- The only differences from the GUI application usage demonstrated
- in the other examples are:
-
- 1) The \c.pro file should include \c qtsinglecoreapplication.pri
- instead of \c qtsingleapplication.pri
-
- 2) The class name is \c QtSingleCoreApplication instead of \c
- QtSingleApplication.
-
- 3) No calls are made regarding window activation, for obvious reasons.
-
- console.pro:
- \quotefile console/console.pro
-
- main.cpp:
- \quotefile console/main.cpp
-
-*/
diff --git a/src/qtsingleapplication/examples/console/main.cpp b/src/qtsingleapplication/examples/console/main.cpp
deleted file mode 100644
index 652feb93..00000000
--- a/src/qtsingleapplication/examples/console/main.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the Qt Solutions component.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
-** of its contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-#include "qtsinglecoreapplication.h"
-#include
-
-
-void report(const QString& msg)
-{
- qDebug("[%i] %s", (int)QCoreApplication::applicationPid(), qPrintable(msg));
-}
-
-class MainClass : public QObject
-{
- Q_OBJECT
-public:
- MainClass()
- : QObject()
- {}
-
-public slots:
- void handleMessage(const QString& message)
- {
- report( "Message received: \"" + message + "\"");
- }
-};
-
-int main(int argc, char **argv)
-{
- report("Starting up");
-
- QtSingleCoreApplication app(argc, argv);
-
- if (app.isRunning()) {
- QString msg(QString("Hi master, I am %1.").arg(QCoreApplication::applicationPid()));
- bool sentok = app.sendMessage(msg, 2000);
- QString rep("Another instance is running, so I will exit.");
- rep += sentok ? " Message sent ok." : " Message sending failed; the other instance may be frozen.";
- report(rep);
- return 0;
- } else {
- report("No other instance is running; so I will.");
- MainClass mainObj;
- QObject::connect(&app, SIGNAL(messageReceived(const QString&)),
- &mainObj, SLOT(handleMessage(const QString&)));
- return app.exec();
- }
-}
-
-
-#include "main.moc"
diff --git a/src/qtsingleapplication/examples/examples.pro b/src/qtsingleapplication/examples/examples.pro
deleted file mode 100644
index 36b8fd38..00000000
--- a/src/qtsingleapplication/examples/examples.pro
+++ /dev/null
@@ -1,4 +0,0 @@
-TEMPLATE = subdirs
-SUBDIRS = trivial \
- loader \
- console
diff --git a/src/qtsingleapplication/examples/loader/file1.qsl b/src/qtsingleapplication/examples/loader/file1.qsl
deleted file mode 100644
index 50fcd26d..00000000
--- a/src/qtsingleapplication/examples/loader/file1.qsl
+++ /dev/null
@@ -1 +0,0 @@
-File 1
diff --git a/src/qtsingleapplication/examples/loader/file2.qsl b/src/qtsingleapplication/examples/loader/file2.qsl
deleted file mode 100644
index 4475433e..00000000
--- a/src/qtsingleapplication/examples/loader/file2.qsl
+++ /dev/null
@@ -1 +0,0 @@
-File 2
diff --git a/src/qtsingleapplication/examples/loader/loader.pro b/src/qtsingleapplication/examples/loader/loader.pro
deleted file mode 100644
index 3e52586b..00000000
--- a/src/qtsingleapplication/examples/loader/loader.pro
+++ /dev/null
@@ -1,6 +0,0 @@
-greaterThan(QT_MAJOR_VERSION, 4): QT += printsupport
-TEMPLATE = app
-
-include(../../src/qtsingleapplication.pri)
-
-SOURCES += main.cpp
diff --git a/src/qtsingleapplication/examples/loader/loader.qdoc b/src/qtsingleapplication/examples/loader/loader.qdoc
deleted file mode 100644
index bfd15d06..00000000
--- a/src/qtsingleapplication/examples/loader/loader.qdoc
+++ /dev/null
@@ -1,81 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the Qt Solutions component.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
-** of its contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-/*! \page qtsingleapplication-example-loader.html
- \title Loading Documents
-
- The application in this example loads or prints the documents
- passed as commandline parameters to further instances of this
- application.
-
- \quotefromfile loader/main.cpp
- \printuntil };
- The user interface in this application is a QMainWindow subclass
- with a QMdiArea as the central widget. It implements a slot
- \c handleMessage() that will be connected to the messageReceived()
- signal of the QtSingleApplication class.
-
- \printuntil }
- The MainWindow constructor creates a minimal user interface.
-
- \printto case Print:
- The handleMessage() slot interprets the message passed in as a
- filename that can be prepended with \e /print to indicate that
- the file should just be printed rather than loaded.
-
- \printto #include
- Loading the file will also activate the window.
-
- \printto mw
- The \c main entry point function creates a QtSingleApplication
- object, and creates a message to send to a running instance
- of the application. If the message was sent successfully the
- process exits immediately.
-
- \printuntil }
- If the message could not be sent the application starts up. Note
- that \c false is passed to the call to setActivationWindow() to
- prevent automatic activation for every message received, e.g. when
- the application should just print a file. Instead, the message
- handling function determines whether activation is requested, and
- signals that by emitting the needToShow() signal. This is then
- simply connected directly to QtSingleApplication's
- activateWindow() slot.
-*/
diff --git a/src/qtsingleapplication/examples/loader/main.cpp b/src/qtsingleapplication/examples/loader/main.cpp
deleted file mode 100644
index f55e57ac..00000000
--- a/src/qtsingleapplication/examples/loader/main.cpp
+++ /dev/null
@@ -1,152 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the Qt Solutions component.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
-** of its contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-class MainWindow : public QMainWindow
-{
- Q_OBJECT
-public:
- MainWindow();
-
-public slots:
- void handleMessage(const QString& message);
-
-signals:
- void needToShow();
-
-private:
- QMdiArea *workspace;
-};
-
-MainWindow::MainWindow()
-{
- workspace = new QMdiArea(this);
-
- setCentralWidget(workspace);
-}
-
-void MainWindow::handleMessage(const QString& message)
-{
- enum Action {
- Nothing,
- Open,
- Print
- } action;
-
- action = Nothing;
- QString filename = message;
- if (message.toLower().startsWith("/print ")) {
- filename = filename.mid(7);
- action = Print;
- } else if (!message.isEmpty()) {
- action = Open;
- }
- if (action == Nothing) {
- emit needToShow();
- return;
- }
-
- QFile file(filename);
- QString contents;
- if (file.open(QIODevice::ReadOnly))
- contents = file.readAll();
- else
- contents = "[[Error: Could not load file " + filename + "]]";
-
- QTextEdit *view = new QTextEdit;
- view->setPlainText(contents);
-
- switch(action) {
- case Print:
- {
- QPrinter printer;
- view->print(&printer);
- delete view;
- }
- break;
-
- case Open:
- {
- workspace->addSubWindow(view);
- view->setWindowTitle(message);
- view->show();
- emit needToShow();
- }
- break;
- default:
- break;
- };
-}
-
-#include "main.moc"
-
-int main(int argc, char **argv)
-{
- QtSingleApplication instance("File loader QtSingleApplication example", argc, argv);
- QString message;
- for (int a = 1; a < argc; ++a) {
- message += argv[a];
- if (a < argc-1)
- message += " ";
- }
-
- if (instance.sendMessage(message))
- return 0;
-
- MainWindow mw;
- mw.handleMessage(message);
- mw.show();
-
- QObject::connect(&instance, SIGNAL(messageReceived(const QString&)),
- &mw, SLOT(handleMessage(const QString&)));
-
- instance.setActivationWindow(&mw, false);
- QObject::connect(&mw, SIGNAL(needToShow()), &instance, SLOT(activateWindow()));
-
- return instance.exec();
-}
diff --git a/src/qtsingleapplication/examples/trivial/main.cpp b/src/qtsingleapplication/examples/trivial/main.cpp
deleted file mode 100644
index 69e102f3..00000000
--- a/src/qtsingleapplication/examples/trivial/main.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the Qt Solutions component.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
-** of its contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include
-#include
-
-class TextEdit : public QTextEdit
-{
- Q_OBJECT
-public:
- TextEdit(QWidget *parent = 0)
- : QTextEdit(parent)
- {}
-public slots:
- void append(const QString &str)
- {
- QTextEdit::append(str);
- }
-};
-
-#include "main.moc"
-
-
-
-int main(int argc, char **argv)
-{
- QtSingleApplication instance(argc, argv);
- if (instance.sendMessage("Wake up!"))
- return 0;
-
- TextEdit logview;
- logview.setReadOnly(true);
- logview.show();
-
- instance.setActivationWindow(&logview);
-
- QObject::connect(&instance, SIGNAL(messageReceived(const QString&)),
- &logview, SLOT(append(const QString&)));
-
- return instance.exec();
-}
diff --git a/src/qtsingleapplication/examples/trivial/trivial.pro b/src/qtsingleapplication/examples/trivial/trivial.pro
deleted file mode 100644
index 673497a4..00000000
--- a/src/qtsingleapplication/examples/trivial/trivial.pro
+++ /dev/null
@@ -1,5 +0,0 @@
-TEMPLATE = app
-
-include(../../src/qtsingleapplication.pri)
-
-SOURCES += main.cpp
diff --git a/src/qtsingleapplication/examples/trivial/trivial.qdoc b/src/qtsingleapplication/examples/trivial/trivial.qdoc
deleted file mode 100644
index 9491cb65..00000000
--- a/src/qtsingleapplication/examples/trivial/trivial.qdoc
+++ /dev/null
@@ -1,76 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the Qt Solutions component.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
-** of its contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-/*! \page qtsingleapplication-example-trivial.html
- \title A Trivial Example
-
- The application in this example has a log-view that displays
- messages sent by further instances of the same application.
-
- The example demonstrates the use of the QtSingleApplication
- class to detect and communicate with a running instance of
- the application using the sendMessage() API. The messageReceived()
- signal is used to display received messages in a QTextEdit log.
-
- \quotefromfile trivial/main.cpp
- \printuntil instance
- The example has only the \c main entry point function.
- A QtSingleApplication object is created immediately.
-
- \printuntil return
- If another instance of this application is already running,
- sendMessage() will succeed, and this instance just exits
- immediately.
-
- \printuntil show()
- Otherwise the instance continues as normal and creates the
- user interface.
-
- \printuntil return instance.exec();
- The \c logview object is also set as the application's activation
- window. Every time a message is received, the window will be raised
- and activated automatically.
-
- The messageReceived() signal is also connected to the QTextEdit's
- append() slot. Every message received from further instances of
- this application will be displayed in the log.
-
- Finally the event loop is entered.
-*/
diff --git a/src/qtsingleapplication/qtsingleapplication.pro b/src/qtsingleapplication/qtsingleapplication.pro
deleted file mode 100644
index 07257c5d..00000000
--- a/src/qtsingleapplication/qtsingleapplication.pro
+++ /dev/null
@@ -1,5 +0,0 @@
-TEMPLATE=subdirs
-CONFIG += ordered
-include(common.pri)
-qtsingleapplication-uselib:SUBDIRS=buildlib
-SUBDIRS+=examples
diff --git a/src/qtsingleapplication/src/QtLockedFile b/src/qtsingleapplication/src/QtLockedFile
deleted file mode 100644
index 16b48ba9..00000000
--- a/src/qtsingleapplication/src/QtLockedFile
+++ /dev/null
@@ -1 +0,0 @@
-#include "qtlockedfile.h"
diff --git a/src/qtsingleapplication/src/QtSingleApplication b/src/qtsingleapplication/src/QtSingleApplication
deleted file mode 100644
index d111bf72..00000000
--- a/src/qtsingleapplication/src/QtSingleApplication
+++ /dev/null
@@ -1 +0,0 @@
-#include "qtsingleapplication.h"
diff --git a/src/qtsingleapplication/src/qtlocalpeer.cpp b/src/qtsingleapplication/src/qtlocalpeer.cpp
deleted file mode 100644
index f3c4546b..00000000
--- a/src/qtsingleapplication/src/qtlocalpeer.cpp
+++ /dev/null
@@ -1,213 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the Qt Solutions component.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
-** of its contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-#include "qtlocalpeer.h"
-#include
-#include
-#include
-
-#if defined(Q_OS_WIN)
-#include
-#include
-typedef BOOL(WINAPI*PProcessIdToSessionId)(DWORD,DWORD*);
-static PProcessIdToSessionId pProcessIdToSessionId = 0;
-#endif
-#if defined(Q_OS_UNIX)
-#include
-#include
-#include
-#endif
-
-namespace QtLP_Private {
-#include "qtlockedfile.cpp"
-#if defined(Q_OS_WIN)
-#include "qtlockedfile_win.cpp"
-#else
-#include "qtlockedfile_unix.cpp"
-#endif
-}
-
-const char* QtLocalPeer::ack = "ack";
-
-QtLocalPeer::QtLocalPeer(QObject* parent, const QString &appId)
- : QObject(parent), id(appId)
-{
- QString prefix = id;
- if (id.isEmpty()) {
- id = QCoreApplication::applicationFilePath();
-#if defined(Q_OS_WIN)
- id = id.toLower();
-#endif
- prefix = id.section(QLatin1Char('/'), -1);
- }
- prefix.remove(QRegExp("[^a-zA-Z]"));
- prefix.truncate(6);
-
- QByteArray idc = id.toUtf8();
- quint16 idNum = qChecksum(idc.constData(), idc.size());
- socketName = QLatin1String("qtsingleapp-") + prefix
- + QLatin1Char('-') + QString::number(idNum, 16);
-
-#if defined(Q_OS_WIN)
- if (!pProcessIdToSessionId) {
- QLibrary lib("kernel32");
- pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve("ProcessIdToSessionId");
- }
- if (pProcessIdToSessionId) {
- DWORD sessionId = 0;
- pProcessIdToSessionId(GetCurrentProcessId(), &sessionId);
- socketName += QLatin1Char('-') + QString::number(sessionId, 16);
- }
-#else
- socketName += QLatin1Char('-') + QString::number(::getuid(), 16);
-#endif
-
- server = new QLocalServer(this);
- QString lockName = QDir(QDir::tempPath()).absolutePath()
- + QLatin1Char('/') + socketName
- + QLatin1String("-lockfile");
- lockFile.setFileName(lockName);
- lockFile.open(QIODevice::ReadWrite);
-}
-
-
-
-bool QtLocalPeer::isClient()
-{
- if (lockFile.isLocked())
- return false;
-
- if (!lockFile.lock(QtLP_Private::QtLockedFile::WriteLock, false))
- return true;
-
- bool res = server->listen(socketName);
-#if defined(Q_OS_UNIX) && (QT_VERSION >= QT_VERSION_CHECK(4,5,0))
- // ### Workaround
- if (!res && server->serverError() == QAbstractSocket::AddressInUseError) {
- QFile::remove(QDir::cleanPath(QDir::tempPath())+QLatin1Char('/')+socketName);
- res = server->listen(socketName);
- }
-#endif
- if (!res)
- qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(server->errorString()));
- QObject::connect(server, SIGNAL(newConnection()), SLOT(receiveConnection()));
- return false;
-}
-
-
-bool QtLocalPeer::sendMessage(const QString &message, int timeout)
-{
- if (!isClient())
- return false;
-
- QLocalSocket socket;
- bool connOk = false;
- for(int i = 0; i < 2; i++) {
- // Try twice, in case the other instance is just starting up
- socket.connectToServer(socketName);
- connOk = socket.waitForConnected(timeout/2);
- if (connOk || i)
- break;
- int ms = 250;
-#if defined(Q_OS_WIN)
- Sleep(DWORD(ms));
-#else
- struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 };
- nanosleep(&ts, NULL);
-#endif
- }
- if (!connOk)
- return false;
-
- QByteArray uMsg(message.toUtf8());
- QDataStream ds(&socket);
- ds.writeBytes(uMsg.constData(), uMsg.size());
- bool res = socket.waitForBytesWritten(timeout);
- if (res) {
- res &= socket.waitForReadyRead(timeout); // wait for ack
- if (res)
- res &= (socket.read(qstrlen(ack)) == ack);
- }
- return res;
-}
-
-
-void QtLocalPeer::receiveConnection()
-{
- QLocalSocket* socket = server->nextPendingConnection();
- if (!socket)
- return;
-
- while (true) {
- if (socket->state() == QLocalSocket::UnconnectedState) {
- qWarning("QtLocalPeer: Peer disconnected");
- delete socket;
- return;
- }
- if (socket->bytesAvailable() >= qint64(sizeof(quint32)))
- break;
- socket->waitForReadyRead();
- }
-
- QDataStream ds(socket);
- QByteArray uMsg;
- quint32 remaining;
- ds >> remaining;
- uMsg.resize(remaining);
- int got = 0;
- char* uMsgBuf = uMsg.data();
- do {
- got = ds.readRawData(uMsgBuf, remaining);
- remaining -= got;
- uMsgBuf += got;
- } while (remaining && got >= 0 && socket->waitForReadyRead(2000));
- if (got < 0) {
- qWarning("QtLocalPeer: Message reception failed %s", socket->errorString().toLatin1().constData());
- delete socket;
- return;
- }
- QString message(QString::fromUtf8(uMsg));
- socket->write(ack, qstrlen(ack));
- socket->waitForBytesWritten(1000);
- socket->waitForDisconnected(1000); // make sure client reads ack
- delete socket;
- emit messageReceived(message); //### (might take a long time to return)
-}
diff --git a/src/qtsingleapplication/src/qtlocalpeer.h b/src/qtsingleapplication/src/qtlocalpeer.h
deleted file mode 100644
index 1b533b1a..00000000
--- a/src/qtsingleapplication/src/qtlocalpeer.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the Qt Solutions component.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
-** of its contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QTLOCALPEER_H
-#define QTLOCALPEER_H
-
-#include
-#include
-#include
-
-#include "qtlockedfile.h"
-
-class QtLocalPeer : public QObject
-{
- Q_OBJECT
-
-public:
- QtLocalPeer(QObject *parent = 0, const QString &appId = QString());
- bool isClient();
- bool sendMessage(const QString &message, int timeout);
- QString applicationId() const
- { return id; }
-
-Q_SIGNALS:
- void messageReceived(const QString &message);
-
-protected Q_SLOTS:
- void receiveConnection();
-
-protected:
- QString id;
- QString socketName;
- QLocalServer* server;
- QtLP_Private::QtLockedFile lockFile;
-
-private:
- static const char* ack;
-};
-
-#endif // QTLOCALPEER_H
diff --git a/src/qtsingleapplication/src/qtlockedfile.cpp b/src/qtsingleapplication/src/qtlockedfile.cpp
deleted file mode 100644
index c142a863..00000000
--- a/src/qtsingleapplication/src/qtlockedfile.cpp
+++ /dev/null
@@ -1,193 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the Qt Solutions component.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
-** of its contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qtlockedfile.h"
-
-/*!
- \class QtLockedFile
-
- \brief The QtLockedFile class extends QFile with advisory locking
- functions.
-
- A file may be locked in read or write mode. Multiple instances of
- \e QtLockedFile, created in multiple processes running on the same
- machine, may have a file locked in read mode. Exactly one instance
- may have it locked in write mode. A read and a write lock cannot
- exist simultaneously on the same file.
-
- The file locks are advisory. This means that nothing prevents
- another process from manipulating a locked file using QFile or
- file system functions offered by the OS. Serialization is only
- guaranteed if all processes that access the file use
- QLockedFile. Also, while holding a lock on a file, a process
- must not open the same file again (through any API), or locks
- can be unexpectedly lost.
-
- The lock provided by an instance of \e QtLockedFile is released
- whenever the program terminates. This is true even when the
- program crashes and no destructors are called.
-*/
-
-/*! \enum QtLockedFile::LockMode
-
- This enum describes the available lock modes.
-
- \value ReadLock A read lock.
- \value WriteLock A write lock.
- \value NoLock Neither a read lock nor a write lock.
-*/
-
-/*!
- Constructs an unlocked \e QtLockedFile object. This constructor
- behaves in the same way as \e QFile::QFile().
-
- \sa QFile::QFile()
-*/
-QtLockedFile::QtLockedFile()
- : QFile()
-{
-#ifdef Q_OS_WIN
- wmutex = 0;
- rmutex = 0;
-#endif
- m_lock_mode = NoLock;
-}
-
-/*!
- Constructs an unlocked QtLockedFile object with file \a name. This
- constructor behaves in the same way as \e QFile::QFile(const
- QString&).
-
- \sa QFile::QFile()
-*/
-QtLockedFile::QtLockedFile(const QString &name)
- : QFile(name)
-{
-#ifdef Q_OS_WIN
- wmutex = 0;
- rmutex = 0;
-#endif
- m_lock_mode = NoLock;
-}
-
-/*!
- Opens the file in OpenMode \a mode.
-
- This is identical to QFile::open(), with the one exception that the
- Truncate mode flag is disallowed. Truncation would conflict with the
- advisory file locking, since the file would be modified before the
- write lock is obtained. If truncation is required, use resize(0)
- after obtaining the write lock.
-
- Returns true if successful; otherwise false.
-
- \sa QFile::open(), QFile::resize()
-*/
-bool QtLockedFile::open(OpenMode mode)
-{
- if (mode & QIODevice::Truncate) {
- qWarning("QtLockedFile::open(): Truncate mode not allowed.");
- return false;
- }
- return QFile::open(mode);
-}
-
-/*!
- Returns \e true if this object has a in read or write lock;
- otherwise returns \e false.
-
- \sa lockMode()
-*/
-bool QtLockedFile::isLocked() const
-{
- return m_lock_mode != NoLock;
-}
-
-/*!
- Returns the type of lock currently held by this object, or \e
- QtLockedFile::NoLock.
-
- \sa isLocked()
-*/
-QtLockedFile::LockMode QtLockedFile::lockMode() const
-{
- return m_lock_mode;
-}
-
-/*!
- \fn bool QtLockedFile::lock(LockMode mode, bool block = true)
-
- Obtains a lock of type \a mode. The file must be opened before it
- can be locked.
-
- If \a block is true, this function will block until the lock is
- aquired. If \a block is false, this function returns \e false
- immediately if the lock cannot be aquired.
-
- If this object already has a lock of type \a mode, this function
- returns \e true immediately. If this object has a lock of a
- different type than \a mode, the lock is first released and then a
- new lock is obtained.
-
- This function returns \e true if, after it executes, the file is
- locked by this object, and \e false otherwise.
-
- \sa unlock(), isLocked(), lockMode()
-*/
-
-/*!
- \fn bool QtLockedFile::unlock()
-
- Releases a lock.
-
- If the object has no lock, this function returns immediately.
-
- This function returns \e true if, after it executes, the file is
- not locked by this object, and \e false otherwise.
-
- \sa lock(), isLocked(), lockMode()
-*/
-
-/*!
- \fn QtLockedFile::~QtLockedFile()
-
- Destroys the \e QtLockedFile object. If any locks were held, they
- are released.
-*/
diff --git a/src/qtsingleapplication/src/qtlockedfile.h b/src/qtsingleapplication/src/qtlockedfile.h
deleted file mode 100644
index 84c18e5c..00000000
--- a/src/qtsingleapplication/src/qtlockedfile.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the Qt Solutions component.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
-** of its contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QTLOCKEDFILE_H
-#define QTLOCKEDFILE_H
-
-#include
-#ifdef Q_OS_WIN
-#include
-#endif
-
-#if defined(Q_OS_WIN)
-# if !defined(QT_QTLOCKEDFILE_EXPORT) && !defined(QT_QTLOCKEDFILE_IMPORT)
-# define QT_QTLOCKEDFILE_EXPORT
-# elif defined(QT_QTLOCKEDFILE_IMPORT)
-# if defined(QT_QTLOCKEDFILE_EXPORT)
-# undef QT_QTLOCKEDFILE_EXPORT
-# endif
-# define QT_QTLOCKEDFILE_EXPORT __declspec(dllimport)
-# elif defined(QT_QTLOCKEDFILE_EXPORT)
-# undef QT_QTLOCKEDFILE_EXPORT
-# define QT_QTLOCKEDFILE_EXPORT __declspec(dllexport)
-# endif
-#else
-# define QT_QTLOCKEDFILE_EXPORT
-#endif
-
-namespace QtLP_Private {
-
-class QT_QTLOCKEDFILE_EXPORT QtLockedFile : public QFile
-{
-public:
- enum LockMode { NoLock = 0, ReadLock, WriteLock };
-
- QtLockedFile();
- QtLockedFile(const QString &name);
- ~QtLockedFile();
-
- bool open(OpenMode mode);
-
- bool lock(LockMode mode, bool block = true);
- bool unlock();
- bool isLocked() const;
- LockMode lockMode() const;
-
-private:
-#ifdef Q_OS_WIN
- Qt::HANDLE wmutex;
- Qt::HANDLE rmutex;
- QVector rmutexes;
- QString mutexname;
-
- Qt::HANDLE getMutexHandle(int idx, bool doCreate);
- bool waitMutex(Qt::HANDLE mutex, bool doBlock);
-
-#endif
- LockMode m_lock_mode;
-};
-}
-#endif
diff --git a/src/qtsingleapplication/src/qtlockedfile_unix.cpp b/src/qtsingleapplication/src/qtlockedfile_unix.cpp
deleted file mode 100644
index 976c1b9e..00000000
--- a/src/qtsingleapplication/src/qtlockedfile_unix.cpp
+++ /dev/null
@@ -1,115 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the Qt Solutions component.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
-** of its contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include
-#include
-#include
-#include
-
-#include "qtlockedfile.h"
-
-bool QtLockedFile::lock(LockMode mode, bool block)
-{
- if (!isOpen()) {
- qWarning("QtLockedFile::lock(): file is not opened");
- return false;
- }
-
- if (mode == NoLock)
- return unlock();
-
- if (mode == m_lock_mode)
- return true;
-
- if (m_lock_mode != NoLock)
- unlock();
-
- struct flock fl;
- fl.l_whence = SEEK_SET;
- fl.l_start = 0;
- fl.l_len = 0;
- fl.l_type = (mode == ReadLock) ? F_RDLCK : F_WRLCK;
- int cmd = block ? F_SETLKW : F_SETLK;
- int ret = fcntl(handle(), cmd, &fl);
-
- if (ret == -1) {
- if (errno != EINTR && errno != EAGAIN)
- qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno));
- return false;
- }
-
-
- m_lock_mode = mode;
- return true;
-}
-
-
-bool QtLockedFile::unlock()
-{
- if (!isOpen()) {
- qWarning("QtLockedFile::unlock(): file is not opened");
- return false;
- }
-
- if (!isLocked())
- return true;
-
- struct flock fl;
- fl.l_whence = SEEK_SET;
- fl.l_start = 0;
- fl.l_len = 0;
- fl.l_type = F_UNLCK;
- int ret = fcntl(handle(), F_SETLKW, &fl);
-
- if (ret == -1) {
- qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno));
- return false;
- }
-
- m_lock_mode = NoLock;
- return true;
-}
-
-QtLockedFile::~QtLockedFile()
-{
- if (isOpen())
- unlock();
-}
-
diff --git a/src/qtsingleapplication/src/qtlockedfile_win.cpp b/src/qtsingleapplication/src/qtlockedfile_win.cpp
deleted file mode 100644
index 5e212620..00000000
--- a/src/qtsingleapplication/src/qtlockedfile_win.cpp
+++ /dev/null
@@ -1,211 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the Qt Solutions component.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
-** of its contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qtlockedfile.h"
-#include
-#include
-
-#define MUTEX_PREFIX "QtLockedFile mutex "
-// Maximum number of concurrent read locks. Must not be greater than MAXIMUM_WAIT_OBJECTS
-#define MAX_READERS MAXIMUM_WAIT_OBJECTS
-
-#if QT_VERSION >= 0x050000
-#define QT_WA(unicode, ansi) unicode
-#endif
-
-Qt::HANDLE QtLockedFile::getMutexHandle(int idx, bool doCreate)
-{
- if (mutexname.isEmpty()) {
- QFileInfo fi(*this);
- mutexname = QString::fromLatin1(MUTEX_PREFIX)
- + fi.absoluteFilePath().toLower();
- }
- QString mname(mutexname);
- if (idx >= 0)
- mname += QString::number(idx);
-
- Qt::HANDLE mutex;
- if (doCreate) {
- QT_WA( { mutex = CreateMutexW(NULL, FALSE, (TCHAR*)mname.utf16()); },
- { mutex = CreateMutexA(NULL, FALSE, mname.toLocal8Bit().constData()); } );
- if (!mutex) {
- qErrnoWarning("QtLockedFile::lock(): CreateMutex failed");
- return 0;
- }
- }
- else {
- QT_WA( { mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (TCHAR*)mname.utf16()); },
- { mutex = OpenMutexA(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, mname.toLocal8Bit().constData()); } );
- if (!mutex) {
- if (GetLastError() != ERROR_FILE_NOT_FOUND)
- qErrnoWarning("QtLockedFile::lock(): OpenMutex failed");
- return 0;
- }
- }
- return mutex;
-}
-
-bool QtLockedFile::waitMutex(Qt::HANDLE mutex, bool doBlock)
-{
- Q_ASSERT(mutex);
- DWORD res = WaitForSingleObject(mutex, doBlock ? INFINITE : 0);
- switch (res) {
- case WAIT_OBJECT_0:
- case WAIT_ABANDONED:
- return true;
- break;
- case WAIT_TIMEOUT:
- break;
- default:
- qErrnoWarning("QtLockedFile::lock(): WaitForSingleObject failed");
- }
- return false;
-}
-
-
-
-bool QtLockedFile::lock(LockMode mode, bool block)
-{
- if (!isOpen()) {
- qWarning("QtLockedFile::lock(): file is not opened");
- return false;
- }
-
- if (mode == NoLock)
- return unlock();
-
- if (mode == m_lock_mode)
- return true;
-
- if (m_lock_mode != NoLock)
- unlock();
-
- if (!wmutex && !(wmutex = getMutexHandle(-1, true)))
- return false;
-
- if (!waitMutex(wmutex, block))
- return false;
-
- if (mode == ReadLock) {
- int idx = 0;
- for (; idx < MAX_READERS; idx++) {
- rmutex = getMutexHandle(idx, false);
- if (!rmutex || waitMutex(rmutex, false))
- break;
- CloseHandle(rmutex);
- }
- bool ok = true;
- if (idx >= MAX_READERS) {
- qWarning("QtLockedFile::lock(): too many readers");
- rmutex = 0;
- ok = false;
- }
- else if (!rmutex) {
- rmutex = getMutexHandle(idx, true);
- if (!rmutex || !waitMutex(rmutex, false))
- ok = false;
- }
- if (!ok && rmutex) {
- CloseHandle(rmutex);
- rmutex = 0;
- }
- ReleaseMutex(wmutex);
- if (!ok)
- return false;
- }
- else {
- Q_ASSERT(rmutexes.isEmpty());
- for (int i = 0; i < MAX_READERS; i++) {
- Qt::HANDLE mutex = getMutexHandle(i, false);
- if (mutex)
- rmutexes.append(mutex);
- }
- if (rmutexes.size()) {
- DWORD res = WaitForMultipleObjects(rmutexes.size(), rmutexes.constData(),
- TRUE, block ? INFINITE : 0);
- if (res != WAIT_OBJECT_0 && res != WAIT_ABANDONED) {
- if (res != WAIT_TIMEOUT)
- qErrnoWarning("QtLockedFile::lock(): WaitForMultipleObjects failed");
- m_lock_mode = WriteLock; // trick unlock() to clean up - semiyucky
- unlock();
- return false;
- }
- }
- }
-
- m_lock_mode = mode;
- return true;
-}
-
-bool QtLockedFile::unlock()
-{
- if (!isOpen()) {
- qWarning("QtLockedFile::unlock(): file is not opened");
- return false;
- }
-
- if (!isLocked())
- return true;
-
- if (m_lock_mode == ReadLock) {
- ReleaseMutex(rmutex);
- CloseHandle(rmutex);
- rmutex = 0;
- }
- else {
- foreach(Qt::HANDLE mutex, rmutexes) {
- ReleaseMutex(mutex);
- CloseHandle(mutex);
- }
- rmutexes.clear();
- ReleaseMutex(wmutex);
- }
-
- m_lock_mode = QtLockedFile::NoLock;
- return true;
-}
-
-QtLockedFile::~QtLockedFile()
-{
- if (isOpen())
- unlock();
- if (wmutex)
- CloseHandle(wmutex);
-}
diff --git a/src/qtsingleapplication/src/qtsingleapplication.cpp b/src/qtsingleapplication/src/qtsingleapplication.cpp
deleted file mode 100644
index d0fb15d7..00000000
--- a/src/qtsingleapplication/src/qtsingleapplication.cpp
+++ /dev/null
@@ -1,347 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the Qt Solutions component.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
-** of its contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-#include "qtsingleapplication.h"
-#include "qtlocalpeer.h"
-#include
-
-
-/*!
- \class QtSingleApplication qtsingleapplication.h
- \brief The QtSingleApplication class provides an API to detect and
- communicate with running instances of an application.
-
- This class allows you to create applications where only one
- instance should be running at a time. I.e., if the user tries to
- launch another instance, the already running instance will be
- activated instead. Another usecase is a client-server system,
- where the first started instance will assume the role of server,
- and the later instances will act as clients of that server.
-
- By default, the full path of the executable file is used to
- determine whether two processes are instances of the same
- application. You can also provide an explicit identifier string
- that will be compared instead.
-
- The application should create the QtSingleApplication object early
- in the startup phase, and call isRunning() to find out if another
- instance of this application is already running. If isRunning()
- returns false, it means that no other instance is running, and
- this instance has assumed the role as the running instance. In
- this case, the application should continue with the initialization
- of the application user interface before entering the event loop
- with exec(), as normal.
-
- The messageReceived() signal will be emitted when the running
- application receives messages from another instance of the same
- application. When a message is received it might be helpful to the
- user to raise the application so that it becomes visible. To
- facilitate this, QtSingleApplication provides the
- setActivationWindow() function and the activateWindow() slot.
-
- If isRunning() returns true, another instance is already
- running. It may be alerted to the fact that another instance has
- started by using the sendMessage() function. Also data such as
- startup parameters (e.g. the name of the file the user wanted this
- new instance to open) can be passed to the running instance with
- this function. Then, the application should terminate (or enter
- client mode).
-
- If isRunning() returns true, but sendMessage() fails, that is an
- indication that the running instance is frozen.
-
- Here's an example that shows how to convert an existing
- application to use QtSingleApplication. It is very simple and does
- not make use of all QtSingleApplication's functionality (see the
- examples for that).
-
- \code
- // Original
- int main(int argc, char **argv)
- {
- QApplication app(argc, argv);
-
- MyMainWidget mmw;
- mmw.show();
- return app.exec();
- }
-
- // Single instance
- int main(int argc, char **argv)
- {
- QtSingleApplication app(argc, argv);
-
- if (app.isRunning())
- return !app.sendMessage(someDataString);
-
- MyMainWidget mmw;
- app.setActivationWindow(&mmw);
- mmw.show();
- return app.exec();
- }
- \endcode
-
- Once this QtSingleApplication instance is destroyed (normally when
- the process exits or crashes), when the user next attempts to run the
- application this instance will not, of course, be encountered. The
- next instance to call isRunning() or sendMessage() will assume the
- role as the new running instance.
-
- For console (non-GUI) applications, QtSingleCoreApplication may be
- used instead of this class, to avoid the dependency on the QtGui
- library.
-
- \sa QtSingleCoreApplication
-*/
-
-
-void QtSingleApplication::sysInit(const QString &appId)
-{
- actWin = 0;
- peer = new QtLocalPeer(this, appId);
- connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&)));
-}
-
-
-/*!
- Creates a QtSingleApplication object. The application identifier
- will be QCoreApplication::applicationFilePath(). \a argc, \a
- argv, and \a GUIenabled are passed on to the QAppliation constructor.
-
- If you are creating a console application (i.e. setting \a
- GUIenabled to false), you may consider using
- QtSingleCoreApplication instead.
-*/
-
-QtSingleApplication::QtSingleApplication(int &argc, char **argv, bool GUIenabled)
- : QApplication(argc, argv, GUIenabled)
-{
- sysInit();
-}
-
-
-/*!
- Creates a QtSingleApplication object with the application
- identifier \a appId. \a argc and \a argv are passed on to the
- QAppliation constructor.
-*/
-
-QtSingleApplication::QtSingleApplication(const QString &appId, int &argc, char **argv)
- : QApplication(argc, argv)
-{
- sysInit(appId);
-}
-
-#if QT_VERSION < 0x050000
-
-/*!
- Creates a QtSingleApplication object. The application identifier
- will be QCoreApplication::applicationFilePath(). \a argc, \a
- argv, and \a type are passed on to the QAppliation constructor.
-*/
-QtSingleApplication::QtSingleApplication(int &argc, char **argv, Type type)
- : QApplication(argc, argv, type)
-{
- sysInit();
-}
-
-
-# if defined(Q_WS_X11)
-/*!
- Special constructor for X11, ref. the documentation of
- QApplication's corresponding constructor. The application identifier
- will be QCoreApplication::applicationFilePath(). \a dpy, \a visual,
- and \a cmap are passed on to the QApplication constructor.
-*/
-QtSingleApplication::QtSingleApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE cmap)
- : QApplication(dpy, visual, cmap)
-{
- sysInit();
-}
-
-/*!
- Special constructor for X11, ref. the documentation of
- QApplication's corresponding constructor. The application identifier
- will be QCoreApplication::applicationFilePath(). \a dpy, \a argc, \a
- argv, \a visual, and \a cmap are passed on to the QApplication
- constructor.
-*/
-QtSingleApplication::QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap)
- : QApplication(dpy, argc, argv, visual, cmap)
-{
- sysInit();
-}
-
-/*!
- Special constructor for X11, ref. the documentation of
- QApplication's corresponding constructor. The application identifier
- will be \a appId. \a dpy, \a argc, \a
- argv, \a visual, and \a cmap are passed on to the QApplication
- constructor.
-*/
-QtSingleApplication::QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap)
- : QApplication(dpy, argc, argv, visual, cmap)
-{
- sysInit(appId);
-}
-# endif // Q_WS_X11
-#endif // QT_VERSION < 0x050000
-
-
-/*!
- Returns true if another instance of this application is running;
- otherwise false.
-
- This function does not find instances of this application that are
- being run by a different user (on Windows: that are running in
- another session).
-
- \sa sendMessage()
-*/
-
-bool QtSingleApplication::isRunning()
-{
- return peer->isClient();
-}
-
-
-/*!
- Tries to send the text \a message to the currently running
- instance. The QtSingleApplication object in the running instance
- will emit the messageReceived() signal when it receives the
- message.
-
- This function returns true if the message has been sent to, and
- processed by, the current instance. If there is no instance
- currently running, or if the running instance fails to process the
- message within \a timeout milliseconds, this function return false.
-
- \sa isRunning(), messageReceived()
-*/
-bool QtSingleApplication::sendMessage(const QString &message, int timeout)
-{
- return peer->sendMessage(message, timeout);
-}
-
-
-/*!
- Returns the application identifier. Two processes with the same
- identifier will be regarded as instances of the same application.
-*/
-QString QtSingleApplication::id() const
-{
- return peer->applicationId();
-}
-
-
-/*!
- Sets the activation window of this application to \a aw. The
- activation window is the widget that will be activated by
- activateWindow(). This is typically the application's main window.
-
- If \a activateOnMessage is true (the default), the window will be
- activated automatically every time a message is received, just prior
- to the messageReceived() signal being emitted.
-
- \sa activateWindow(), messageReceived()
-*/
-
-void QtSingleApplication::setActivationWindow(QWidget* aw, bool activateOnMessage)
-{
- actWin = aw;
- if (activateOnMessage)
- connect(peer, SIGNAL(messageReceived(const QString&)), this, SLOT(activateWindow()));
- else
- disconnect(peer, SIGNAL(messageReceived(const QString&)), this, SLOT(activateWindow()));
-}
-
-
-/*!
- Returns the applications activation window if one has been set by
- calling setActivationWindow(), otherwise returns 0.
-
- \sa setActivationWindow()
-*/
-QWidget* QtSingleApplication::activationWindow() const
-{
- return actWin;
-}
-
-
-/*!
- De-minimizes, raises, and activates this application's activation window.
- This function does nothing if no activation window has been set.
-
- This is a convenience function to show the user that this
- application instance has been activated when he has tried to start
- another instance.
-
- This function should typically be called in response to the
- messageReceived() signal. By default, that will happen
- automatically, if an activation window has been set.
-
- \sa setActivationWindow(), messageReceived(), initialize()
-*/
-void QtSingleApplication::activateWindow()
-{
- if (actWin) {
- actWin->setWindowState(actWin->windowState() & ~Qt::WindowMinimized);
- actWin->raise();
- actWin->activateWindow();
- }
-}
-
-
-/*!
- \fn void QtSingleApplication::messageReceived(const QString& message)
-
- This signal is emitted when the current instance receives a \a
- message from another instance of this application.
-
- \sa sendMessage(), setActivationWindow(), activateWindow()
-*/
-
-
-/*!
- \fn void QtSingleApplication::initialize(bool dummy = true)
-
- \obsolete
-*/
diff --git a/src/qtsingleapplication/src/qtsingleapplication.h b/src/qtsingleapplication/src/qtsingleapplication.h
deleted file mode 100644
index 049406f7..00000000
--- a/src/qtsingleapplication/src/qtsingleapplication.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the Qt Solutions component.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
-** of its contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QTSINGLEAPPLICATION_H
-#define QTSINGLEAPPLICATION_H
-
-#include
-
-class QtLocalPeer;
-
-#if defined(Q_OS_WIN)
-# if !defined(QT_QTSINGLEAPPLICATION_EXPORT) && !defined(QT_QTSINGLEAPPLICATION_IMPORT)
-# define QT_QTSINGLEAPPLICATION_EXPORT
-# elif defined(QT_QTSINGLEAPPLICATION_IMPORT)
-# if defined(QT_QTSINGLEAPPLICATION_EXPORT)
-# undef QT_QTSINGLEAPPLICATION_EXPORT
-# endif
-# define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllimport)
-# elif defined(QT_QTSINGLEAPPLICATION_EXPORT)
-# undef QT_QTSINGLEAPPLICATION_EXPORT
-# define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllexport)
-# endif
-#else
-# define QT_QTSINGLEAPPLICATION_EXPORT
-#endif
-
-class QT_QTSINGLEAPPLICATION_EXPORT QtSingleApplication : public QApplication
-{
- Q_OBJECT
-
-public:
- QtSingleApplication(int &argc, char **argv, bool GUIenabled = true);
- QtSingleApplication(const QString &id, int &argc, char **argv);
-#if QT_VERSION < 0x050000
- QtSingleApplication(int &argc, char **argv, Type type);
-# if defined(Q_WS_X11)
- QtSingleApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0);
- QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0);
- QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0);
-# endif // Q_WS_X11
-#endif // QT_VERSION < 0x050000
-
- bool isRunning();
- QString id() const;
-
- void setActivationWindow(QWidget* aw, bool activateOnMessage = true);
- QWidget* activationWindow() const;
-
- // Obsolete:
- void initialize(bool dummy = true)
- { isRunning(); Q_UNUSED(dummy) }
-
-public Q_SLOTS:
- bool sendMessage(const QString &message, int timeout = 5000);
- void activateWindow();
-
-
-Q_SIGNALS:
- void messageReceived(const QString &message);
-
-
-private:
- void sysInit(const QString &appId = QString());
- QtLocalPeer *peer;
- QWidget *actWin;
-};
-
-#endif // QTSINGLEAPPLICATION_H
diff --git a/src/qtsingleapplication/src/qtsingleapplication.pri b/src/qtsingleapplication/src/qtsingleapplication.pri
deleted file mode 100644
index 6f2bced9..00000000
--- a/src/qtsingleapplication/src/qtsingleapplication.pri
+++ /dev/null
@@ -1,17 +0,0 @@
-include(../common.pri)
-INCLUDEPATH += $$PWD
-DEPENDPATH += $$PWD
-QT *= network
-greaterThan(QT_MAJOR_VERSION, 4): QT *= widgets
-
-qtsingleapplication-uselib:!qtsingleapplication-buildlib {
- LIBS += -L$$QTSINGLEAPPLICATION_LIBDIR -l$$QTSINGLEAPPLICATION_LIBNAME
-} else {
- SOURCES += $$PWD/qtsingleapplication.cpp $$PWD/qtlocalpeer.cpp
- HEADERS += $$PWD/qtsingleapplication.h $$PWD/qtlocalpeer.h
-}
-
-win32 {
- contains(TEMPLATE, lib):contains(CONFIG, shared):DEFINES += QT_QTSINGLEAPPLICATION_EXPORT
- else:qtsingleapplication-uselib:DEFINES += QT_QTSINGLEAPPLICATION_IMPORT
-}
diff --git a/src/qtsingleapplication/src/qtsinglecoreapplication.cpp b/src/qtsingleapplication/src/qtsinglecoreapplication.cpp
deleted file mode 100644
index 56345373..00000000
--- a/src/qtsingleapplication/src/qtsinglecoreapplication.cpp
+++ /dev/null
@@ -1,149 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the Qt Solutions component.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
-** of its contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-#include "qtsinglecoreapplication.h"
-#include "qtlocalpeer.h"
-
-/*!
- \class QtSingleCoreApplication qtsinglecoreapplication.h
- \brief A variant of the QtSingleApplication class for non-GUI applications.
-
- This class is a variant of QtSingleApplication suited for use in
- console (non-GUI) applications. It is an extension of
- QCoreApplication (instead of QApplication). It does not require
- the QtGui library.
-
- The API and usage is identical to QtSingleApplication, except that
- functions relating to the "activation window" are not present, for
- obvious reasons. Please refer to the QtSingleApplication
- documentation for explanation of the usage.
-
- A QtSingleCoreApplication instance can communicate to a
- QtSingleApplication instance if they share the same application
- id. Hence, this class can be used to create a light-weight
- command-line tool that sends commands to a GUI application.
-
- \sa QtSingleApplication
-*/
-
-/*!
- Creates a QtSingleCoreApplication object. The application identifier
- will be QCoreApplication::applicationFilePath(). \a argc and \a
- argv are passed on to the QCoreAppliation constructor.
-*/
-
-QtSingleCoreApplication::QtSingleCoreApplication(int &argc, char **argv)
- : QCoreApplication(argc, argv)
-{
- peer = new QtLocalPeer(this);
- connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&)));
-}
-
-
-/*!
- Creates a QtSingleCoreApplication object with the application
- identifier \a appId. \a argc and \a argv are passed on to the
- QCoreAppliation constructor.
-*/
-QtSingleCoreApplication::QtSingleCoreApplication(const QString &appId, int &argc, char **argv)
- : QCoreApplication(argc, argv)
-{
- peer = new QtLocalPeer(this, appId);
- connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&)));
-}
-
-
-/*!
- Returns true if another instance of this application is running;
- otherwise false.
-
- This function does not find instances of this application that are
- being run by a different user (on Windows: that are running in
- another session).
-
- \sa sendMessage()
-*/
-
-bool QtSingleCoreApplication::isRunning()
-{
- return peer->isClient();
-}
-
-
-/*!
- Tries to send the text \a message to the currently running
- instance. The QtSingleCoreApplication object in the running instance
- will emit the messageReceived() signal when it receives the
- message.
-
- This function returns true if the message has been sent to, and
- processed by, the current instance. If there is no instance
- currently running, or if the running instance fails to process the
- message within \a timeout milliseconds, this function return false.
-
- \sa isRunning(), messageReceived()
-*/
-
-bool QtSingleCoreApplication::sendMessage(const QString &message, int timeout)
-{
- return peer->sendMessage(message, timeout);
-}
-
-
-/*!
- Returns the application identifier. Two processes with the same
- identifier will be regarded as instances of the same application.
-*/
-
-QString QtSingleCoreApplication::id() const
-{
- return peer->applicationId();
-}
-
-
-/*!
- \fn void QtSingleCoreApplication::messageReceived(const QString& message)
-
- This signal is emitted when the current instance receives a \a
- message from another instance of this application.
-
- \sa sendMessage()
-*/
diff --git a/src/qtsingleapplication/src/qtsinglecoreapplication.h b/src/qtsingleapplication/src/qtsinglecoreapplication.h
deleted file mode 100644
index b87fffe4..00000000
--- a/src/qtsingleapplication/src/qtsinglecoreapplication.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the Qt Solutions component.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
-** of its contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QTSINGLECOREAPPLICATION_H
-#define QTSINGLECOREAPPLICATION_H
-
-#include
-
-class QtLocalPeer;
-
-class QtSingleCoreApplication : public QCoreApplication
-{
- Q_OBJECT
-
-public:
- QtSingleCoreApplication(int &argc, char **argv);
- QtSingleCoreApplication(const QString &id, int &argc, char **argv);
-
- bool isRunning();
- QString id() const;
-
-public Q_SLOTS:
- bool sendMessage(const QString &message, int timeout = 5000);
-
-
-Q_SIGNALS:
- void messageReceived(const QString &message);
-
-
-private:
- QtLocalPeer* peer;
-};
-
-#endif // QTSINGLECOREAPPLICATION_H
diff --git a/src/qtsingleapplication/src/qtsinglecoreapplication.pri b/src/qtsingleapplication/src/qtsinglecoreapplication.pri
deleted file mode 100644
index d2d6cc3e..00000000
--- a/src/qtsingleapplication/src/qtsinglecoreapplication.pri
+++ /dev/null
@@ -1,10 +0,0 @@
-INCLUDEPATH += $$PWD
-DEPENDPATH += $$PWD
-HEADERS += $$PWD/qtsinglecoreapplication.h $$PWD/qtlocalpeer.h
-SOURCES += $$PWD/qtsinglecoreapplication.cpp $$PWD/qtlocalpeer.cpp
-
-QT *= network
-
-win32:contains(TEMPLATE, lib):contains(CONFIG, shared) {
- DEFINES += QT_QTSINGLECOREAPPLICATION_EXPORT=__declspec(dllexport)
-}
diff --git a/src/singleapplication/CHANGELOG.md b/src/singleapplication/CHANGELOG.md
new file mode 100644
index 00000000..4368d0f5
--- /dev/null
+++ b/src/singleapplication/CHANGELOG.md
@@ -0,0 +1,306 @@
+Changelog
+=========
+
+If by accident I have forgotten to credit someone in the CHANGELOG, email me and I will fix it.
+
+
+__3.3.1__
+---------
+
+* Added support for _AppImage_ dynamic executable paths. - _Michael Klein_
+
+__3.3.0__
+---------
+
+* Fixed message fragmentation issue causing crashes and incorrectly / inconsistently received messages. - _Nils Jeisecke_
+
+__3.2.0__
+---------
+
+* Added support for Qt 6 - _Jonas Kvinge_
+* Fixed warning in `Qt 5.9` with `min`/`max` functions on Windows - _Nick Korotysh_
+* Fix return value of connectToPrimary() when connect is successful - _Jonas Kvinge_
+* Fix build issue with MinGW GCC pedantic mode - _Iakov Kirilenko_
+* Fixed conversion from `int` to `quint32` and Clang Tidy warnings - _Hennadii Chernyshchyk_
+
+__3.1.5__
+---------
+
+* Improved library stability in edge cases and very rapid process initialisation
+* Fixed Bug where the shared memory block may have been modified without a lock
+* Fixed Bug causing `instanceStarted()` to not get emitted when a second instance
+ has been started before the primary has initiated it's `QLocalServer`.
+
+__3.1.4__
+---------
+* Officially supporting and build-testing against Qt 5.15
+* Fixed an MSVC C4996 warning that suggests using `strncpy_s`.
+
+ _Hennadii Chernyshchyk_
+
+__3.1.3.1__
+---------
+* CMake build system improvements
+* Fixed Clang Tidy warnings
+
+ _Hennadii Chernyshchyk_
+
+__3.1.3__
+---------
+* Improved `CMakeLists.txt`
+
+ _Hennadii Chernyshchyk_
+
+__3.1.2__
+---------
+
+* Fix a crash when exiting an application on Android and iOS
+
+ _Emeric Grange_
+
+__3.1.1a__
+----------
+
+* Added currentUser() method that returns the user the current instance is running as.
+
+ _Leander Schulten_
+
+__3.1.0a__
+----------
+
+* Added primaryUser() method that returns the user the primary instance is running as.
+
+__3.0.19__
+----------
+
+* Fixed code warning for depricated functions in Qt 5.10 related to `QTime` and `qrand()`.
+
+ _Hennadii Chernyshchyk_
+ _Anton Filimonov_
+ _Jonas Kvinge_
+
+__3.0.18__
+----------
+
+* Fallback to standard QApplication class on iOS and Android systems where
+ the library is not supported.
+
+* Added Build CI tests to verify the library builds successfully on Linux, Windows and MacOS across multiple Qt versions.
+
+ _Anton Filimonov_
+
+__3.0.17__
+----------
+
+* Fixed compilation warning/error caused by `geteuid()` on unix based systems.
+
+ _Iakov Kirilenko_
+
+* Added CMake support
+
+ _Hennadii Chernyshchyk_
+
+__3.0.16__
+----------
+
+* Use geteuid and getpwuid to get username on Unix, fallback to environment variable.
+
+ _Jonas Kvinge_
+
+__3.0.15__
+----------
+
+* Bug Fix: sendMessage() might return false even though data was actually written.
+
+ _Jonas Kvinge_
+
+__3.0.14__
+----------
+
+* Fixed uninitialised variables in the `SingleApplicationPrivate` constructor.
+
+__3.0.13a__
+----------
+
+* Process socket events asynchronously
+* Fix undefined variable error on Windows
+
+ _Francis Giraldeau_
+
+__3.0.12a__
+----------
+
+* Removed signal handling.
+
+__3.0.11a__
+----------
+
+* Fixed bug where the message sent by the second process was not received
+ correctly when the message is sent immediately following a connection.
+
+ _Francis Giraldeau_
+
+* Refactored code and implemented shared memory block consistency checks
+ via `qChecksum()` (CRC-16).
+* Explicit `qWarning` and `qCritical` when the library is unable to initialise
+ correctly.
+
+__3.0.10__
+----------
+
+* Removed C style casts and eliminated all clang warnings. Fixed `instanceId`
+ reading from only one byte in the message deserialization. Cleaned up
+ serialization code using `QDataStream`. Changed connection type to use
+ `quint8 enum` rather than `char`.
+* Renamed `SingleAppConnectionType` to `ConnectionType`. Added initialization
+ values to all `ConnectionType` enum cases.
+
+ _Jedidiah Buck McCready_
+
+__3.0.9__
+---------
+
+* Added SingleApplicationPrivate::primaryPid() as a solution to allow
+ bringing the primary window of an application to the foreground on
+ Windows.
+
+ _Eelco van Dam from Peacs BV_
+
+__3.0.8__
+---------
+
+* Bug fix - changed QApplication::instance() to QCoreApplication::instance()
+
+ _Evgeniy Bazhenov_
+
+__3.0.7a__
+----------
+
+* Fixed compilation error with Mingw32 in MXE thanks to Vitaly Tonkacheyev.
+* Removed QMutex used for thread safe behaviour. The implementation now uses
+ QCoreApplication::instance() to get an instance to SingleApplication for
+ memory deallocation.
+
+__3.0.6a__
+----------
+
+* Reverted GetUserName API usage on Windows. Fixed bug with missing library.
+* Fixed bug in the Calculator example, preventing it's window to be raised
+ on Windows.
+
+ Special thanks to Charles Gunawan.
+
+__3.0.5a__
+----------
+
+* Fixed a memory leak in the SingleApplicationPrivate destructor.
+
+ _Sergei Moiseev_
+
+__3.0.4a__
+----------
+
+* Fixed shadow and uninitialised variable warnings.
+
+ _Paul Walmsley_
+
+__3.0.3a__
+----------
+
+* Removed Microsoft Windows specific code for getting username due to
+ multiple problems and compiler differences on Windows platforms. On
+ Windows the shared memory block in User mode now includes the user's
+ home path (which contains the user's username).
+
+* Explicitly getting absolute path of the user's home directory as on Unix
+ a relative path (`~`) may be returned.
+
+__3.0.2a__
+----------
+
+* Fixed bug on Windows when username containing wide characters causes the
+ library to crash.
+
+ _Le Liu_
+
+__3.0.1a__
+----------
+
+* Allows the application path and version to be excluded from the server name
+ hash. The following flags were added for this purpose:
+ * `SingleApplication::Mode::ExcludeAppVersion`
+ * `SingleApplication::Mode::ExcludeAppPath`
+* Allow a non elevated process to connect to a local server created by an
+ elevated process run by the same user on Windows
+* Fixes a problem with upper case letters in paths on Windows
+
+ _Le Liu_
+
+__v3.0a__
+---------
+
+* Deprecated secondary instances count.
+* Added a sendMessage() method to send a message to the primary instance.
+* Added a receivedMessage() signal, emitted when a message is received from a
+ secondary instance.
+* The SingleApplication constructor's third parameter is now a bool
+ specifying if the current instance should be allowed to run as a secondary
+ instance if there is already a primary instance.
+* The SingleApplication constructor accept a fourth parameter specifying if
+ the SingleApplication block should be User-wide or System-wide.
+* SingleApplication no longer relies on `applicationName` and
+ `organizationName` to be set. It instead concatenates all of the following
+ data and computes a `SHA256` hash which is used as the key of the
+ `QSharedMemory` block and the `QLocalServer`. Since at least
+ `applicationFilePath` is always present there is no need to explicitly set
+ any of the following prior to initialising `SingleApplication`.
+ * `QCoreApplication::applicationName`
+ * `QCoreApplication::applicationVersion`
+ * `QCoreApplication::applicationFilePath`
+ * `QCoreApplication::organizationName`
+ * `QCoreApplication::organizationDomain`
+ * User name or home directory path if in User mode
+* The primary instance is no longer notified when a secondary instance had
+ been started by default. A `Mode` flag for this feature exists.
+* Added `instanceNumber()` which represents a unique identifier for each
+ secondary instance started. When called from the primary instance will
+ return `0`.
+
+__v2.4__
+--------
+
+* Stability improvements
+* Support for secondary instances.
+* The library now recovers safely after the primary process has crashed
+and the shared memory had not been deleted.
+
+__v2.3__
+--------
+
+* Improved pimpl design and inheritance safety.
+
+ _Vladislav Pyatnichenko_
+
+__v2.2__
+--------
+
+* The `QAPPLICATION_CLASS` macro can now be defined in the file including the
+Single Application header or with a `DEFINES+=` statement in the project file.
+
+__v2.1__
+--------
+
+* A race condition can no longer occur when starting two processes nearly
+ simultaneously.
+
+ Fix issue [#3](https://github.com/itay-grudev/SingleApplication/issues/3)
+
+__v2.0__
+--------
+
+* SingleApplication is now being passed a reference to `argc` instead of a
+ copy.
+
+ Fix issue [#1](https://github.com/itay-grudev/SingleApplication/issues/1)
+
+* Improved documentation.
diff --git a/src/singleapplication/CMakeLists.txt b/src/singleapplication/CMakeLists.txt
new file mode 100644
index 00000000..ae1b1439
--- /dev/null
+++ b/src/singleapplication/CMakeLists.txt
@@ -0,0 +1,40 @@
+cmake_minimum_required(VERSION 3.7.0)
+
+project(SingleApplication LANGUAGES CXX)
+
+set(CMAKE_AUTOMOC ON)
+
+add_library(${PROJECT_NAME} STATIC
+ singleapplication.cpp
+ singleapplication_p.cpp
+)
+add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
+
+if(NOT QT_DEFAULT_MAJOR_VERSION)
+ set(QT_DEFAULT_MAJOR_VERSION 5 CACHE STRING "Qt version to use (5 or 6), defaults to 5")
+endif()
+
+# Find dependencies
+set(QT_COMPONENTS Core Network)
+set(QT_LIBRARIES Qt${QT_DEFAULT_MAJOR_VERSION}::Core Qt${QT_DEFAULT_MAJOR_VERSION}::Network)
+
+if(QAPPLICATION_CLASS STREQUAL QApplication)
+ list(APPEND QT_COMPONENTS Widgets)
+ list(APPEND QT_LIBRARIES Qt${QT_DEFAULT_MAJOR_VERSION}::Widgets)
+elseif(QAPPLICATION_CLASS STREQUAL QGuiApplication)
+ list(APPEND QT_COMPONENTS Gui)
+ list(APPEND QT_LIBRARIES Qt${QT_DEFAULT_MAJOR_VERSION}::Gui)
+else()
+ set(QAPPLICATION_CLASS QCoreApplication)
+endif()
+
+find_package(Qt${QT_DEFAULT_MAJOR_VERSION} COMPONENTS ${QT_COMPONENTS} REQUIRED)
+
+target_link_libraries(${PROJECT_NAME} PUBLIC ${QT_LIBRARIES})
+
+if(WIN32)
+ target_link_libraries(${PROJECT_NAME} PRIVATE advapi32)
+endif()
+
+target_compile_definitions(${PROJECT_NAME} PUBLIC QAPPLICATION_CLASS=${QAPPLICATION_CLASS})
+target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
diff --git a/src/singleapplication/LICENSE b/src/singleapplication/LICENSE
new file mode 100644
index 00000000..a82e5a68
--- /dev/null
+++ b/src/singleapplication/LICENSE
@@ -0,0 +1,24 @@
+The MIT License (MIT)
+
+Copyright (c) Itay Grudev 2015 - 2020
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+Note: Some of the examples include code not distributed under the terms of the
+MIT License.
diff --git a/src/singleapplication/README.md b/src/singleapplication/README.md
new file mode 100644
index 00000000..a76bada3
--- /dev/null
+++ b/src/singleapplication/README.md
@@ -0,0 +1,305 @@
+SingleApplication
+=================
+[](https://github.com/itay-grudev/SingleApplication/actions)
+
+This is a replacement of the QtSingleApplication for `Qt5` and `Qt6`.
+
+Keeps the Primary Instance of your Application and kills each subsequent
+instances. It can (if enabled) spawn secondary (non-related to the primary)
+instances and can send data to the primary instance from secondary instances.
+
+Usage
+-----
+
+The `SingleApplication` class inherits from whatever `Q[Core|Gui]Application`
+class you specify via the `QAPPLICATION_CLASS` macro (`QCoreApplication` is the
+default). Further usage is similar to the use of the `Q[Core|Gui]Application`
+classes.
+
+You can use the library as if you use any other `QCoreApplication` derived
+class:
+
+```cpp
+#include
+#include
+
+int main( int argc, char* argv[] )
+{
+ SingleApplication app( argc, argv );
+
+ return app.exec();
+}
+```
+
+To include the library files I would recommend that you add it as a git
+submodule to your project. Here is how:
+
+```bash
+git submodule add git@github.com:itay-grudev/SingleApplication.git singleapplication
+```
+
+**Qmake:**
+
+Then include the `singleapplication.pri` file in your `.pro` project file.
+
+```qmake
+include(singleapplication/singleapplication.pri)
+DEFINES += QAPPLICATION_CLASS=QApplication
+```
+
+**CMake:**
+
+Then include the subdirectory in your `CMakeLists.txt` project file.
+
+```cmake
+set(QAPPLICATION_CLASS QApplication CACHE STRING "Inheritance class for SingleApplication")
+add_subdirectory(src/third-party/singleapplication)
+target_link_libraries(${PROJECT_NAME} SingleApplication::SingleApplication)
+```
+
+
+The library sets up a `QLocalServer` and a `QSharedMemory` block. The first
+instance of your Application is your Primary Instance. It would check if the
+shared memory block exists and if not it will start a `QLocalServer` and listen
+for connections. Each subsequent instance of your application would check if the
+shared memory block exists and if it does, it will connect to the QLocalServer
+to notify the primary instance that a new instance had been started, after which
+it would terminate with status code `0`. In the Primary Instance
+`SingleApplication` would emit the `instanceStarted()` signal upon detecting
+that a new instance had been started.
+
+The library uses `stdlib` to terminate the program with the `exit()` function.
+
+Also don't forget to specify which `QCoreApplication` class your app is using if it
+is not `QCoreApplication` as in examples above.
+
+The `Instance Started` signal
+-----------------------------
+
+The SingleApplication class implements a `instanceStarted()` signal. You can
+bind to that signal to raise your application's window when a new instance had
+been started, for example.
+
+```cpp
+// window is a QWindow instance
+QObject::connect(
+ &app,
+ &SingleApplication::instanceStarted,
+ &window,
+ &QWindow::raise
+);
+```
+
+Using `SingleApplication::instance()` is a neat way to get the
+`SingleApplication` instance for binding to it's signals anywhere in your
+program.
+
+__Note:__ On Windows the ability to bring the application windows to the
+foreground is restricted. See [Windows specific implementations](Windows.md)
+for a workaround and an example implementation.
+
+
+Secondary Instances
+-------------------
+
+If you want to be able to launch additional Secondary Instances (not related to
+your Primary Instance) you have to enable that with the third parameter of the
+`SingleApplication` constructor. The default is `false` meaning no Secondary
+Instances. Here is an example of how you would start a Secondary Instance send
+a message with the command line arguments to the primary instance and then shut
+down.
+
+```cpp
+int main(int argc, char *argv[])
+{
+ SingleApplication app( argc, argv, true );
+
+ if( app.isSecondary() ) {
+ app.sendMessage( app.arguments().join(' ')).toUtf8() );
+ app.exit( 0 );
+ }
+
+ return app.exec();
+}
+```
+
+*__Note:__ A secondary instance won't cause the emission of the
+`instanceStarted()` signal by default. See `SingleApplication::Mode` for more
+details.*
+
+You can check whether your instance is a primary or secondary with the following
+methods:
+
+```cpp
+app.isPrimary();
+// or
+app.isSecondary();
+```
+
+*__Note:__ If your Primary Instance is terminated a newly launched instance
+will replace the Primary one even if the Secondary flag has been set.*
+
+Examples
+--------
+
+There are three examples provided in this repository:
+
+* Basic example that prevents a secondary instance from starting [`examples/basic`](https://github.com/itay-grudev/SingleApplication/tree/master/examples/basic)
+* An example of a graphical application raising it's parent window [`examples/calculator`](https://github.com/itay-grudev/SingleApplication/tree/master/examples/calculator)
+* A console application sending the primary instance it's command line parameters [`examples/sending_arguments`](https://github.com/itay-grudev/SingleApplication/tree/master/examples/sending_arguments)
+
+API
+---
+
+### Members
+
+```cpp
+SingleApplication::SingleApplication( int &argc, char *argv[], bool allowSecondary = false, Options options = Mode::User, int timeout = 100, QString userData = QString() )
+```
+
+Depending on whether `allowSecondary` is set, this constructor may terminate
+your app if there is already a primary instance running. Additional `Options`
+can be specified to set whether the SingleApplication block should work
+user-wide or system-wide. Additionally the `Mode::SecondaryNotification` may be
+used to notify the primary instance whenever a secondary instance had been
+started (disabled by default). `timeout` specifies the maximum time in
+milliseconds to wait for blocking operations. Setting `userData` provides additional data that will isolate this instance from other instances that do not have the same (or any) user data set.
+
+*__Note:__ `argc` and `argv` may be changed as Qt removes arguments that it
+recognizes.*
+
+*__Note:__ `Mode::SecondaryNotification` only works if set on both the primary
+and the secondary instance.*
+
+*__Note:__ Operating system can restrict the shared memory blocks to the same
+user, in which case the User/System modes will have no effect and the block will
+be user wide.*
+
+---
+
+```cpp
+bool SingleApplication::sendMessage( QByteArray message, int timeout = 100 )
+```
+
+Sends `message` to the Primary Instance. Uses `timeout` as a the maximum timeout
+in milliseconds for blocking functions. Returns `true` if the message has been sent
+successfully. If the message can't be sent or the function timeouts - returns `false`.
+
+---
+
+```cpp
+bool SingleApplication::isPrimary()
+```
+
+Returns if the instance is the primary instance.
+
+---
+
+```cpp
+bool SingleApplication::isSecondary()
+```
+Returns if the instance is a secondary instance.
+
+---
+
+```cpp
+quint32 SingleApplication::instanceId()
+```
+
+Returns a unique identifier for the current instance.
+
+---
+
+```cpp
+qint64 SingleApplication::primaryPid()
+```
+
+Returns the process ID (PID) of the primary instance.
+
+---
+
+```cpp
+QString SingleApplication::primaryUser()
+```
+
+Returns the username the primary instance is running as.
+
+---
+
+```cpp
+QString SingleApplication::currentUser()
+```
+
+Returns the username the current instance is running as.
+
+### Signals
+
+```cpp
+void SingleApplication::instanceStarted()
+```
+
+Triggered whenever a new instance had been started, except for secondary
+instances if the `Mode::SecondaryNotification` flag is not specified.
+
+---
+
+```cpp
+void SingleApplication::receivedMessage( quint32 instanceId, QByteArray message )
+```
+
+Triggered whenever there is a message received from a secondary instance.
+
+---
+
+### Flags
+
+```cpp
+enum SingleApplication::Mode
+```
+
+* `Mode::User` - The SingleApplication block should apply user wide. This adds
+ user specific data to the key used for the shared memory and server name.
+ This is the default functionality.
+* `Mode::System` – The SingleApplication block applies system-wide.
+* `Mode::SecondaryNotification` – Whether to trigger `instanceStarted()` even
+ whenever secondary instances are started.
+* `Mode::ExcludeAppPath` – Excludes the application path from the server name
+ (and memory block) hash.
+* `Mode::ExcludeAppVersion` – Excludes the application version from the server
+ name (and memory block) hash.
+
+*__Note:__ `Mode::SecondaryNotification` only works if set on both the primary
+and the secondary instance.*
+
+*__Note:__ Operating system can restrict the shared memory blocks to the same
+user, in which case the User/System modes will have no effect and the block will
+be user wide.*
+
+---
+
+Versioning
+----------
+
+Each major version introduces either very significant changes or is not
+backwards compatible with the previous version. Minor versions only add
+additional features, bug fixes or performance improvements and are backwards
+compatible with the previous release. See [`CHANGELOG.md`](CHANGELOG.md) for
+more details.
+
+Implementation
+--------------
+
+The library is implemented with a QSharedMemory block which is thread safe and
+guarantees a race condition will not occur. It also uses a QLocalSocket to
+notify the main process that a new instance had been spawned and thus invoke the
+`instanceStarted()` signal and for messaging the primary instance.
+
+Additionally the library can recover from being forcefully killed on *nix
+systems and will reset the memory block given that there are no other
+instances running.
+
+License
+-------
+This library and it's supporting documentation are released under
+`The MIT License (MIT)` with the exception of the Qt calculator examples which
+is distributed under the BSD license.
diff --git a/src/singleapplication/SingleApplication b/src/singleapplication/SingleApplication
new file mode 100644
index 00000000..8ead1a42
--- /dev/null
+++ b/src/singleapplication/SingleApplication
@@ -0,0 +1 @@
+#include "singleapplication.h"
diff --git a/src/singleapplication/Windows.md b/src/singleapplication/Windows.md
new file mode 100644
index 00000000..13c52da0
--- /dev/null
+++ b/src/singleapplication/Windows.md
@@ -0,0 +1,46 @@
+Windows Specific Implementations
+================================
+
+Setting the foreground window
+-----------------------------
+
+In the `instanceStarted()` example in the `README` we demonstrated how an
+application can bring it's primary instance window whenever a second copy
+of the application is started.
+
+On Windows the ability to bring the application windows to the foreground is
+restricted, see [`AllowSetForegroundWindow()`][AllowSetForegroundWindow] for more
+details.
+
+The background process (the primary instance) can bring its windows to the
+foreground if it is allowed by the current foreground process (the secondary
+instance). To bypass this `SingleApplication` must be initialized with the
+`allowSecondary` parameter set to `true` and the `options` parameter must
+include `Mode::SecondaryNotification`, See `SingleApplication::Mode` for more
+details.
+
+Here is an example:
+
+```cpp
+if( app.isSecondary() ) {
+ // This API requires LIBS += User32.lib to be added to the project
+ AllowSetForegroundWindow( DWORD( app.primaryPid() ) );
+}
+
+if( app.isPrimary() ) {
+ QObject::connect(
+ &app,
+ &SingleApplication::instanceStarted,
+ this,
+ &App::instanceStarted
+ );
+}
+```
+
+```cpp
+void App::instanceStarted() {
+ QApplication::setActiveWindow( [window/widget to set to the foreground] );
+}
+```
+
+[AllowSetForegroundWindow]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms632668.aspx
diff --git a/src/singleapplication/singleapplication.cpp b/src/singleapplication/singleapplication.cpp
new file mode 100644
index 00000000..09e264ef
--- /dev/null
+++ b/src/singleapplication/singleapplication.cpp
@@ -0,0 +1,271 @@
+// The MIT License (MIT)
+//
+// Copyright (c) Itay Grudev 2015 - 2020
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include
+#include
+#include
+
+#include "singleapplication.h"
+#include "singleapplication_p.h"
+
+/**
+ * @brief Constructor. Checks and fires up LocalServer or closes the program
+ * if another instance already exists
+ * @param argc
+ * @param argv
+ * @param allowSecondary Whether to enable secondary instance support
+ * @param options Optional flags to toggle specific behaviour
+ * @param timeout Maximum time blocking functions are allowed during app load
+ */
+SingleApplication::SingleApplication( int &argc, char *argv[], bool allowSecondary, Options options, int timeout, const QString &userData )
+ : app_t( argc, argv ), d_ptr( new SingleApplicationPrivate( this ) )
+{
+ Q_D( SingleApplication );
+
+#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
+ // On Android and iOS since the library is not supported fallback to
+ // standard QApplication behaviour by simply returning at this point.
+ qWarning() << "SingleApplication is not supported on Android and iOS systems.";
+ return;
+#endif
+
+ // Store the current mode of the program
+ d->options = options;
+
+ // Add any unique user data
+ if ( ! userData.isEmpty() )
+ d->addAppData( userData );
+
+ // Generating an application ID used for identifying the shared memory
+ // block and QLocalServer
+ d->genBlockServerName();
+
+ // To mitigate QSharedMemory issues with large amount of processes
+ // attempting to attach at the same time
+ SingleApplicationPrivate::randomSleep();
+
+#ifdef Q_OS_UNIX
+ // By explicitly attaching it and then deleting it we make sure that the
+ // memory is deleted even after the process has crashed on Unix.
+ d->memory = new QSharedMemory( d->blockServerName );
+ d->memory->attach();
+ delete d->memory;
+#endif
+ // Guarantee thread safe behaviour with a shared memory block.
+ d->memory = new QSharedMemory( d->blockServerName );
+
+ // Create a shared memory block
+ if( d->memory->create( sizeof( InstancesInfo ) )){
+ // Initialize the shared memory block
+ if( ! d->memory->lock() ){
+ qCritical() << "SingleApplication: Unable to lock memory block after create.";
+ abortSafely();
+ }
+ d->initializeMemoryBlock();
+ } else {
+ if( d->memory->error() == QSharedMemory::AlreadyExists ){
+ // Attempt to attach to the memory segment
+ if( ! d->memory->attach() ){
+ qCritical() << "SingleApplication: Unable to attach to shared memory block.";
+ abortSafely();
+ }
+ if( ! d->memory->lock() ){
+ qCritical() << "SingleApplication: Unable to lock memory block after attach.";
+ abortSafely();
+ }
+ } else {
+ qCritical() << "SingleApplication: Unable to create block.";
+ abortSafely();
+ }
+ }
+
+ auto *inst = static_cast( d->memory->data() );
+ QElapsedTimer time;
+ time.start();
+
+ // Make sure the shared memory block is initialised and in consistent state
+ while( true ){
+ // If the shared memory block's checksum is valid continue
+ if( d->blockChecksum() == inst->checksum ) break;
+
+ // If more than 5s have elapsed, assume the primary instance crashed and
+ // assume it's position
+ if( time.elapsed() > 5000 ){
+ qWarning() << "SingleApplication: Shared memory block has been in an inconsistent state from more than 5s. Assuming primary instance failure.";
+ d->initializeMemoryBlock();
+ }
+
+ // Otherwise wait for a random period and try again. The random sleep here
+ // limits the probability of a collision between two racing apps and
+ // allows the app to initialise faster
+ if( ! d->memory->unlock() ){
+ qDebug() << "SingleApplication: Unable to unlock memory for random wait.";
+ qDebug() << d->memory->errorString();
+ }
+ SingleApplicationPrivate::randomSleep();
+ if( ! d->memory->lock() ){
+ qCritical() << "SingleApplication: Unable to lock memory after random wait.";
+ abortSafely();
+ }
+ }
+
+ if( inst->primary == false ){
+ d->startPrimary();
+ if( ! d->memory->unlock() ){
+ qDebug() << "SingleApplication: Unable to unlock memory after primary start.";
+ qDebug() << d->memory->errorString();
+ }
+ return;
+ }
+
+ // Check if another instance can be started
+ if( allowSecondary ){
+ d->startSecondary();
+ if( d->options & Mode::SecondaryNotification ){
+ d->connectToPrimary( timeout, SingleApplicationPrivate::SecondaryInstance );
+ }
+ if( ! d->memory->unlock() ){
+ qDebug() << "SingleApplication: Unable to unlock memory after secondary start.";
+ qDebug() << d->memory->errorString();
+ }
+ return;
+ }
+
+ if( ! d->memory->unlock() ){
+ qDebug() << "SingleApplication: Unable to unlock memory at end of execution.";
+ qDebug() << d->memory->errorString();
+ }
+
+ d->connectToPrimary( timeout, SingleApplicationPrivate::NewInstance );
+
+ delete d;
+
+ ::exit( EXIT_SUCCESS );
+}
+
+SingleApplication::~SingleApplication()
+{
+ Q_D( SingleApplication );
+ delete d;
+}
+
+/**
+ * Checks if the current application instance is primary.
+ * @return Returns true if the instance is primary, false otherwise.
+ */
+bool SingleApplication::isPrimary() const
+{
+ Q_D( const SingleApplication );
+ return d->server != nullptr;
+}
+
+/**
+ * Checks if the current application instance is secondary.
+ * @return Returns true if the instance is secondary, false otherwise.
+ */
+bool SingleApplication::isSecondary() const
+{
+ Q_D( const SingleApplication );
+ return d->server == nullptr;
+}
+
+/**
+ * Allows you to identify an instance by returning unique consecutive instance
+ * ids. It is reset when the first (primary) instance of your app starts and
+ * only incremented afterwards.
+ * @return Returns a unique instance id.
+ */
+quint32 SingleApplication::instanceId() const
+{
+ Q_D( const SingleApplication );
+ return d->instanceNumber;
+}
+
+/**
+ * Returns the OS PID (Process Identifier) of the process running the primary
+ * instance. Especially useful when SingleApplication is coupled with OS.
+ * specific APIs.
+ * @return Returns the primary instance PID.
+ */
+qint64 SingleApplication::primaryPid() const
+{
+ Q_D( const SingleApplication );
+ return d->primaryPid();
+}
+
+/**
+ * Returns the username the primary instance is running as.
+ * @return Returns the username the primary instance is running as.
+ */
+QString SingleApplication::primaryUser() const
+{
+ Q_D( const SingleApplication );
+ return d->primaryUser();
+}
+
+/**
+ * Returns the username the current instance is running as.
+ * @return Returns the username the current instance is running as.
+ */
+QString SingleApplication::currentUser() const
+{
+ return SingleApplicationPrivate::getUsername();
+}
+
+/**
+ * Sends message to the Primary Instance.
+ * @param message The message to send.
+ * @param timeout the maximum timeout in milliseconds for blocking functions.
+ * @return true if the message was sent successfuly, false otherwise.
+ */
+bool SingleApplication::sendMessage( const QByteArray &message, int timeout )
+{
+ Q_D( SingleApplication );
+
+ // Nobody to connect to
+ if( isPrimary() ) return false;
+
+ // Make sure the socket is connected
+ if( ! d->connectToPrimary( timeout, SingleApplicationPrivate::Reconnect ) )
+ return false;
+
+ return d->writeConfirmedMessage( timeout, message );
+}
+
+/**
+ * Cleans up the shared memory block and exits with a failure.
+ * This function halts program execution.
+ */
+void SingleApplication::abortSafely()
+{
+ Q_D( SingleApplication );
+
+ qCritical() << "SingleApplication: " << d->memory->error() << d->memory->errorString();
+ delete d;
+ ::exit( EXIT_FAILURE );
+}
+
+QStringList SingleApplication::userData() const
+{
+ Q_D( const SingleApplication );
+ return d->appData();
+}
diff --git a/src/singleapplication/singleapplication.h b/src/singleapplication/singleapplication.h
new file mode 100644
index 00000000..91cabf93
--- /dev/null
+++ b/src/singleapplication/singleapplication.h
@@ -0,0 +1,154 @@
+// The MIT License (MIT)
+//
+// Copyright (c) Itay Grudev 2015 - 2018
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef SINGLE_APPLICATION_H
+#define SINGLE_APPLICATION_H
+
+#include
+#include
+
+#ifndef QAPPLICATION_CLASS
+ #define QAPPLICATION_CLASS QCoreApplication
+#endif
+
+#include QT_STRINGIFY(QAPPLICATION_CLASS)
+
+class SingleApplicationPrivate;
+
+/**
+ * @brief The SingleApplication class handles multiple instances of the same
+ * Application
+ * @see QCoreApplication
+ */
+class SingleApplication : public QAPPLICATION_CLASS
+{
+ Q_OBJECT
+
+ using app_t = QAPPLICATION_CLASS;
+
+public:
+ /**
+ * @brief Mode of operation of SingleApplication.
+ * Whether the block should be user-wide or system-wide and whether the
+ * primary instance should be notified when a secondary instance had been
+ * started.
+ * @note Operating system can restrict the shared memory blocks to the same
+ * user, in which case the User/System modes will have no effect and the
+ * block will be user wide.
+ * @enum
+ */
+ enum Mode {
+ User = 1 << 0,
+ System = 1 << 1,
+ SecondaryNotification = 1 << 2,
+ ExcludeAppVersion = 1 << 3,
+ ExcludeAppPath = 1 << 4
+ };
+ Q_DECLARE_FLAGS(Options, Mode)
+
+ /**
+ * @brief Intitializes a SingleApplication instance with argc command line
+ * arguments in argv
+ * @arg {int &} argc - Number of arguments in argv
+ * @arg {const char *[]} argv - Supplied command line arguments
+ * @arg {bool} allowSecondary - Whether to start the instance as secondary
+ * if there is already a primary instance.
+ * @arg {Mode} mode - Whether for the SingleApplication block to be applied
+ * User wide or System wide.
+ * @arg {int} timeout - Timeout to wait in milliseconds.
+ * @note argc and argv may be changed as Qt removes arguments that it
+ * recognizes
+ * @note Mode::SecondaryNotification only works if set on both the primary
+ * instance and the secondary instance.
+ * @note The timeout is just a hint for the maximum time of blocking
+ * operations. It does not guarantee that the SingleApplication
+ * initialisation will be completed in given time, though is a good hint.
+ * Usually 4*timeout would be the worst case (fail) scenario.
+ * @see See the corresponding QAPPLICATION_CLASS constructor for reference
+ */
+ explicit SingleApplication( int &argc, char *argv[], bool allowSecondary = false, Options options = Mode::User, int timeout = 1000, const QString &userData = {} );
+ ~SingleApplication() override;
+
+ /**
+ * @brief Returns if the instance is the primary instance
+ * @returns {bool}
+ */
+ bool isPrimary() const;
+
+ /**
+ * @brief Returns if the instance is a secondary instance
+ * @returns {bool}
+ */
+ bool isSecondary() const;
+
+ /**
+ * @brief Returns a unique identifier for the current instance
+ * @returns {qint32}
+ */
+ quint32 instanceId() const;
+
+ /**
+ * @brief Returns the process ID (PID) of the primary instance
+ * @returns {qint64}
+ */
+ qint64 primaryPid() const;
+
+ /**
+ * @brief Returns the username of the user running the primary instance
+ * @returns {QString}
+ */
+ QString primaryUser() const;
+
+ /**
+ * @brief Returns the username of the current user
+ * @returns {QString}
+ */
+ QString currentUser() const;
+
+ /**
+ * @brief Sends a message to the primary instance. Returns true on success.
+ * @param {int} timeout - Timeout for connecting
+ * @returns {bool}
+ * @note sendMessage() will return false if invoked from the primary
+ * instance.
+ */
+ bool sendMessage( const QByteArray &message, int timeout = 100 );
+
+ /**
+ * @brief Get the set user data.
+ * @returns {QStringList}
+ */
+ QStringList userData() const;
+
+Q_SIGNALS:
+ void instanceStarted();
+ void receivedMessage( quint32 instanceId, QByteArray message );
+
+private:
+ SingleApplicationPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(SingleApplication)
+ void abortSafely();
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(SingleApplication::Options)
+
+#endif // SINGLE_APPLICATION_H
diff --git a/src/singleapplication/singleapplication.pri b/src/singleapplication/singleapplication.pri
new file mode 100644
index 00000000..ae81f599
--- /dev/null
+++ b/src/singleapplication/singleapplication.pri
@@ -0,0 +1,20 @@
+QT += core network
+CONFIG += c++11
+
+HEADERS += $$PWD/SingleApplication \
+ $$PWD/singleapplication.h \
+ $$PWD/singleapplication_p.h
+SOURCES += $$PWD/singleapplication.cpp \
+ $$PWD/singleapplication_p.cpp
+
+INCLUDEPATH += $$PWD
+
+win32 {
+ msvc:LIBS += Advapi32.lib
+ gcc:LIBS += -ladvapi32
+}
+
+DISTFILES += \
+ $$PWD/README.md \
+ $$PWD/CHANGELOG.md \
+ $$PWD/Windows.md
diff --git a/src/singleapplication/singleapplication_p.cpp b/src/singleapplication/singleapplication_p.cpp
new file mode 100644
index 00000000..1a061f23
--- /dev/null
+++ b/src/singleapplication/singleapplication_p.cpp
@@ -0,0 +1,538 @@
+// The MIT License (MIT)
+//
+// Copyright (c) Itay Grudev 2015 - 2020
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+//
+// W A R N I N G !!!
+// -----------------
+//
+// This file is not part of the SingleApplication API. It is used purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or may even be removed.
+//
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
+#include
+#else
+#include
+#endif
+
+#include "singleapplication.h"
+#include "singleapplication_p.h"
+
+#ifdef Q_OS_UNIX
+ #include
+ #include
+ #include
+#endif
+
+#ifdef Q_OS_WIN
+ #ifndef NOMINMAX
+ #define NOMINMAX 1
+ #endif
+ #include
+ #include
+#endif
+
+SingleApplicationPrivate::SingleApplicationPrivate( SingleApplication *q_ptr )
+ : q_ptr( q_ptr )
+{
+ server = nullptr;
+ socket = nullptr;
+ memory = nullptr;
+ instanceNumber = 0;
+}
+
+SingleApplicationPrivate::~SingleApplicationPrivate()
+{
+ if( socket != nullptr ){
+ socket->close();
+ delete socket;
+ }
+
+ if( memory != nullptr ){
+ memory->lock();
+ auto *inst = static_cast(memory->data());
+ if( server != nullptr ){
+ server->close();
+ delete server;
+ inst->primary = false;
+ inst->primaryPid = -1;
+ inst->primaryUser[0] = '\0';
+ inst->checksum = blockChecksum();
+ }
+ memory->unlock();
+
+ delete memory;
+ }
+}
+
+QString SingleApplicationPrivate::getUsername()
+{
+#ifdef Q_OS_WIN
+ wchar_t username[UNLEN + 1];
+ // Specifies size of the buffer on input
+ DWORD usernameLength = UNLEN + 1;
+ if( GetUserNameW( username, &usernameLength ) )
+ return QString::fromWCharArray( username );
+#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
+ return QString::fromLocal8Bit( qgetenv( "USERNAME" ) );
+#else
+ return qEnvironmentVariable( "USERNAME" );
+#endif
+#endif
+#ifdef Q_OS_UNIX
+ QString username;
+ uid_t uid = geteuid();
+ struct passwd *pw = getpwuid( uid );
+ if( pw )
+ username = QString::fromLocal8Bit( pw->pw_name );
+ if ( username.isEmpty() ){
+#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
+ username = QString::fromLocal8Bit( qgetenv( "USER" ) );
+#else
+ username = qEnvironmentVariable( "USER" );
+#endif
+ }
+ return username;
+#endif
+}
+
+void SingleApplicationPrivate::genBlockServerName()
+{
+ QCryptographicHash appData( QCryptographicHash::Sha256 );
+ appData.addData( "SingleApplication", 17 );
+ appData.addData( SingleApplication::app_t::applicationName().toUtf8() );
+ appData.addData( SingleApplication::app_t::organizationName().toUtf8() );
+ appData.addData( SingleApplication::app_t::organizationDomain().toUtf8() );
+
+ if ( ! appDataList.isEmpty() )
+ appData.addData( appDataList.join( "" ).toUtf8() );
+
+ if( ! (options & SingleApplication::Mode::ExcludeAppVersion) ){
+ appData.addData( SingleApplication::app_t::applicationVersion().toUtf8() );
+ }
+
+ if( ! (options & SingleApplication::Mode::ExcludeAppPath) ){
+#if defined(Q_OS_WIN)
+ appData.addData( SingleApplication::app_t::applicationFilePath().toLower().toUtf8() );
+#elif defined(Q_OS_LINUX)
+ // If the application is running as an AppImage then the APPIMAGE env var should be used
+ // instead of applicationPath() as each instance is launched with its own executable path
+ const QByteArray appImagePath = qgetenv( "APPIMAGE" );
+ if( appImagePath.isEmpty() ){ // Not running as AppImage: use path to executable file
+ appData.addData( SingleApplication::app_t::applicationFilePath().toUtf8() );
+ } else { // Running as AppImage: Use absolute path to AppImage file
+ appData.addData( appImagePath );
+ };
+#else
+ appData.addData( SingleApplication::app_t::applicationFilePath().toUtf8() );
+#endif
+ }
+
+ // User level block requires a user specific data in the hash
+ if( options & SingleApplication::Mode::User ){
+ appData.addData( getUsername().toUtf8() );
+ }
+
+ // Replace the backslash in RFC 2045 Base64 [a-zA-Z0-9+/=] to comply with
+ // server naming requirements.
+ blockServerName = appData.result().toBase64().replace("/", "_");
+}
+
+void SingleApplicationPrivate::initializeMemoryBlock() const
+{
+ auto *inst = static_cast( memory->data() );
+ inst->primary = false;
+ inst->secondary = 0;
+ inst->primaryPid = -1;
+ inst->primaryUser[0] = '\0';
+ inst->checksum = blockChecksum();
+}
+
+void SingleApplicationPrivate::startPrimary()
+{
+ // Reset the number of connections
+ auto *inst = static_cast ( memory->data() );
+
+ inst->primary = true;
+ inst->primaryPid = QCoreApplication::applicationPid();
+ qstrncpy( inst->primaryUser, getUsername().toUtf8().data(), sizeof(inst->primaryUser) );
+ inst->checksum = blockChecksum();
+ instanceNumber = 0;
+ // Successful creation means that no main process exists
+ // So we start a QLocalServer to listen for connections
+ QLocalServer::removeServer( blockServerName );
+ server = new QLocalServer();
+
+ // Restrict access to the socket according to the
+ // SingleApplication::Mode::User flag on User level or no restrictions
+ if( options & SingleApplication::Mode::User ){
+ server->setSocketOptions( QLocalServer::UserAccessOption );
+ } else {
+ server->setSocketOptions( QLocalServer::WorldAccessOption );
+ }
+
+ server->listen( blockServerName );
+ QObject::connect(
+ server,
+ &QLocalServer::newConnection,
+ this,
+ &SingleApplicationPrivate::slotConnectionEstablished
+ );
+}
+
+void SingleApplicationPrivate::startSecondary()
+{
+ auto *inst = static_cast ( memory->data() );
+
+ inst->secondary += 1;
+ inst->checksum = blockChecksum();
+ instanceNumber = inst->secondary;
+}
+
+bool SingleApplicationPrivate::connectToPrimary( int msecs, ConnectionType connectionType )
+{
+ QElapsedTimer time;
+ time.start();
+
+ // Connect to the Local Server of the Primary Instance if not already
+ // connected.
+ if( socket == nullptr ){
+ socket = new QLocalSocket();
+ }
+
+ if( socket->state() == QLocalSocket::ConnectedState ) return true;
+
+ if( socket->state() != QLocalSocket::ConnectedState ){
+
+ while( true ){
+ randomSleep();
+
+ if( socket->state() != QLocalSocket::ConnectingState )
+ socket->connectToServer( blockServerName );
+
+ if( socket->state() == QLocalSocket::ConnectingState ){
+ socket->waitForConnected( static_cast(msecs - time.elapsed()) );
+ }
+
+ // If connected break out of the loop
+ if( socket->state() == QLocalSocket::ConnectedState ) break;
+
+ // If elapsed time since start is longer than the method timeout return
+ if( time.elapsed() >= msecs ) return false;
+ }
+ }
+
+ // Initialisation message according to the SingleApplication protocol
+ QByteArray initMsg;
+ QDataStream writeStream(&initMsg, QIODevice::WriteOnly);
+
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
+ writeStream.setVersion(QDataStream::Qt_5_6);
+#endif
+
+ writeStream << blockServerName.toLatin1();
+ writeStream << static_cast(connectionType);
+ writeStream << instanceNumber;
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ quint16 checksum = qChecksum(QByteArray(initMsg, static_cast(initMsg.length())));
+#else
+ quint16 checksum = qChecksum(initMsg.constData(), static_cast(initMsg.length()));
+#endif
+ writeStream << checksum;
+
+ return writeConfirmedMessage( static_cast(msecs - time.elapsed()), initMsg );
+}
+
+void SingleApplicationPrivate::writeAck( QLocalSocket *sock ) {
+ sock->putChar('\n');
+}
+
+bool SingleApplicationPrivate::writeConfirmedMessage (int msecs, const QByteArray &msg)
+{
+ QElapsedTimer time;
+ time.start();
+
+ // Frame 1: The header indicates the message length that follows
+ QByteArray header;
+ QDataStream headerStream(&header, QIODevice::WriteOnly);
+
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
+ headerStream.setVersion(QDataStream::Qt_5_6);
+#endif
+ headerStream << static_cast ( msg.length() );
+
+ if( ! writeConfirmedFrame( static_cast(msecs - time.elapsed()), header ))
+ return false;
+
+ // Frame 2: The message
+ return writeConfirmedFrame( static_cast(msecs - time.elapsed()), msg );
+}
+
+bool SingleApplicationPrivate::writeConfirmedFrame( int msecs, const QByteArray &msg )
+{
+ socket->write( msg );
+ socket->flush();
+
+ bool result = socket->waitForReadyRead( msecs ); // await ack byte
+ if (result) {
+ socket->read( 1 );
+ return true;
+ }
+
+ return false;
+}
+
+quint16 SingleApplicationPrivate::blockChecksum() const
+{
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ quint16 checksum = qChecksum(QByteArray(static_cast(memory->constData()), offsetof(InstancesInfo, checksum)));
+#else
+ quint16 checksum = qChecksum(static_cast(memory->constData()), offsetof(InstancesInfo, checksum));
+#endif
+ return checksum;
+}
+
+qint64 SingleApplicationPrivate::primaryPid() const
+{
+ qint64 pid;
+
+ memory->lock();
+ auto *inst = static_cast( memory->data() );
+ pid = inst->primaryPid;
+ memory->unlock();
+
+ return pid;
+}
+
+QString SingleApplicationPrivate::primaryUser() const
+{
+ QByteArray username;
+
+ memory->lock();
+ auto *inst = static_cast( memory->data() );
+ username = inst->primaryUser;
+ memory->unlock();
+
+ return QString::fromUtf8( username );
+}
+
+/**
+ * @brief Executed when a connection has been made to the LocalServer
+ */
+void SingleApplicationPrivate::slotConnectionEstablished()
+{
+ QLocalSocket *nextConnSocket = server->nextPendingConnection();
+ connectionMap.insert(nextConnSocket, ConnectionInfo());
+
+ QObject::connect(nextConnSocket, &QLocalSocket::aboutToClose, this,
+ [nextConnSocket, this](){
+ auto &info = connectionMap[nextConnSocket];
+ this->slotClientConnectionClosed( nextConnSocket, info.instanceId );
+ }
+ );
+
+ QObject::connect(nextConnSocket, &QLocalSocket::disconnected, nextConnSocket, &QLocalSocket::deleteLater);
+
+ QObject::connect(nextConnSocket, &QLocalSocket::destroyed, this,
+ [nextConnSocket, this](){
+ connectionMap.remove(nextConnSocket);
+ }
+ );
+
+ QObject::connect(nextConnSocket, &QLocalSocket::readyRead, this,
+ [nextConnSocket, this](){
+ auto &info = connectionMap[nextConnSocket];
+ switch(info.stage){
+ case StageInitHeader:
+ readMessageHeader( nextConnSocket, StageInitBody );
+ break;
+ case StageInitBody:
+ readInitMessageBody(nextConnSocket);
+ break;
+ case StageConnectedHeader:
+ readMessageHeader( nextConnSocket, StageConnectedBody );
+ break;
+ case StageConnectedBody:
+ this->slotDataAvailable( nextConnSocket, info.instanceId );
+ break;
+ default:
+ break;
+ };
+ }
+ );
+}
+
+void SingleApplicationPrivate::readMessageHeader( QLocalSocket *sock, SingleApplicationPrivate::ConnectionStage nextStage )
+{
+ if (!connectionMap.contains( sock )){
+ return;
+ }
+
+ if( sock->bytesAvailable() < ( qint64 )sizeof( quint64 ) ){
+ return;
+ }
+
+ QDataStream headerStream( sock );
+
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
+ headerStream.setVersion( QDataStream::Qt_5_6 );
+#endif
+
+ // Read the header to know the message length
+ quint64 msgLen = 0;
+ headerStream >> msgLen;
+ ConnectionInfo &info = connectionMap[sock];
+ info.stage = nextStage;
+ info.msgLen = msgLen;
+
+ writeAck( sock );
+}
+
+bool SingleApplicationPrivate::isFrameComplete( QLocalSocket *sock )
+{
+ if (!connectionMap.contains( sock )){
+ return false;
+ }
+
+ ConnectionInfo &info = connectionMap[sock];
+ if( sock->bytesAvailable() < ( qint64 )info.msgLen ){
+ return false;
+ }
+
+ return true;
+}
+
+void SingleApplicationPrivate::readInitMessageBody( QLocalSocket *sock )
+{
+ Q_Q(SingleApplication);
+
+ if( !isFrameComplete( sock ) )
+ return;
+
+ // Read the message body
+ QByteArray msgBytes = sock->readAll();
+ QDataStream readStream(msgBytes);
+
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
+ readStream.setVersion( QDataStream::Qt_5_6 );
+#endif
+
+ // server name
+ QByteArray latin1Name;
+ readStream >> latin1Name;
+
+ // connection type
+ ConnectionType connectionType = InvalidConnection;
+ quint8 connTypeVal = InvalidConnection;
+ readStream >> connTypeVal;
+ connectionType = static_cast ( connTypeVal );
+
+ // instance id
+ quint32 instanceId = 0;
+ readStream >> instanceId;
+
+ // checksum
+ quint16 msgChecksum = 0;
+ readStream >> msgChecksum;
+
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ const quint16 actualChecksum = qChecksum(QByteArray(msgBytes, static_cast(msgBytes.length() - sizeof(quint16))));
+#else
+ const quint16 actualChecksum = qChecksum(msgBytes.constData(), static_cast(msgBytes.length() - sizeof(quint16)));
+#endif
+
+ bool isValid = readStream.status() == QDataStream::Ok &&
+ QLatin1String(latin1Name) == blockServerName &&
+ msgChecksum == actualChecksum;
+
+ if( !isValid ){
+ sock->close();
+ return;
+ }
+
+ ConnectionInfo &info = connectionMap[sock];
+ info.instanceId = instanceId;
+ info.stage = StageConnectedHeader;
+
+ if( connectionType == NewInstance ||
+ ( connectionType == SecondaryInstance &&
+ options & SingleApplication::Mode::SecondaryNotification ) )
+ {
+ Q_EMIT q->instanceStarted();
+ }
+
+ writeAck( sock );
+}
+
+void SingleApplicationPrivate::slotDataAvailable( QLocalSocket *dataSocket, quint32 instanceId )
+{
+ Q_Q(SingleApplication);
+
+ if ( !isFrameComplete( dataSocket ) )
+ return;
+
+ Q_EMIT q->receivedMessage( instanceId, dataSocket->readAll() );
+
+ writeAck( dataSocket );
+
+ ConnectionInfo &info = connectionMap[dataSocket];
+ info.stage = StageConnectedHeader;
+}
+
+void SingleApplicationPrivate::slotClientConnectionClosed( QLocalSocket *closedSocket, quint32 instanceId )
+{
+ if( closedSocket->bytesAvailable() > 0 )
+ slotDataAvailable( closedSocket, instanceId );
+}
+
+void SingleApplicationPrivate::randomSleep()
+{
+#if QT_VERSION >= QT_VERSION_CHECK( 5, 10, 0 )
+ QThread::msleep( QRandomGenerator::global()->bounded( 8u, 18u ));
+#else
+ qsrand( QDateTime::currentMSecsSinceEpoch() % std::numeric_limits::max() );
+ QThread::msleep( qrand() % 11 + 8);
+#endif
+}
+
+void SingleApplicationPrivate::addAppData(const QString &data)
+{
+ appDataList.push_back(data);
+}
+
+QStringList SingleApplicationPrivate::appData() const
+{
+ return appDataList;
+}
diff --git a/src/singleapplication/singleapplication_p.h b/src/singleapplication/singleapplication_p.h
new file mode 100644
index 00000000..58507cf3
--- /dev/null
+++ b/src/singleapplication/singleapplication_p.h
@@ -0,0 +1,109 @@
+// The MIT License (MIT)
+//
+// Copyright (c) Itay Grudev 2015 - 2020
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+//
+// W A R N I N G !!!
+// -----------------
+//
+// This file is not part of the SingleApplication API. It is used purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or may even be removed.
+//
+
+#ifndef SINGLEAPPLICATION_P_H
+#define SINGLEAPPLICATION_P_H
+
+#include
+#include
+#include
+#include "singleapplication.h"
+
+struct InstancesInfo {
+ bool primary;
+ quint32 secondary;
+ qint64 primaryPid;
+ char primaryUser[128];
+ quint16 checksum; // Must be the last field
+};
+
+struct ConnectionInfo {
+ qint64 msgLen = 0;
+ quint32 instanceId = 0;
+ quint8 stage = 0;
+};
+
+class SingleApplicationPrivate : public QObject {
+Q_OBJECT
+public:
+ enum ConnectionType : quint8 {
+ InvalidConnection = 0,
+ NewInstance = 1,
+ SecondaryInstance = 2,
+ Reconnect = 3
+ };
+ enum ConnectionStage : quint8 {
+ StageInitHeader = 0,
+ StageInitBody = 1,
+ StageConnectedHeader = 2,
+ StageConnectedBody = 3,
+ };
+ Q_DECLARE_PUBLIC(SingleApplication)
+
+ SingleApplicationPrivate( SingleApplication *q_ptr );
+ ~SingleApplicationPrivate() override;
+
+ static QString getUsername();
+ void genBlockServerName();
+ void initializeMemoryBlock() const;
+ void startPrimary();
+ void startSecondary();
+ bool connectToPrimary( int msecs, ConnectionType connectionType );
+ quint16 blockChecksum() const;
+ qint64 primaryPid() const;
+ QString primaryUser() const;
+ bool isFrameComplete(QLocalSocket *sock);
+ void readMessageHeader(QLocalSocket *socket, ConnectionStage nextStage);
+ void readInitMessageBody(QLocalSocket *socket);
+ void writeAck(QLocalSocket *sock);
+ bool writeConfirmedFrame(int msecs, const QByteArray &msg);
+ bool writeConfirmedMessage(int msecs, const QByteArray &msg);
+ static void randomSleep();
+ void addAppData(const QString &data);
+ QStringList appData() const;
+
+ SingleApplication *q_ptr;
+ QSharedMemory *memory;
+ QLocalSocket *socket;
+ QLocalServer *server;
+ quint32 instanceNumber;
+ QString blockServerName;
+ SingleApplication::Options options;
+ QMap connectionMap;
+ QStringList appDataList;
+
+public Q_SLOTS:
+ void slotConnectionEstablished();
+ void slotDataAvailable( QLocalSocket*, quint32 );
+ void slotClientConnectionClosed( QLocalSocket*, quint32 );
+};
+
+#endif // SINGLEAPPLICATION_P_H
diff --git a/src/tools/UBGraphicsAxes.cpp b/src/tools/UBGraphicsAxes.cpp
index 9fb6be2f..279d0342 100644
--- a/src/tools/UBGraphicsAxes.cpp
+++ b/src/tools/UBGraphicsAxes.cpp
@@ -428,7 +428,6 @@ void UBGraphicsAxes::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
setCursor(Qt::ArrowCursor);
mCloseSvgItem->setVisible(mShowButtons);
mNumbersSvgItem->setVisible(mShowButtons);
- UBDrawingController::drawingController()->mActiveRuler = NULL;
event->accept();
update();
}
diff --git a/src/tools/UBGraphicsRuler.cpp b/src/tools/UBGraphicsRuler.cpp
index dd4a9e0c..d42ece6a 100644
--- a/src/tools/UBGraphicsRuler.cpp
+++ b/src/tools/UBGraphicsRuler.cpp
@@ -420,6 +420,9 @@ void UBGraphicsRuler::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
UBStylusTool::Enum currentTool = (UBStylusTool::Enum)UBDrawingController::drawingController ()->stylusTool ();
+ if (UBDrawingController::drawingController()->mActiveRuler == nullptr)
+ UBDrawingController::drawingController()->mActiveRuler = this;
+
if (currentTool == UBStylusTool::Selector ||
currentTool == UBStylusTool::Play)
{
@@ -450,7 +453,6 @@ void UBGraphicsRuler::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
else if (UBDrawingController::drawingController()->isDrawingTool())
{
setCursor(drawRulerLineCursor());
- UBDrawingController::drawingController()->mActiveRuler = this;
event->accept();
}
}
@@ -462,7 +464,7 @@ void UBGraphicsRuler::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
mCloseSvgItem->setVisible(mShowButtons);
mResizeSvgItem->setVisible(mShowButtons);
mRotateSvgItem->setVisible(mShowButtons);
- UBDrawingController::drawingController()->mActiveRuler = NULL;
+ UBDrawingController::drawingController()->mActiveRuler = nullptr;
event->accept();
update();
}
diff --git a/src/web/UBWebController.cpp b/src/web/UBWebController.cpp
index f47bac80..eb6e65bb 100644
--- a/src/web/UBWebController.cpp
+++ b/src/web/UBWebController.cpp
@@ -141,10 +141,6 @@ void UBWebController::webBrowserInstance()
UBApplication::app()->insertSpaceToToolbarBeforeAction(mMainWindow->webToolBar, mMainWindow->actionBoard, 32);
UBApplication::app()->decorateActionMenu(mMainWindow->actionMenu);
- bool showAddBookmarkButtons = UBSettings::settings()->webShowAddBookmarkButton->get().toBool();
- mMainWindow->actionBookmarks->setVisible(showAddBookmarkButtons);
- mMainWindow->actionAddBookmark->setVisible(showAddBookmarkButtons);
-
showTabAtTop(UBSettings::settings()->appToolBarPositionedAtTop->get().toBool());
adaptToolBar();
@@ -308,7 +304,7 @@ void UBWebController::setupPalettes()
UBApplication::boardController->paletteManager()->mKeyboardPalette, SLOT(onDeactivated()));
#endif
- connect(mMainWindow->actionWebTrapFlash, SIGNAL(triggered()), this, SLOT(trapFlash()));
+ connect(mMainWindow->actionCaptureWebContent, SIGNAL(triggered()), this, SLOT(trapFlash()));
connect(mMainWindow->actionWebCustomCapture, SIGNAL(triggered()), this, SLOT(customCapture()));
connect(mMainWindow->actionWebWindowCapture, SIGNAL(triggered()), this, SLOT(captureWindow()));
connect(mMainWindow->actionWebOEmbed, SIGNAL(triggered()), this, SLOT(captureoEmbed()));
diff --git a/src/web/browser/WBBrowserWindow.cpp b/src/web/browser/WBBrowserWindow.cpp
index 6b7ca6b9..24f780ff 100644
--- a/src/web/browser/WBBrowserWindow.cpp
+++ b/src/web/browser/WBBrowserWindow.cpp
@@ -248,9 +248,6 @@ void WBBrowserWindow::setupToolBar()
mWebToolBar->insertSeparator(mUniboardMainWindow->actionWebBigger);
connect(mUniboardMainWindow->actionHome, SIGNAL(triggered()), this , SLOT(slotHome()));
-
- connect(mUniboardMainWindow->actionBookmarks, SIGNAL(triggered()), this , SLOT(bookmarks()));
- connect(mUniboardMainWindow->actionAddBookmark, SIGNAL(triggered()), this , SLOT(addBookmark()));
connect(mUniboardMainWindow->actionWebBigger, SIGNAL(triggered()), this , SLOT(slotViewZoomIn()));
connect(mUniboardMainWindow->actionWebSmaller, SIGNAL(triggered()), this , SLOT(slotViewZoomOut()));
@@ -514,18 +511,6 @@ void WBBrowserWindow::tabCurrentChanged(int index)
}
-void WBBrowserWindow::bookmarks()
-{
- loadPage(UBSettings::settings()->webBookmarksPage->get().toString());
-}
-
-
-void WBBrowserWindow::addBookmark()
-{
- loadPage(UBSettings::settings()->webAddBookmarkUrl->get().toString() + currentTabWebView()->url().toString());
-}
-
-
WBWebView* WBBrowserWindow::paintWidget()
{
return mTabWidget->currentWebView();
diff --git a/src/web/browser/WBBrowserWindow.h b/src/web/browser/WBBrowserWindow.h
index 80926e3b..46959099 100644
--- a/src/web/browser/WBBrowserWindow.h
+++ b/src/web/browser/WBBrowserWindow.h
@@ -121,9 +121,6 @@ class WBBrowserWindow : public QWidget
void tabCurrentChanged(int);
- void bookmarks();
- void addBookmark();
-
void showTabAtTop(bool attop);
void aboutToShowBackMenu();