From 72d43788da91e0ccd3f6d4ffc28f7449ce3dafca Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Tue, 10 Nov 2015 12:49:26 +0100 Subject: [PATCH 001/243] Corrected signal/slot connection (signal function header changed) --- src/core/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/main.cpp b/src/core/main.cpp index 3cd783f8..090a206a 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -134,7 +134,7 @@ int main(int argc, char *argv[]) //app.initialize(false); // should not be needed anymore - QObject::connect(&app, SIGNAL(messageReceived(const QString&)), &app, SLOT(handleOpenMessage(const QString&))); + QObject::connect(&app, SIGNAL(messageReceived(const QString&, QObject*)), &app, SLOT(handleOpenMessage(const QString&))); qDebug() << "file name argument" << fileToOpen; int result = app.exec(fileToOpen); From 7a4e9d2e834ae131d05981392985ce1257422a38 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Tue, 10 Nov 2015 13:20:03 +0100 Subject: [PATCH 002/243] Removed UBGraphicsPolygonItem::shape() Long version: UBGraphicsPolygonItem::shape() sometimes caused OpenBoard to crash due to inifinite recursion. This is easily replicated by trying to use the highlighting tool. The reason is: shape() calls boundingRect(); this function's definition is: QRectF QGraphicsPolygonItem::boundingRect() const { Q_D(const QGraphicsPolygonItem); if (d->boundingRect.isNull()) { qreal pw = pen().style() == Qt::NoPen ? qreal(0) : pen().widthF(); if (pw == 0.0) d->boundingRect = d->polygon.boundingRect(); else d->boundingRect = shape().controlPointRect(); } return d->boundingRect; } In the case where pw != 0, the shape() function is called. However, it is shape() from the derived class, not the base class, which is called. In other words, UBGraphicsPolygonItem::shape() is called rather than QGraphicsPolygonItem::shape(). This means that boundingRect() is called again from within shape(), and so on, causing the program to crash. The fix was simply to remove UBGraphicsPolygonItem::shape(), as it appears to provide the same (or very similar) functionality to that of the base class's shape() function. In case this shape() function actually is needed, another workaround should be implemented to prevent this infinite recursion. --- src/domain/UBGraphicsPolygonItem.cpp | 10 ---------- src/domain/UBGraphicsPolygonItem.h | 1 - 2 files changed, 11 deletions(-) diff --git a/src/domain/UBGraphicsPolygonItem.cpp b/src/domain/UBGraphicsPolygonItem.cpp index bfbd515e..1f5b40c3 100644 --- a/src/domain/UBGraphicsPolygonItem.cpp +++ b/src/domain/UBGraphicsPolygonItem.cpp @@ -211,16 +211,6 @@ void UBGraphicsPolygonItem::paint ( QPainter * painter, const QStyleOptionGraphi QGraphicsPolygonItem::paint(painter, option, widget); } -QPainterPath UBGraphicsPolygonItem::shape() const -{ - - QPainterPath path; - path.addRect(boundingRect()); - - return path; -} - - UBGraphicsScene* UBGraphicsPolygonItem::scene() { return qobject_cast(QGraphicsPolygonItem::scene()); diff --git a/src/domain/UBGraphicsPolygonItem.h b/src/domain/UBGraphicsPolygonItem.h index 1296b65d..600e4598 100644 --- a/src/domain/UBGraphicsPolygonItem.h +++ b/src/domain/UBGraphicsPolygonItem.h @@ -132,7 +132,6 @@ class UBGraphicsPolygonItem : public QGraphicsPolygonItem, public UBItem protected: void paint ( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget); - QPainterPath shape () const; private: From d4e42b5163f9f02117e02b76fc04befe7479d16b Mon Sep 17 00:00:00 2001 From: agriche Date: Thu, 12 Nov 2015 13:39:35 +0100 Subject: [PATCH 003/243] - Add minor changes. --- changes_porting_qt5.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changes_porting_qt5.txt b/changes_porting_qt5.txt index 4c1324ae..50f23ce1 100644 --- a/changes_porting_qt5.txt +++ b/changes_porting_qt5.txt @@ -778,7 +778,7 @@ main.cpp - replace // qt_message_output(type, msg); by qt_message_output(type,context_m, msg); - +************************************ COMPILATION STATUS IN DEBUG STATUS : ************************************ From c4e28b5507b7ebbfa99e3c3b75924cf63dcd55e5 Mon Sep 17 00:00:00 2001 From: agriche Date: Thu, 12 Nov 2015 17:08:41 +0100 Subject: [PATCH 004/243] - Update the libraries config .pro (freetype,xpdf,quazip). --- changes_porting_qt5.txt | 48 +++++++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/changes_porting_qt5.txt b/changes_porting_qt5.txt index 50f23ce1..0819c3f7 100644 --- a/changes_porting_qt5.txt +++ b/changes_porting_qt5.txt @@ -374,8 +374,6 @@ UBOEmbedParser.cpp -replace toAscii--> toLatin1 qurl.setEncodedUrl(url.toLatin1()); (line 230) --replace - WBSqueezeLabel.h ----------------- @@ -395,7 +393,6 @@ UBOEmbedParser.cpp - replace //qurl.setEncodedUrl(url.toAscii()); by qurl.setUrl(url.toLatin1(),QUrl::TolerantMode); - WBChaseWidget.cpp ------------------ @@ -778,15 +775,19 @@ main.cpp - replace // qt_message_output(type, msg); by qt_message_output(type,context_m, msg); -************************************ -COMPILATION STATUS IN DEBUG STATUS : -************************************ +*************************** +COMPILATION IN DEBUG MODE : +*************************** - compile all libraries (freetype.lib quazip.lib,xpdf.lib) with success - issue: error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '2' doesn't match value '0' -=> solution: complation in RELEASE MODE +=> 1st solution: compilation in RELEASE MODE + +***************************** +COMPILATION IN RELEASE MODE : +***************************** - problem : LINK : fatal error LNK1123: échec lors de la conversion en fichier COFF msvc 2010 qt 5.2 => solution : @@ -817,14 +818,17 @@ cf http://stackoverflow.com/questions/10888391/error-link-fatal-error-lnk1123-fa into C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\cvtres.exe +The compilation works with success except warning message as following : + +- UBExportCFF.obj : warning LNK4217: locally defined symbol ??1UBCFFAdaptor@@QAE@XZ (public: __thiscall UBCFFAdaptor::~UBCFFAdaptor(void)) +imported in function "public: virtual void __thiscall UBExportCFF::persist(class UBDocumentProxy *)" +(?persist@UBExportCFF@@UAEXPAVUBDocumentProxy@@@Z). + OpenBoard.pro -------------- - pb: fatal error LNK1123: échec lors de la conversion en fichier COFF vs 2010 qt 5.2 => add QMAKE_LFLAGS += /INCREMENTAL:NO - - - UBBoardView.cpp ---------------- @@ -834,9 +838,31 @@ the ItemAt issue was solved by the last update methods from the repository. UBGraphicsTextItem.cpp ---------------------- - - replace //#include by #include . +*************************** +COMPILATION IN DEBUG MODE : +*************************** + +issue: error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '2' doesn't match value '0' + +solution : replace the following config libraries by debug_release flag (quazip.pro,xpdf.pro) + + +freetype.pro +-------- +- replace CONFIG += staticlib release by CONFIG += staticlib debug_and_release. + +quazip.pro +---------- + +- replace CONFIG += staticlib release by CONFIG += staticlib debug_and_release. + + +xpdf.pro +-------- +- replace CONFIG += staticlib release by CONFIG += staticlib debug_and_release. + From 91cc74fbd7cb70da6ec05652ddc4891d9ddd377c Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Mon, 16 Nov 2015 14:56:57 +0100 Subject: [PATCH 005/243] First pass at OS X port (Qt4->5; Carbon->Cocoa) Application compiles and runs, with some caveats. Full list of changes: - minor changes related to Qt4->Qt5 API differences - Replaced calls to Carbon framework by Cocoa - Removed registering of AE event handler. Seems to be done automatically in Qt5. - temporarily removed Podcast functionality, pending (presumably) complete re-write due to Quicktime being obsolete in newer OS X versions. - Created OBCocoa namespace, and associated files src/core/OBCocoa.h/.mm, to handle OS X - specific system calls. Currently used only by UBApplication, but can in the future provide a useful interface between the cocoa framework and OB, to avoid having too much OSX-specific code in various files --- OpenBoard.pro | 34 +++++++++-------- src/adaptors/UBThumbnailAdaptor.cpp | 2 +- src/board/UBBoardView.cpp | 3 +- src/core/OBCocoa.h | 11 ++++++ src/core/OBCocoa.mm | 24 ++++++++++++ src/core/UBApplication.cpp | 38 ++----------------- src/core/UBApplication.h | 9 +++-- src/core/UBApplicationController.cpp | 3 -- src/core/core.pri | 4 ++ src/desktop/UBWindowCapture_mac.mm | 3 +- src/frameworks/UBPlatformUtils_mac.mm | 12 +++--- src/gui/UBFloatingPalette.cpp | 2 +- ...lette_mac.cpp => UBKeyboardPalette_mac.mm} | 6 ++- src/gui/UBMagnifer.cpp | 2 +- src/gui/UBRubberBand.cpp | 10 ++--- src/gui/gui.pri | 3 +- src/podcast/UBPodcastController.cpp | 14 +++---- src/podcast/podcast.pri | 16 ++++---- 18 files changed, 104 insertions(+), 92 deletions(-) create mode 100644 src/core/OBCocoa.h create mode 100644 src/core/OBCocoa.mm rename src/gui/{UBKeyboardPalette_mac.cpp => UBKeyboardPalette_mac.mm} (97%) diff --git a/OpenBoard.pro b/OpenBoard.pro index 5f073bea..4ba4b151 100644 --- a/OpenBoard.pro +++ b/OpenBoard.pro @@ -128,32 +128,34 @@ win32 { macx { LIBS += -framework Foundation + LIBS += -framework Cocoa + LIBS += -framework Carbon LIBS += -lcrypto - CONFIG(release, debug|release):CONFIG += x86 + CONFIG(release, debug|release):CONFIG += x86_64 + CONFIG(debug, debug|release):CONFIG += x86_64 - # [03-02-2011] We must use the 32bit version for the moment - # because the Quicktime components used by this application - # are not yet available in 64bits. - CONFIG(debug, debug|release):CONFIG += x86 + # TODO Craig: switch to 64bit - QMAKE_MAC_SDK = "/Developer/SDKs/MacOSX10.6.sdk" - QMAKE_MACOSX_DEPLOYMENT_TARGET = "10.5" + QMAKE_MAC_SDK = macosx + QMAKE_MACOSX_DEPLOYMENT_TARGET = "10.10" - VERSION_RC_PATH = "$$BUILD_DIR/version_rc" + QMAKE_CXXFLAGS += -Wno-overloaded-virtual + #VERSION_RC_PATH = "$$BUILD_DIR/version_rc" + # No references to breakpad in the code =>is this still used? # Embed version into executable for breakpad - QMAKE_LFLAGS += -sectcreate \ - __DATA \ - __version \ - $$VERSION_RC_PATH + #QMAKE_LFLAGS += -sectcreate \ + # __DATA \ + # __version \ + # $$VERSION_RC_PATH QMAKE_CXXFLAGS_RELEASE += -gdwarf-2 \ -mdynamic-no-pic - QMAKE_CFLAGS += -fopenmp - QMAKE_CXXFLAGS += -fopenmp - QMAKE_LFLAGS += -fopenmp +# QMAKE_CFLAGS += -fopenmp + # QMAKE_CXXFLAGS += -fopenmp + # QMAKE_LFLAGS += -fopenmp CONTENTS_DIR = "Contents" RESOURCES_DIR = "Contents/Resources" @@ -364,7 +366,7 @@ macx { system(mkdir -p $$BUILD_DIR) system(printf \""$$OSX_VERSION"\" > $$BUILD_DIR/osx_version) system(printf \""$$VERSION"\" > $$BUILD_DIR/version) - system(printf "%02x%02x%02x%02x" `printf $$VERSION_RC | cut -d ',' -f 1` `printf $$VERSION_RC | cut -d ',' -f 2` `printf $$VERSION_RC | cut -d ',' -f 3` `printf $$VERSION_RC | cut -d ',' -f 4` | xxd -r -p > "$$VERSION_RC_PATH") + # system(printf "%02x%02x%02x%02x" `printf $$VERSION_RC | cut -d ',' -f 1` `printf $$VERSION_RC | cut -d ',' -f 2` `printf $$VERSION_RC | cut -d ',' -f 3` `printf $$VERSION_RC | cut -d ',' -f 4` | xxd -r -p > "$$VERSION_RC_PATH") } linux-g++* { diff --git a/src/adaptors/UBThumbnailAdaptor.cpp b/src/adaptors/UBThumbnailAdaptor.cpp index 96545d0f..660e3a7f 100644 --- a/src/adaptors/UBThumbnailAdaptor.cpp +++ b/src/adaptors/UBThumbnailAdaptor.cpp @@ -98,7 +98,7 @@ const QPixmap* UBThumbnailAdaptor::get(UBDocumentProxy* proxy, int pageIndex) #ifdef Q_OS_LINUX pix->load(fileName, 0, Qt::AutoColor); #else - pix->load(fileName, 0, Qt::AutoColor, false); + pix->load(fileName, 0, Qt::AutoColor); #endif } return pix; diff --git a/src/board/UBBoardView.cpp b/src/board/UBBoardView.cpp index 6024b07a..57b61d6f 100644 --- a/src/board/UBBoardView.cpp +++ b/src/board/UBBoardView.cpp @@ -872,7 +872,6 @@ bool UBBoardView::directTabletEvent(QEvent *event) tEvent = new QTabletEvent(tEvent->type() , mapFromGlobal(tEvent->pos()) , tEvent->globalPos() - , tEvent->hiResGlobalPos() , tEvent->device() , tEvent->pointerType() , tEvent->pressure() @@ -905,7 +904,7 @@ QWidget *UBBoardView::widgetForTabletEvent(QWidget *w, const QPoint &pos) QWidget *childAtPos = NULL; - QList childs = w->childItems(); + QList childs = w->children(); foreach(QObject *child, childs) { QWidget *childWidget = qobject_cast(child); diff --git a/src/core/OBCocoa.h b/src/core/OBCocoa.h new file mode 100644 index 00000000..f646d434 --- /dev/null +++ b/src/core/OBCocoa.h @@ -0,0 +1,11 @@ +/* + OBCocoa.h + + Header file permitting access to Mac OSX / Cocoa specific functions + +*/ + + +namespace OBCocoa { + void setFrontProcess(); +} diff --git a/src/core/OBCocoa.mm b/src/core/OBCocoa.mm new file mode 100644 index 00000000..53c01e2f --- /dev/null +++ b/src/core/OBCocoa.mm @@ -0,0 +1,24 @@ +#include "OBCocoa.h" +#include "UBApplicationController.h" + +#include +#import + +namespace OBCocoa { + +/** + * @brief Activate the current application + */ +void setFrontProcess() +{ + NSRunningApplication* app = [NSRunningApplication currentApplication]; + + // activate the application, forcing focus on it + [app activateWithOptions: NSApplicationActivateIgnoringOtherApps]; + + // other option:NSApplicationActivateAllWindows. This won't steal focus from another app, e.g + // if the user is doing something else while waiting for OpenBoard to load +} + + +} // namespace OBCocoa diff --git a/src/core/UBApplication.cpp b/src/core/UBApplication.cpp index 5225655b..c24ffbbb 100644 --- a/src/core/UBApplication.cpp +++ b/src/core/UBApplication.cpp @@ -34,7 +34,7 @@ #include #if defined(Q_OS_OSX) -#include + #include "OBCocoa.h" #endif #include "frameworks/UBPlatformUtils.h" @@ -91,27 +91,6 @@ bool bIsMinimized = false; QObject* UBApplication::staticMemoryCleaner = 0; -#if defined(Q_OS_OSX) -static OSStatus ub_appleEventProcessor(const AppleEvent *ae, AppleEvent *event, long handlerRefCon) -{ - Q_UNUSED(event); - OSType aeID = typeWildCard; - OSType aeClass = typeWildCard; - - AEGetAttributePtr(ae, keyEventClassAttr, typeType, 0, &aeClass, sizeof(aeClass), 0); - AEGetAttributePtr(ae, keyEventIDAttr, typeType, 0, &aeID, sizeof(aeID), 0); - - if (aeClass == kCoreEventClass && aeID == kAEReopenApplication) - { - // User clicked on Uniboard in the Dock - ((UBApplicationController*)handlerRefCon)->hideDesktop(); - return noErr; - } - - return eventNotHandledErr; -} -#endif - UBApplication::UBApplication(const QString &id, int &argc, char **argv) : QtSingleApplication(id, argc, argv) , mPreferencesController(NULL) @@ -368,11 +347,6 @@ int UBApplication::exec(const QString& pFileToImport) if (pFileToImport.length() > 0) UBApplication::applicationController->importFile(pFileToImport); -#if defined(Q_OS_OSX) - static AEEventHandlerUPP ub_proc_ae_handlerUPP = AEEventHandlerUPP(ub_appleEventProcessor); - AEInstallEventHandler(kCoreEventClass, kAEReopenApplication, ub_proc_ae_handlerUPP, SRefCon(UBApplication::applicationController), true); -#endif - if (UBSettings::settings()->appStartMode->get().toInt()) applicationController->showDesktop(); else @@ -390,14 +364,14 @@ void UBApplication::onScreenCountChanged(int newCount) mainWindow->actionMultiScreen->setEnabled(displayManager.numScreens() > 1); } -#ifdef Q_OS_OSX void UBApplication::showMinimized() { +#ifdef Q_OS_OSX mainWindow->hide(); bIsMinimized = true; +#endif } -#endif void UBApplication::startScript() { @@ -590,11 +564,7 @@ bool UBApplication::eventFilter(QObject *obj, QEvent *event) { QFileOpenEvent *fileToOpenEvent = static_cast(event); -#if defined(Q_OS_OSX) - ProcessSerialNumber psn; - GetCurrentProcess(&psn); - SetFrontProcess(&psn); -#endif + OBCocoa::setFrontProcess(); applicationController->importFile(fileToOpenEvent->file()); } diff --git a/src/core/UBApplication.h b/src/core/UBApplication.h index 2ab2c65a..ccb8f605 100644 --- a/src/core/UBApplication.h +++ b/src/core/UBApplication.h @@ -124,9 +124,9 @@ class UBApplication : public QtSingleApplication private slots: void closing(); -#ifdef Q_OS_OSX +//#ifdef Q_OS_OSX // for some reason this is not compiled if the ifdef is uncommented void showMinimized(); -#endif +//#endif void onScreenCountChanged(int newCount); private: @@ -136,10 +136,11 @@ class UBApplication : public QtSingleApplication bool mIsVerbose; QString checkLanguageAvailabilityForSankore(QString& language); protected: - -#if defined(Q_OS_OSX) && !defined(QT_MAC_USE_COCOA) +/* +#if defined(Q_OS_MAC) && !defined(QT_MAC_USE_COCOA) bool macEventFilter(EventHandlerCallRef caller, EventRef event); #endif + */ UBPreferencesController* mPreferencesController; QTranslator* mApplicationTranslator; diff --git a/src/core/UBApplicationController.cpp b/src/core/UBApplicationController.cpp index b4ae6a28..203aad85 100644 --- a/src/core/UBApplicationController.cpp +++ b/src/core/UBApplicationController.cpp @@ -67,9 +67,6 @@ #include "ui_mainWindow.h" -#ifdef Q_OS_OSX -#include -#endif #include "core/memcheck.h" diff --git a/src/core/core.pri b/src/core/core.pri index fedfde3f..92825ee3 100644 --- a/src/core/core.pri +++ b/src/core/core.pri @@ -36,3 +36,7 @@ SOURCES += src/core/main.cpp \ src/core/UBPersistenceWorker.cpp +macx { + HEADERS += src/core/OBCocoa.h + OBJECTIVE_SOURCES += src/core/OBCocoa.mm +} diff --git a/src/desktop/UBWindowCapture_mac.mm b/src/desktop/UBWindowCapture_mac.mm index 9e39b3b6..1de369fe 100644 --- a/src/desktop/UBWindowCapture_mac.mm +++ b/src/desktop/UBWindowCapture_mac.mm @@ -26,9 +26,10 @@ #include "UBWindowCapture.h" #include "UBDesktopAnnotationController.h" +#include #import -#import +#import UBWindowCapture::UBWindowCapture(UBDesktopAnnotationController *parent) diff --git a/src/frameworks/UBPlatformUtils_mac.mm b/src/frameworks/UBPlatformUtils_mac.mm index 9b73b850..70619205 100644 --- a/src/frameworks/UBPlatformUtils_mac.mm +++ b/src/frameworks/UBPlatformUtils_mac.mm @@ -33,6 +33,7 @@ #include #import +#import #import #import @@ -51,7 +52,7 @@ OSStatus emptySetSystemUIMode ( return noErr; } -void *originalSetSystemUIMode = 0; +//void *originalSetSystemUIMode = 0; void UBPlatformUtils::init() { @@ -62,7 +63,7 @@ void UBPlatformUtils::init() // http://developer.apple.com/mac/library/documentation/Carbon/Reference/Dock_Manager/Reference/reference.html#//apple_ref/c/func/SetSystemUIMode // - originalSetSystemUIMode = APEPatchCreate((const void *)SetSystemUIMode, (const void *)emptySetSystemUIMode); + //originalSetSystemUIMode = APEPatchCreate((const void *)SetSystemUIMode, (const void *)emptySetSystemUIMode); setDesktopMode(false); @@ -92,9 +93,9 @@ void UBPlatformUtils::init() void UBPlatformUtils::setDesktopMode(bool desktop) -{ +{ /* #ifndef OS_NEWER_THAN_OR_EQUAL_TO_1010 - OSStatus (*functor)(SystemUIMode, SystemUIOptions) = (OSStatus (*)(SystemUIMode, SystemUIOptions))originalSetSystemUIMode; + //OSStatus (*functor)(SystemUIMode, SystemUIOptions) = (OSStatus (*)(SystemUIMode, SystemUIOptions))originalSetSystemUIMode; if (desktop) { @@ -105,6 +106,7 @@ void UBPlatformUtils::setDesktopMode(bool desktop) functor(kUIModeAllHidden, 0); } #endif +*/ } @@ -533,7 +535,7 @@ void UBPlatformUtils::SetMacLocaleByIdentifier(const QString& id) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - const char * strName = id.toAscii().data(); + const char * strName = id.toLatin1().data(); CFStringRef iName = CFStringCreateWithCString(NULL, strName, kCFStringEncodingMacRoman ); diff --git a/src/gui/UBFloatingPalette.cpp b/src/gui/UBFloatingPalette.cpp index 749320c2..0aa19233 100644 --- a/src/gui/UBFloatingPalette.cpp +++ b/src/gui/UBFloatingPalette.cpp @@ -60,7 +60,7 @@ UBFloatingPalette::UBFloatingPalette(Qt::Corner position, QWidget *parent) #endif #ifdef Q_OS_OSX setAttribute(Qt::WA_MacAlwaysShowToolWindow); - setAttribute(Qt::WA_MacNonActivatingToolWindow); + //setAttribute(Qt::WA_MacNonActivatingToolWindow); // no longer exists setAttribute(Qt::WA_MacNoShadow); #endif } diff --git a/src/gui/UBKeyboardPalette_mac.cpp b/src/gui/UBKeyboardPalette_mac.mm similarity index 97% rename from src/gui/UBKeyboardPalette_mac.cpp rename to src/gui/UBKeyboardPalette_mac.mm index 401242bb..8fa984fd 100644 --- a/src/gui/UBKeyboardPalette_mac.cpp +++ b/src/gui/UBKeyboardPalette_mac.mm @@ -30,7 +30,8 @@ #include #include #include -#include + +#import #include #include @@ -74,6 +75,8 @@ void UBKeyboardPalette::createCtrlButtons() void UBKeyboardPalette::checkLayout() { + /* + * REMOVED FOR NOW -- check if is still needed in 10.9/10.10 TISInputSourceRef selectedLocale = TISCopyCurrentKeyboardInputSource(); CFStringRef sr = (CFStringRef) TISGetInputSourceProperty(selectedLocale, @@ -96,6 +99,7 @@ void UBKeyboardPalette::checkLayout() } } } + */ } void UBKeyboardPalette::onActivated(bool) diff --git a/src/gui/UBMagnifer.cpp b/src/gui/UBMagnifer.cpp index b6ce41cf..0d492655 100644 --- a/src/gui/UBMagnifer.cpp +++ b/src/gui/UBMagnifer.cpp @@ -85,7 +85,7 @@ UBMagnifier::UBMagnifier(QWidget *parent, bool isInteractive) #endif #ifdef Q_OS_OSX setAttribute(Qt::WA_MacAlwaysShowToolWindow); - setAttribute(Qt::WA_MacNonActivatingToolWindow); + //setAttribute(Qt::WA_MacNonActivatingToolWindow); setAttribute(Qt::WA_MacNoShadow); #endif } diff --git a/src/gui/UBRubberBand.cpp b/src/gui/UBRubberBand.cpp index a6c36e98..8fdd3117 100644 --- a/src/gui/UBRubberBand.cpp +++ b/src/gui/UBRubberBand.cpp @@ -31,15 +31,11 @@ #include #include -#ifdef Q_OS_OSX -#include -#endif - -#include "core/UBApplication.h" -#include "board/UBBoardController.h" #include "board/UBBoardView.h" #include "core/memcheck.h" +#include "core/UBApplication.h" +#include "board/UBBoardController.h" UBRubberBand::UBRubberBand(Shape s, QWidget * p) : QRubberBand(s, p) @@ -53,7 +49,7 @@ UBRubberBand::UBRubberBand(Shape s, QWidget * p) #ifdef Q_OS_WIN customStyle = new QWindowsXPStyle(); #elif defined(Q_OS_OSX) - customStyle = new QMacStyle(); + customStyle = QStyleFactory::create("macintosh"); #elif defined(Q_OS_LINUX) customStyle = QStyleFactory::create("oxygen"); #endif diff --git a/src/gui/gui.pri b/src/gui/gui.pri index dd1fd260..38f5f654 100644 --- a/src/gui/gui.pri +++ b/src/gui/gui.pri @@ -85,7 +85,8 @@ SOURCES += src/gui/UBThumbnailView.cpp \ src/gui/UBOpenSankoreImporterWidget.cpp \ src/gui/UBStartupHintsPalette.cpp win32:SOURCES += src/gui/UBKeyboardPalette_win.cpp -macx:SOURCES += src/gui/UBKeyboardPalette_mac.cpp +macx:OBJECTIVE_SOURCES += src/gui/UBKeyboardPalette_mac.mm linux-g++:SOURCES += src/gui/UBKeyboardPalette_linux.cpp linux-g++-32:SOURCES += src/gui/UBKeyboardPalette_linux.cpp linux-g++-64:SOURCES += src/gui/UBKeyboardPalette_linux.cpp + diff --git a/src/podcast/UBPodcastController.cpp b/src/podcast/UBPodcastController.cpp index 12641434..45a5e435 100644 --- a/src/podcast/UBPodcastController.cpp +++ b/src/podcast/UBPodcastController.cpp @@ -59,9 +59,9 @@ #ifdef Q_OS_WIN #include "windowsmedia/UBWindowsMediaVideoEncoder.h" #include "windowsmedia/UBWaveRecorder.h" -#elif defined(Q_OS_OSX) - #include "quicktime/UBQuickTimeVideoEncoder.h" - #include "quicktime/UBAudioQueueRecorder.h" +//#elif defined(Q_OS_OSX) +// #include "quicktime/UBQuickTimeVideoEncoder.h" +// #include "quicktime/UBAudioQueueRecorder.h" #endif #include "core/memcheck.h" @@ -305,8 +305,8 @@ void UBPodcastController::start() #ifdef Q_OS_WIN mVideoEncoder = new UBWindowsMediaVideoEncoder(this); //deleted on stop -#elif defined(Q_OS_OSX) - mVideoEncoder = new UBQuickTimeVideoEncoder(this); //deleted on stop +//#elif defined(Q_OS_OSX) +// mVideoEncoder = new UBQuickTimeVideoEncoder(this); //deleted on stop #endif if (mVideoEncoder) @@ -795,8 +795,8 @@ QStringList UBPodcastController::audioRecordingDevices() #ifdef Q_OS_WIN devices = UBWaveRecorder::waveInDevices(); -#elif defined(Q_OS_OSX) - devices = UBAudioQueueRecorder::waveInDevices(); +//#elif defined(Q_OS_OSX) +// devices = UBAudioQueueRecorder::waveInDevices(); #endif return devices; diff --git a/src/podcast/podcast.pri b/src/podcast/podcast.pri index 88943d78..d6d5aa94 100644 --- a/src/podcast/podcast.pri +++ b/src/podcast/podcast.pri @@ -22,13 +22,13 @@ win32 { src/podcast/windowsmedia/UBWaveRecorder.h } -macx { +#macx { - SOURCES += src/podcast/quicktime/UBQuickTimeVideoEncoder.cpp \ - src/podcast/quicktime/UBQuickTimeFile.cpp \ - src/podcast/quicktime/UBAudioQueueRecorder.cpp +# SOURCES += src/podcast/quicktime/UBQuickTimeVideoEncoder.cpp \ +# src/podcast/quicktime/UBQuickTimeFile.cpp \ +# src/podcast/quicktime/UBAudioQueueRecorder.cpp - HEADERS += src/podcast/quicktime/UBQuickTimeVideoEncoder.h \ - src/podcast/quicktime/UBQuickTimeFile.h \ - src/podcast/quicktime/UBAudioQueueRecorder.h -} \ No newline at end of file +# HEADERS += src/podcast/quicktime/UBQuickTimeVideoEncoder.h \ +# src/podcast/quicktime/UBQuickTimeFile.h \ +# src/podcast/quicktime/UBAudioQueueRecorder.h +#} From e1014a013840bfeb14b5ddc2ec29ebb7cc677885 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Tue, 17 Nov 2015 12:07:52 +0100 Subject: [PATCH 006/243] re-enabled keyboard switching on Mac OS // functionality is still spotty.. --- src/frameworks/UBPlatformUtils_mac.mm | 5 ++++- src/gui/UBKeyboardPalette_mac.mm | 6 +++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/frameworks/UBPlatformUtils_mac.mm b/src/frameworks/UBPlatformUtils_mac.mm index 70619205..d4685fe5 100644 --- a/src/frameworks/UBPlatformUtils_mac.mm +++ b/src/frameworks/UBPlatformUtils_mac.mm @@ -537,11 +537,14 @@ void UBPlatformUtils::SetMacLocaleByIdentifier(const QString& id) const char * strName = id.toLatin1().data(); - CFStringRef iName = CFStringCreateWithCString(NULL, strName, kCFStringEncodingMacRoman ); + CFStringRef iName = CFStringCreateWithCString(NULL, strName, kCFStringEncodingISOLatin1 ); + CFStringRef keys[] = { kTISPropertyInputSourceCategory, kTISPropertyInputSourceID }; CFStringRef values[] = { kTISCategoryKeyboardInputSource, iName }; CFDictionaryRef dict = CFDictionaryCreate(NULL, (const void **)keys, (const void **)values, 2, NULL, NULL); + + // get list of current enabled keyboard layouts. dict filters the list CFArrayRef kbds = TISCreateInputSourceList(dict, true); if (kbds!=NULL) { diff --git a/src/gui/UBKeyboardPalette_mac.mm b/src/gui/UBKeyboardPalette_mac.mm index 8fa984fd..f5d12959 100644 --- a/src/gui/UBKeyboardPalette_mac.mm +++ b/src/gui/UBKeyboardPalette_mac.mm @@ -32,6 +32,7 @@ #include #import +#import #include #include @@ -75,8 +76,7 @@ void UBKeyboardPalette::createCtrlButtons() void UBKeyboardPalette::checkLayout() { - /* - * REMOVED FOR NOW -- check if is still needed in 10.9/10.10 + TISInputSourceRef selectedLocale = TISCopyCurrentKeyboardInputSource(); CFStringRef sr = (CFStringRef) TISGetInputSourceProperty(selectedLocale, @@ -99,7 +99,7 @@ void UBKeyboardPalette::checkLayout() } } } - */ + } void UBKeyboardPalette::onActivated(bool) From b219655ac299609e02658109b0de96422016134b Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Tue, 17 Nov 2015 13:50:48 +0100 Subject: [PATCH 007/243] removed redundant OBCocoa files / namespace; moved functions to UBPlatformUtils, which serves the same purpose --- src/core/OBCocoa.h | 11 ----------- src/core/OBCocoa.mm | 24 ------------------------ src/core/UBApplication.cpp | 6 +----- src/core/core.pri | 6 ------ src/frameworks/UBPlatformUtils.h | 1 + src/frameworks/UBPlatformUtils_linux.cpp | 5 +++++ src/frameworks/UBPlatformUtils_mac.mm | 14 ++++++++++++++ src/frameworks/UBPlatformUtils_win.cpp | 4 ++++ 8 files changed, 25 insertions(+), 46 deletions(-) delete mode 100644 src/core/OBCocoa.h delete mode 100644 src/core/OBCocoa.mm diff --git a/src/core/OBCocoa.h b/src/core/OBCocoa.h deleted file mode 100644 index f646d434..00000000 --- a/src/core/OBCocoa.h +++ /dev/null @@ -1,11 +0,0 @@ -/* - OBCocoa.h - - Header file permitting access to Mac OSX / Cocoa specific functions - -*/ - - -namespace OBCocoa { - void setFrontProcess(); -} diff --git a/src/core/OBCocoa.mm b/src/core/OBCocoa.mm deleted file mode 100644 index 53c01e2f..00000000 --- a/src/core/OBCocoa.mm +++ /dev/null @@ -1,24 +0,0 @@ -#include "OBCocoa.h" -#include "UBApplicationController.h" - -#include -#import - -namespace OBCocoa { - -/** - * @brief Activate the current application - */ -void setFrontProcess() -{ - NSRunningApplication* app = [NSRunningApplication currentApplication]; - - // activate the application, forcing focus on it - [app activateWithOptions: NSApplicationActivateIgnoringOtherApps]; - - // other option:NSApplicationActivateAllWindows. This won't steal focus from another app, e.g - // if the user is doing something else while waiting for OpenBoard to load -} - - -} // namespace OBCocoa diff --git a/src/core/UBApplication.cpp b/src/core/UBApplication.cpp index c24ffbbb..24558e59 100644 --- a/src/core/UBApplication.cpp +++ b/src/core/UBApplication.cpp @@ -33,10 +33,6 @@ #include #include -#if defined(Q_OS_OSX) - #include "OBCocoa.h" -#endif - #include "frameworks/UBPlatformUtils.h" #include "frameworks/UBFileSystemUtils.h" #include "frameworks/UBStringUtils.h" @@ -564,7 +560,7 @@ bool UBApplication::eventFilter(QObject *obj, QEvent *event) { QFileOpenEvent *fileToOpenEvent = static_cast(event); - OBCocoa::setFrontProcess(); + UBPlatformUtils::setFrontProcess(); applicationController->importFile(fileToOpenEvent->file()); } diff --git a/src/core/core.pri b/src/core/core.pri index 92825ee3..a60978ad 100644 --- a/src/core/core.pri +++ b/src/core/core.pri @@ -34,9 +34,3 @@ SOURCES += src/core/main.cpp \ src/core/UBOpenSankoreImporter.cpp \ src/core/UBTextTools.cpp \ src/core/UBPersistenceWorker.cpp - - -macx { - HEADERS += src/core/OBCocoa.h - OBJECTIVE_SOURCES += src/core/OBCocoa.mm -} diff --git a/src/frameworks/UBPlatformUtils.h b/src/frameworks/UBPlatformUtils.h index c7b99bc1..e0b3f4ff 100644 --- a/src/frameworks/UBPlatformUtils.h +++ b/src/frameworks/UBPlatformUtils.h @@ -203,6 +203,7 @@ public: static UBKeyboardLocale** getKeyboardLayouts(int& nCount); static QString urlFromClipboard(); static QStringList availableTranslations(); + static void setFrontProcess(); #ifdef Q_OS_OSX static void SetMacLocaleByIdentifier(const QString& id); diff --git a/src/frameworks/UBPlatformUtils_linux.cpp b/src/frameworks/UBPlatformUtils_linux.cpp index 73e901a0..17011217 100644 --- a/src/frameworks/UBPlatformUtils_linux.cpp +++ b/src/frameworks/UBPlatformUtils_linux.cpp @@ -429,3 +429,8 @@ QString UBPlatformUtils::urlFromClipboard() return qsRet; } + + +void UBPlatformUtils::setFrontProcess() +{ +} diff --git a/src/frameworks/UBPlatformUtils_mac.mm b/src/frameworks/UBPlatformUtils_mac.mm index d4685fe5..b2623080 100644 --- a/src/frameworks/UBPlatformUtils_mac.mm +++ b/src/frameworks/UBPlatformUtils_mac.mm @@ -557,3 +557,17 @@ void UBPlatformUtils::SetMacLocaleByIdentifier(const QString& id) } [pool drain]; } + +/** + * @brief Activate the current application + */ +void UBPlatformUtils::setFrontProcess() +{ + NSRunningApplication* app = [NSRunningApplication currentApplication]; + + // activate the application, forcing focus on it + [app activateWithOptions: NSApplicationActivateIgnoringOtherApps]; + + // other option:NSApplicationActivateAllWindows. This won't steal focus from another app, e.g + // if the user is doing something else while waiting for OpenBoard to load +} diff --git a/src/frameworks/UBPlatformUtils_win.cpp b/src/frameworks/UBPlatformUtils_win.cpp index 1d46586a..ed698a39 100644 --- a/src/frameworks/UBPlatformUtils_win.cpp +++ b/src/frameworks/UBPlatformUtils_win.cpp @@ -424,3 +424,7 @@ QString UBPlatformUtils::urlFromClipboard() // Not implemented yet return qsRet; } + +void UBPlatformUtils::setFrontProcess() +{ +} From 50772c52a82c91cb03b534dc493d0fc77dc4ed1c Mon Sep 17 00:00:00 2001 From: agriche Date: Tue, 17 Nov 2015 13:58:11 +0100 Subject: [PATCH 008/243] - Update all lastest release libraries. --- changes_porting_qt5.txt | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/changes_porting_qt5.txt b/changes_porting_qt5.txt index 0819c3f7..ed187b68 100644 --- a/changes_porting_qt5.txt +++ b/changes_porting_qt5.txt @@ -864,7 +864,45 @@ xpdf.pro - replace CONFIG += staticlib release by CONFIG += staticlib debug_and_release. +OpenBoard.pro +-------------- + +- insert the qtlockedfile config include($$THIRD_PARTY_PATH/trolltech/singleapplication/qtlockedfile.pri) + +freetype.pro +------------ + +- replace the old version 2.4.6 by the last release 2.6 => FREETYPE_DIR_WITH_VERSION = freetype-2.6.1 + + +Openssl 1.0.2 library +---------------------- + +- configure & build & install the static version of the library Openssl 1.0.2. with msvc 2010 compiler. + +libeay32MT.lib is compiled with default /MT run-time option [Multithreaded static] + + +quazip 0.7.1 library +-------------------- + +- update the last update release quazip 0.7.1 +=> quazip.pro et quazip.pri + +xpdf 3.04 library +---------------- + +- Update the last release xpdf 3.04 lib. + + +zlib 1.2.8 library +------------------ +- Build the last static version of the library zlib 1.2.8 with msvc 2010 compiler. +=> Launch cl(command line msvc 2010). +=> Go the main folder path/zlib 1.2.8. +=> Enter nmake -f win32/Makefile.msc. +=> Retrieve the include headers files (zconf.h,zlib.h) and the static library zlib.lib. From 056086fa97a367c0404bd71345f6369406c5d770 Mon Sep 17 00:00:00 2001 From: agriche Date: Tue, 17 Nov 2015 14:00:50 +0100 Subject: [PATCH 009/243] - Update all latest release libraries. --- changes_porting_qt5.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/changes_porting_qt5.txt b/changes_porting_qt5.txt index ed187b68..ead838e0 100644 --- a/changes_porting_qt5.txt +++ b/changes_porting_qt5.txt @@ -9,9 +9,6 @@ - - - QtSingleApplication replacement for Qt5 ---------------------------------------- From e7c986b402f7ae3ecab53737a27c2b0802f90493 Mon Sep 17 00:00:00 2001 From: agriche Date: Tue, 17 Nov 2015 14:56:59 +0100 Subject: [PATCH 010/243] - Update all latest release libraries(Quazip 0.7.1;xpdf 3.04;zlib 1.2.8) --- changes_porting_qt5.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/changes_porting_qt5.txt b/changes_porting_qt5.txt index ead838e0..afaf2f03 100644 --- a/changes_porting_qt5.txt +++ b/changes_porting_qt5.txt @@ -9,6 +9,9 @@ + + + QtSingleApplication replacement for Qt5 ---------------------------------------- @@ -872,6 +875,7 @@ freetype.pro - replace the old version 2.4.6 by the last release 2.6 => FREETYPE_DIR_WITH_VERSION = freetype-2.6.1 + Openssl 1.0.2 library ---------------------- @@ -901,5 +905,5 @@ zlib 1.2.8 library => Launch cl(command line msvc 2010). => Go the main folder path/zlib 1.2.8. => Enter nmake -f win32/Makefile.msc. -=> Retrieve the include headers files (zconf.h,zlib.h) and the static library zlib.lib. +=> Retrieve and move the include headers files (zconf.h,zlib.h) and the static library zlib.lib. From 40faa8ffcbae6b9b891aee663362cc30060f476c Mon Sep 17 00:00:00 2001 From: agriche Date: Wed, 18 Nov 2015 08:54:08 +0100 Subject: [PATCH 011/243] - Replace some headers files. --- changes_porting_qt5.txt | 63 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/changes_porting_qt5.txt b/changes_porting_qt5.txt index afaf2f03..23e91ab0 100644 --- a/changes_porting_qt5.txt +++ b/changes_porting_qt5.txt @@ -874,12 +874,9 @@ freetype.pro - replace the old version 2.4.6 by the last release 2.6 => FREETYPE_DIR_WITH_VERSION = freetype-2.6.1 - - Openssl 1.0.2 library ---------------------- - - configure & build & install the static version of the library Openssl 1.0.2. with msvc 2010 compiler. libeay32MT.lib is compiled with default /MT run-time option [Multithreaded static] @@ -907,3 +904,63 @@ zlib 1.2.8 library => Enter nmake -f win32/Makefile.msc. => Retrieve and move the include headers files (zconf.h,zlib.h) and the static library zlib.lib. + +UBWindowCaptureDelegate_win.cpp +------------------------------- +- replace mCapturedPixmap = QPixmap::grabWindow(mCurrentWindow); by mCapturedPixmap = QPixmap::grabWindow((WId)mCurrentWindow); + + +UBGraphicsCurtainItemDelegate.cpp +------------------------------------ + +- replace //#include by #include . + +UBToolsManager.h +------------------ + +- replace //#include by #include . + +UBGraphicsCompass.h +------------------- + +- replace //#include by #include . + +UBGraphicsCurtainItem.h +------------------------ + +- replace //#include by #include . + +UBGraphicsCurtainItemDelegate.h +------------------------------- + +- replace //#include by #include . + + +UBGraphicsRuler.h +---------------- + +- replace //#include by #include . + + +UBGraphicsTriangle.h +-------------------- +- replace //#include by #include . + + +UBGraphicsCurtainItem.cpp +-------------------------- + +- Replace //#include by #include . + + + +*************************** +COMPILATION IN DEBUG MODE : +*************************** + +The Openboard application crashes after a checkUpdate ("http://get.openboard.org/update.json") +=> the url do not exists. + + +UBGraphicsDelegateFrame.cpp +------------------------------ \ No newline at end of file From 2bf6a6d6e0a8092ef70fa16073e2f90e15184656 Mon Sep 17 00:00:00 2001 From: agriche Date: Wed, 18 Nov 2015 10:00:47 +0100 Subject: [PATCH 012/243] - Increase the dimension of the video widget. --- src/domain/UBGraphicsMediaItem.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/domain/UBGraphicsMediaItem.cpp b/src/domain/UBGraphicsMediaItem.cpp index e4ea11a8..8ae95aec 100644 --- a/src/domain/UBGraphicsMediaItem.cpp +++ b/src/domain/UBGraphicsMediaItem.cpp @@ -76,7 +76,6 @@ UBGraphicsMediaItem::UBGraphicsMediaItem(const QUrl& pMediaFileUrl, QGraphicsIte //mMediaObject->setTickInterval(50); mMediaObject->setPosition(50); - //mVideoWidget = new Phonon::VideoWidget(); // owned and destructed by the scene ... mVideoWidget = new QVideoWidget(); // owned and destructed by the scene ... @@ -87,9 +86,15 @@ UBGraphicsMediaItem::UBGraphicsMediaItem(const QUrl& pMediaFileUrl, QGraphicsIte mVideoWidget->resize(320,240); } - mVideoWidget->setMinimumSize(140,26); + //mVideoWidget->setMinimumSize(140,26); + mVideoWidget->setMinimumSize(320,240); haveLinkedImage = true; + + + // DEBUGGING VIDEO + //***************** + qDebug() << "UBGraphicsMediaItem.cpp:" << mVideoWidget << "setMinimumSize(140,26)" ; } else if (mediaPath.toLower().contains("audios")) { From 1ddeaa0d619745190cf6ca315d5e5a233562c60c Mon Sep 17 00:00:00 2001 From: agriche Date: Thu, 19 Nov 2015 14:05:11 +0100 Subject: [PATCH 013/243] - In DEBUG mode,the Openboard application crashes after a checkUpdate ("http://get.openboard.org/update.json"). => the url do not exists. --- src/core/UBApplicationController.cpp | 109 +++++++++++++++++---------- 1 file changed, 71 insertions(+), 38 deletions(-) diff --git a/src/core/UBApplicationController.cpp b/src/core/UBApplicationController.cpp index 203aad85..6bfcbdef 100644 --- a/src/core/UBApplicationController.cpp +++ b/src/core/UBApplicationController.cpp @@ -22,9 +22,7 @@ * along with OpenBoard. If not, see . */ -#include -#include -#include + #include "UBApplicationController.h" @@ -67,6 +65,9 @@ #include "ui_mainWindow.h" +#ifdef Q_WS_MAC +#include +#endif #include "core/memcheck.h" @@ -85,6 +86,7 @@ UBApplicationController::UBApplicationController(UBBoardView *pControlView, , mAutomaticCheckForUpdates(false) , mCheckingForUpdates(false) , mIsShowingDesktop(false) + , mHttp(0) { mDisplayManager = new UBDisplayManager(this); @@ -119,7 +121,7 @@ UBApplicationController::UBApplicationController(UBBoardView *pControlView, QTimer::singleShot (1000, this, SLOT (checkAtLaunch())); -#ifdef Q_OS_LINUX +#ifdef Q_WS_X11 mMainWindow->setStyleSheet("QToolButton { font-size: 11px}"); #endif @@ -136,6 +138,8 @@ UBApplicationController::~UBApplicationController() delete mBlackScene; delete mMirror; + if (mHttp) delete mHttp; + delete(mOpenSankoreImporter); mOpenSankoreImporter = NULL; } @@ -475,55 +479,84 @@ void UBApplicationController::showDesktop(bool dontSwitchFrontProcess) UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); } + void UBApplicationController::checkUpdate(QString urlString) { - //connect(networkAccessManager, &QNetworkAccessManager::finished, - // this, &UBApplicationController::updateRequestFinished); - connect(networkAccessManager, SIGNAL(finished(QNetworkReply*)), - this, SLOT(updateRequestFinished(QNetworkReply*))); - networkAccessManager->get(QNetworkRequest(QUrl(urlString))); + #if defined(QT_NO_DEBUG) + /* + if(mHttp) + mHttp->deleteLater(); + QUrl url(urlString); + mHttp = new QHttpPart(url.host()); + connect(mHttp, SIGNAL(requestFinished(int,bool)), this, SLOT(updateRequestFinished(int,bool))); + connect(mHttp, SIGNAL(responseHeaderReceived(QHttpResponseHeader)), this, SLOT(updateHeaderReceived(QHttpResponseHeader))); -} + mHttp->get(url.path()); + */ + if(mHttpreply) + mHttpreply->deleteLater(); + QUrl url(urlString); + mHttpreply = qnam.get(QNetworkRequest(url)); + connect(mHttpreply, SIGNAL(requestFinished(int,bool)), this, SLOT(updateRequestFinished(int,bool))); + connect(mHttpreply, SIGNAL(responseHeaderReceived(QHttpResponseHeader)), this, SLOT(updateHeaderReceived(QHttpResponseHeader))); + // mHttpreply->setUrl(url.path()); + //mHttp->get(url.path()); +#else -void UBApplicationController::updateRequestFinished(QNetworkReply * reply) -{ - if (reply->error()) { - qWarning() << "HTTP Error"; - return; - } - // Check if we are being redirected. If so, call checkUpdate again - QVariant redirect_target = reply->attribute(QNetworkRequest::RedirectionTargetAttribute); - - if (!redirect_target.isNull()) { - // The returned URL might be relative. resolved() creates an absolute url from it - QUrl redirect_url(reply->url().resolved(redirect_target.toUrl())); +#endif +} - checkUpdate(redirect_url.toString()); - return; +/* +void UBApplicationController::updateHeaderReceived(QHttpResponseHeader header) +{ + if(header.statusCode() == 302 && header.hasKey("Location")){ + mHttp->close(); + checkUpdate(header.value("Location")); } +} +*/ +void UBApplicationController::updateHeaderReceived(QNetworkRequest header ) +{ + //if(header.attribute(QNetworkRequest::HttpStatusCodeAttribute) == 302 && header.header(QNetworkRequest::LocationHeader)){ + // mHttp->close(); + mHttpreply->close(); + //checkUpdate(header.value("Location")); + // } +} - // No error and no redirect => we read the whole response - - QString responseString = QString(reply->readAll()); - qDebug() << responseString; - - if (!responseString.isEmpty() && - responseString.contains("version") && - responseString.contains("url")) { - - reply->close(); - reply->deleteLater(); - - downloadJsonFinished(responseString); - } +void UBApplicationController::updateRequestFinished(int id, bool error) +{ + if (error){ + qWarning() << "http command id" << id << "return an error"; + } + else{ + /* QString responseString = QString(mHttp->readAll()); + qDebug() << responseString; + if (!responseString.isEmpty() && responseString.contains("version") && responseString.contains("url")){ + mHttp->close(); + mHttp->deleteLater(); + mHttp = 0; + downloadJsonFinished(responseString); + } + */ + QString responseString = QString(mHttpreply->readAll()); + qDebug() << responseString; + if (!responseString.isEmpty() && responseString.contains("version") && responseString.contains("url")){ + mHttpreply->close(); + mHttpreply->deleteLater(); + mHttpreply = 0; + downloadJsonFinished(responseString); + } + } } + void UBApplicationController::downloadJsonFinished(QString currentJson) { QScriptValue scriptValue; From f12032f54979811a019c4237af1561f05cef84d2 Mon Sep 17 00:00:00 2001 From: agriche Date: Thu, 19 Nov 2015 14:12:26 +0100 Subject: [PATCH 014/243] - Replace apps.id = "uniboardTool://uniboard.mnemis.com/apps" by "openboardtool://apps". --- src/tools/UBToolsManager.cpp | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/tools/UBToolsManager.cpp b/src/tools/UBToolsManager.cpp index dfb332b8..d9c756f2 100644 --- a/src/tools/UBToolsManager.cpp +++ b/src/tools/UBToolsManager.cpp @@ -49,50 +49,63 @@ void UBToolsManager::destroy() UBToolsManager::UBToolsManager(QObject *parent) : QObject(parent) { + //mask.id = "uniboardTool://uniboard.mnemis.com/mask"; - mask.id = "uniboardTool://uniboard.mnemis.com/mask"; + mask.id = "openboardtool://openboard/mask"; mask.icon = QPixmap(":/images/toolPalette/maskTool.png"); mask.label = tr("Mask"); mask.version = "1.0"; mToolsIcon.insert(mask.id, ":/images/toolPalette/maskTool.png"); mDescriptors << mask; - ruler.id = "uniboardTool://uniboard.mnemis.com/ruler"; + //ruler.id = "uniboardTool://uniboard.mnemis.com/ruler"; + + ruler.id = "openboardtool://ruler"; ruler.icon = QPixmap(":/images/toolPalette/rulerTool.png"); ruler.label = tr("Ruler"); ruler.version = "1.0"; mToolsIcon.insert(ruler.id, ":/images/toolPalette/rulerTool.png"); mDescriptors << ruler; - compass.id = "uniboardTool://uniboard.mnemis.com/compass"; + //compass.id = "uniboardTool://uniboard.mnemis.com/compass"; + + compass.id = "openboardtool://compass"; compass.icon = QPixmap(":/images/toolPalette/compassTool.png"); compass.label = tr("Compass"); compass.version = "1.0"; mToolsIcon.insert(compass.id, ":/images/toolPalette/compassTool.png"); mDescriptors << compass; - protractor.id = "uniboardTool://uniboard.mnemis.com/protractor"; + //protractor.id = "uniboardTool://uniboard.mnemis.com/protractor"; + + protractor.id = "openboardtool://protractor"; protractor.icon = QPixmap(":/images/toolPalette/protractorTool.png"); protractor.label = tr("Protractor"); protractor.version = "1.0"; mToolsIcon.insert(protractor.id,":/images/toolPalette/protractorTool.png"); mDescriptors << protractor; - triangle.id = "uniboardTool://uniboard.mnemis.com/triangle"; + //triangle.id = "uniboardTool://uniboard.mnemis.com/triangle"; + + triangle.id = "openboardtool://triangle"; triangle.icon = QPixmap(":/images/toolPalette/triangleTool.png"); triangle.label = tr("Triangle"); triangle.version = "1.0"; mToolsIcon.insert(triangle.id,":/images/toolPalette/triangleTool.png"); mDescriptors << triangle; - magnifier.id = "uniboardTool://uniboard.mnemis.com/magnifier"; + //magnifier.id = "uniboardTool://uniboard.mnemis.com/magnifier"; + + magnifier.id = "openboardtool://magnifier"; magnifier.icon = QPixmap(":/images/toolPalette/magnifierTool.png"); magnifier.label = tr("Magnifier"); magnifier.version = "1.0"; mToolsIcon.insert(magnifier.id,":/images/toolPalette/magnifierTool.png"); mDescriptors << magnifier; - cache.id = "uniboardTool://uniboard.mnemis.com/cache"; + //cache.id = "uniboardTool://uniboard.mnemis.com/cache"; + + cache.id = "openboardtool://cache"; cache.icon = QPixmap(":/images/toolPalette/cacheTool.png"); cache.label = tr("Cache"); cache.version = "1.0"; From f7df53b0630c019e2d497cb13da4a4d0d33320c9 Mon Sep 17 00:00:00 2001 From: agriche Date: Thu, 19 Nov 2015 14:18:36 +0100 Subject: [PATCH 015/243] - Replace UniboardTool enum field by OpenboardTool . --- src/core/UB.h | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/core/UB.h b/src/core/UB.h index be8f53a0..f2dd6685 100644 --- a/src/core/UB.h +++ b/src/core/UB.h @@ -28,8 +28,9 @@ #ifndef UB_H_ #define UB_H_ -#include -#include +//#include +#include + #define UB_MAX_ZOOM 9 @@ -45,7 +46,8 @@ struct UBMimeType Audio, Flash, PDF, - UniboardTool, + //UniboardTool, + OpenboardTool, Group, UNKNOWN }; @@ -144,25 +146,25 @@ struct UBGraphicsItemType { enum Enum { - PolygonItemType = QGraphicsItem::UserType + 1, //65537 + PolygonItemType = QGraphicsItem::UserType + 1, PixmapItemType, SvgItemType, - DelegateButtonType, //65540 + DelegateButtonType, MediaItemType, PDFItemType, TextItemType, CurtainItemType, - RulerItemType, //65545 + RulerItemType, CompassItemType, ProtractorItemType, StrokeItemType, TriangleItemType, - MagnifierItemType, //65550 + MagnifierItemType, cacheItemType, groupContainerType, ToolWidgetItemType, GraphicsWidgetItemType, - UserTypesCount, //65555 + UserTypesCount, SelectionFrameType// this line must be the last line in this enum because it is types counter. }; }; From 6a941e256c6d6fe5d4497ab0d4935eb3d4373a34 Mon Sep 17 00:00:00 2001 From: agriche Date: Thu, 19 Nov 2015 14:41:59 +0100 Subject: [PATCH 016/243] - Replace #include by #include . - Replace #include by #include . - Replace uniboardTool by openboardTool. - Replace UBMimeType::UniboardTool by UBMimeType::OpenboardTool. --- src/board/UBBoardController.cpp | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/board/UBBoardController.cpp b/src/board/UBBoardController.cpp index ccf9b692..ceb85256 100644 --- a/src/board/UBBoardController.cpp +++ b/src/board/UBBoardController.cpp @@ -27,8 +27,11 @@ #include "UBBoardController.h" -#include -#include +//#include +#include + +//#include +#include #include "frameworks/UBFileSystemUtils.h" #include "frameworks/UBPlatformUtils.h" @@ -1019,9 +1022,12 @@ void UBBoardController::downloadURL(const QUrl& url, QString contentSourceUrl, c if (isBackground) oldBackgroundObject = mActiveScene->backgroundObject(); - if(sUrl.startsWith("uniboardTool://")) + //if(sUrl.startsWith("uniboardTool://")) + //if(sUrl.startsWith("openboardTool://",Qt::CaseInsensitive)) + if(sUrl.startsWith("openboardtool://")) + { - downloadFinished(true, url, QUrl(), "application/vnd.mnemis-uniboard-tool", QByteArray(), pPos, pSize, isBackground); + downloadFinished(true, url, QUrl(), "application/openboard-tool", QByteArray(), pPos, pSize, isBackground); } else if (sUrl.startsWith("file://") || sUrl.startsWith("/")) { @@ -1118,7 +1124,8 @@ UBItem *UBBoardController::downloadFinished(bool pSuccess, QUrl sourceUrl, QUrl mActiveScene->deselectAllItems(); - if (!sourceUrl.toString().startsWith("file://") && !sourceUrl.toString().startsWith("uniboardTool://")) + //if (!sourceUrl.toString().startsWith("file://") && !sourceUrl.toString().startsWith("uniboardTool://")) + if (!sourceUrl.toString().startsWith("file://") && !sourceUrl.toString().startsWith("openboardtool://")) showMessage(tr("Download finished")); if (UBMimeType::RasterImage == itemMimeType) @@ -1398,9 +1405,10 @@ UBItem *UBBoardController::downloadFinished(bool pSuccess, QUrl sourceUrl, QUrl selectedDocument()->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); } } - else if (UBMimeType::UniboardTool == itemMimeType) + //else if (UBMimeType::UniboardTool == itemMimeType) + else if (UBMimeType::OpenboardTool == itemMimeType) { - qDebug() << "accepting mime type" << mimeType << "as Uniboard Tool"; + qDebug() << "accepting mime type" << mimeType << "OpenBoard Tool"; if (sourceUrl.toString() == UBToolsManager::manager()->compass.id) { From 533c4a577f179b700bf4e11b675dfe6586c570da Mon Sep 17 00:00:00 2001 From: agriche Date: Thu, 19 Nov 2015 14:44:55 +0100 Subject: [PATCH 017/243] - Replace UniboardTool case by OpenboardTool. --- src/frameworks/UBFileSystemUtils.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/frameworks/UBFileSystemUtils.cpp b/src/frameworks/UBFileSystemUtils.cpp index d70e8df3..980831b6 100644 --- a/src/frameworks/UBFileSystemUtils.cpp +++ b/src/frameworks/UBFileSystemUtils.cpp @@ -57,7 +57,7 @@ UBFileSystemUtils::~UBFileSystemUtils() QString UBFileSystemUtils::removeLocalFilePrefix(QString input) { -#ifdef Q_OS_WIN +#ifdef Q_WS_WIN if(input.startsWith("file:///")) return input.mid(8); else @@ -592,12 +592,17 @@ UBMimeType::Enum UBFileSystemUtils::mimeTypeFromString(const QString& typeString { type = UBMimeType::PDF; } - else if (typeString.startsWith("application/vnd.mnemis-uniboard-tool")) + /* else if (typeString.startsWith("application/vnd.mnemis-uniboard-tool")) { type = UBMimeType::UniboardTool; - } + } */ + else if (typeString.startsWith("application/openboard-tool")) + { + type = UBMimeType::OpenboardTool; + } return type; + } UBMimeType::Enum UBFileSystemUtils::mimeTypeFromUrl(const QUrl& url) From b6088a487b7f5d48d1827ff9035a694832869320 Mon Sep 17 00:00:00 2001 From: agriche Date: Thu, 19 Nov 2015 14:47:40 +0100 Subject: [PATCH 018/243] - Replace uniboardTool by OpenboardTool. --- src/board/UBFeaturesController.cpp | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/board/UBFeaturesController.cpp b/src/board/UBFeaturesController.cpp index ab2588e7..51178d2c 100644 --- a/src/board/UBFeaturesController.cpp +++ b/src/board/UBFeaturesController.cpp @@ -346,6 +346,8 @@ UBFeaturesController::UBFeaturesController(QWidget *pParentWidget) : scanFS(); featuresModel = new UBFeaturesModel(featuresList, this); + //featuresModel->setSupportedDragActions(Qt::CopyAction | Qt::MoveAction); + //featuresModel->setSupportedDragActions(Qt::CopyAction | Qt::MoveAction); featuresProxyModel = new UBFeaturesProxyModel(this); featuresProxyModel->setFilterFixedString(rootPath); @@ -448,7 +450,7 @@ void UBFeaturesController::fileSystemScan(const QUrl & currentPath, const QStrin if ( fullFileName.contains(".thumbnail.")) continue; - + UBFeature testFeature(currVirtualPath + "/" + fileName, icon, fileName, QUrl::fromLocalFile(fullFileName), featureType); featuresList->append(testFeature); @@ -620,7 +622,8 @@ void UBFeaturesController::removeFromFavorite( const QUrl &path, bool deleteManu QString UBFeaturesController::fileNameFromUrl( const QUrl &url ) { QString fileName = url.toString(); - if ( fileName.contains( "uniboardTool://" ) ) + //if ( fileName.contains( "uniboardTool://")) + if ( fileName.contains( "OpenboardTool://")) return fileName; return url.toLocalFile(); } @@ -630,7 +633,8 @@ UBFeatureElementType UBFeaturesController::fileTypeFromUrl(const QString &path) { QFileInfo fileInfo(path); - if ( path.contains("uniboardTool://")) + //if ( path.contains("uniboardTool://")) + if ( path.contains("OpenboardTool://")) return FEATURE_INTERNAL; if (!fileInfo.exists()) { @@ -749,17 +753,17 @@ void UBFeaturesController::importImage( const QImage &image, const UBFeature &de QDateTime now = QDateTime::currentDateTime(); static int imageCounter = 0; mFileName = tr("ImportedImage") + "-" + now.toString("dd-MM-yyyy hh-mm-ss"); - + filePath = dest.getFullPath().toLocalFile() + "/" + mFileName; if (QFile::exists(filePath+".png")) mFileName += QString("-[%1]").arg(++imageCounter); else imageCounter = 0; - + mFileName += ".png"; } - + if ( !destination.getFullVirtualPath().startsWith( picturesElement.getFullVirtualPath(), Qt::CaseInsensitive ) ) { @@ -860,7 +864,7 @@ void UBFeaturesController::addDownloadedFile(const QUrl &sourceUrl, const QByteA QString fileName; QString filePath; - + //Audio item if(dest == picturesElement) { @@ -912,7 +916,7 @@ UBFeature UBFeaturesController::moveItemToFolder( const QUrl &url, const UBFeatu UBFeature dest = destination; - if ( destination != trashElement && + if ( destination != trashElement && !destination.getFullVirtualPath().startsWith( possibleDest.getFullVirtualPath(), Qt::CaseInsensitive ) ) { dest = possibleDest; @@ -929,9 +933,9 @@ UBFeature UBFeaturesController::moveItemToFolder( const QUrl &url, const UBFeatu } QImage thumb = getIcon( newFullPath ); - + UBFeatureElementType type = FEATURE_ITEM; - if ( UBFileSystemUtils::mimeTypeFromFileName( newFullPath ).contains("application") ) + if ( UBFileSystemUtils::mimeTypeFromFileName( newFullPath ).contains("application") ) type = FEATURE_INTERACTIVE; UBFeature newElement( destVirtualPath + "/" + name, thumb, name, QUrl::fromLocalFile( newFullPath ), type ); return newElement; @@ -1041,8 +1045,11 @@ void UBFeaturesController::moveExternalData(const QUrl &url, const UBFeature &de UBFeature dest = destination; - if ( destination != trashElement && destination != UBFeature()) + if ( destination != trashElement && destination != UBFeature() + /*&& !destination.getFullVirtualPath().startsWith( possibleDest.getFullVirtualPath(), Qt::CaseInsensitive )*/ ) + { dest = possibleDest; + } UBFeatureElementType type = fileTypeFromUrl(sourcePath); From 642d1546eba719fb55bbf56869845a26d01bf653 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Fri, 20 Nov 2015 14:49:52 +0100 Subject: [PATCH 019/243] Podcast functionality (partially) restored on OS X. Migrated all QuickTime-related code to modern AVFoundation / Core Video / Core Media equivalents. Audio support was temporarily removed; to be re-established ASAP. Beginnings of doxygen-style function documentation was added --- OpenBoard.pro | 4 +- src/podcast/UBPodcastController.cpp | 14 +- src/podcast/podcast.pri | 69 +- .../quicktime/UBAudioQueueRecorder.cpp | 4 +- src/podcast/quicktime/UBQuickTimeFile.cpp | 656 ------------------ src/podcast/quicktime/UBQuickTimeFile.h | 77 +- src/podcast/quicktime/UBQuickTimeFile.mm | 262 +++++++ .../quicktime/UBQuickTimeVideoEncoder.cpp | 10 +- 8 files changed, 348 insertions(+), 748 deletions(-) delete mode 100644 src/podcast/quicktime/UBQuickTimeFile.cpp create mode 100644 src/podcast/quicktime/UBQuickTimeFile.mm diff --git a/OpenBoard.pro b/OpenBoard.pro index 4ba4b151..b6802c50 100644 --- a/OpenBoard.pro +++ b/OpenBoard.pro @@ -130,13 +130,13 @@ macx { LIBS += -framework Foundation LIBS += -framework Cocoa LIBS += -framework Carbon + LIBS += -framework AVFoundation + LIBS += -framework CoreMedia LIBS += -lcrypto CONFIG(release, debug|release):CONFIG += x86_64 CONFIG(debug, debug|release):CONFIG += x86_64 - # TODO Craig: switch to 64bit - QMAKE_MAC_SDK = macosx QMAKE_MACOSX_DEPLOYMENT_TARGET = "10.10" diff --git a/src/podcast/UBPodcastController.cpp b/src/podcast/UBPodcastController.cpp index 45a5e435..12641434 100644 --- a/src/podcast/UBPodcastController.cpp +++ b/src/podcast/UBPodcastController.cpp @@ -59,9 +59,9 @@ #ifdef Q_OS_WIN #include "windowsmedia/UBWindowsMediaVideoEncoder.h" #include "windowsmedia/UBWaveRecorder.h" -//#elif defined(Q_OS_OSX) -// #include "quicktime/UBQuickTimeVideoEncoder.h" -// #include "quicktime/UBAudioQueueRecorder.h" +#elif defined(Q_OS_OSX) + #include "quicktime/UBQuickTimeVideoEncoder.h" + #include "quicktime/UBAudioQueueRecorder.h" #endif #include "core/memcheck.h" @@ -305,8 +305,8 @@ void UBPodcastController::start() #ifdef Q_OS_WIN mVideoEncoder = new UBWindowsMediaVideoEncoder(this); //deleted on stop -//#elif defined(Q_OS_OSX) -// mVideoEncoder = new UBQuickTimeVideoEncoder(this); //deleted on stop +#elif defined(Q_OS_OSX) + mVideoEncoder = new UBQuickTimeVideoEncoder(this); //deleted on stop #endif if (mVideoEncoder) @@ -795,8 +795,8 @@ QStringList UBPodcastController::audioRecordingDevices() #ifdef Q_OS_WIN devices = UBWaveRecorder::waveInDevices(); -//#elif defined(Q_OS_OSX) -// devices = UBAudioQueueRecorder::waveInDevices(); +#elif defined(Q_OS_OSX) + devices = UBAudioQueueRecorder::waveInDevices(); #endif return devices; diff --git a/src/podcast/podcast.pri b/src/podcast/podcast.pri index d6d5aa94..3dde6273 100644 --- a/src/podcast/podcast.pri +++ b/src/podcast/podcast.pri @@ -1,34 +1,35 @@ - -HEADERS += src/podcast/UBPodcastController.h \ - src/podcast/UBAbstractVideoEncoder.h \ - src/podcast/UBPodcastRecordingPalette.h \ - src/podcast/youtube/UBYouTubePublisher.h \ - src/podcast/intranet/UBIntranetPodcastPublisher.h - -SOURCES += src/podcast/UBPodcastController.cpp \ - src/podcast/UBAbstractVideoEncoder.cpp \ - src/podcast/UBPodcastRecordingPalette.cpp \ - src/podcast/youtube/UBYouTubePublisher.cpp \ - src/podcast/intranet/UBIntranetPodcastPublisher.cpp - -win32 { - - SOURCES += src/podcast/windowsmedia/UBWindowsMediaVideoEncoder.cpp \ - src/podcast/windowsmedia/UBWindowsMediaFile.cpp \ - src/podcast/windowsmedia/UBWaveRecorder.cpp - - HEADERS += src/podcast/windowsmedia/UBWindowsMediaVideoEncoder.h \ - src/podcast/windowsmedia/UBWindowsMediaFile.h \ - src/podcast/windowsmedia/UBWaveRecorder.h -} - -#macx { - -# SOURCES += src/podcast/quicktime/UBQuickTimeVideoEncoder.cpp \ -# src/podcast/quicktime/UBQuickTimeFile.cpp \ -# src/podcast/quicktime/UBAudioQueueRecorder.cpp - -# HEADERS += src/podcast/quicktime/UBQuickTimeVideoEncoder.h \ -# src/podcast/quicktime/UBQuickTimeFile.h \ -# src/podcast/quicktime/UBAudioQueueRecorder.h -#} + +HEADERS += src/podcast/UBPodcastController.h \ + src/podcast/UBAbstractVideoEncoder.h \ + src/podcast/UBPodcastRecordingPalette.h \ + src/podcast/youtube/UBYouTubePublisher.h \ + src/podcast/intranet/UBIntranetPodcastPublisher.h + +SOURCES += src/podcast/UBPodcastController.cpp \ + src/podcast/UBAbstractVideoEncoder.cpp \ + src/podcast/UBPodcastRecordingPalette.cpp \ + src/podcast/youtube/UBYouTubePublisher.cpp \ + src/podcast/intranet/UBIntranetPodcastPublisher.cpp + +win32 { + + SOURCES += src/podcast/windowsmedia/UBWindowsMediaVideoEncoder.cpp \ + src/podcast/windowsmedia/UBWindowsMediaFile.cpp \ + src/podcast/windowsmedia/UBWaveRecorder.cpp + + HEADERS += src/podcast/windowsmedia/UBWindowsMediaVideoEncoder.h \ + src/podcast/windowsmedia/UBWindowsMediaFile.h \ + src/podcast/windowsmedia/UBWaveRecorder.h +} + +macx { + + SOURCES += src/podcast/quicktime/UBQuickTimeVideoEncoder.cpp \ + src/podcast/quicktime/UBAudioQueueRecorder.cpp + + HEADERS += src/podcast/quicktime/UBQuickTimeVideoEncoder.h \ + src/podcast/quicktime/UBQuickTimeFile.h \ + src/podcast/quicktime/UBAudioQueueRecorder.h + + OBJECTIVE_SOURCES += src/podcast/quicktime/UBQuickTimeFile.mm +} diff --git a/src/podcast/quicktime/UBAudioQueueRecorder.cpp b/src/podcast/quicktime/UBAudioQueueRecorder.cpp index 1c529ab5..43c106f2 100644 --- a/src/podcast/quicktime/UBAudioQueueRecorder.cpp +++ b/src/podcast/quicktime/UBAudioQueueRecorder.cpp @@ -151,10 +151,10 @@ QString UBAudioQueueRecorder::deviceUIDFromDeviceID(AudioDeviceID id) { char *cname = new char[1024]; - CFStringGetCString (name, cname, 1024, kCFStringEncodingASCII); + CFStringGetCString (name, cname, 1024, kCFStringEncodingISOLatin1); int length = CFStringGetLength (name); - uid = QString::fromAscii(cname, length); + uid = QString::fromLatin1(cname, length); delete cname; diff --git a/src/podcast/quicktime/UBQuickTimeFile.cpp b/src/podcast/quicktime/UBQuickTimeFile.cpp deleted file mode 100644 index 97ebf048..00000000 --- a/src/podcast/quicktime/UBQuickTimeFile.cpp +++ /dev/null @@ -1,656 +0,0 @@ -/* - * Copyright (C) 2013 Open Education Foundation - * - * Copyright (C) 2010-2013 Groupement d'Intérêt Public pour - * l'Education Numérique en Afrique (GIP ENA) - * - * This file is part of OpenBoard. - * - * OpenBoard is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3 of the License, - * with a specific linking exception for the OpenSSL project's - * "OpenSSL" library (or with modified versions of it that use the - * same license as the "OpenSSL" library). - * - * OpenBoard is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with OpenBoard. If not, see . - */ - - - - -#include "UBQuickTimeFile.h" - -#include - -#include "UBAudioQueueRecorder.h" -#include - -#include "core/memcheck.h" - -QQueue UBQuickTimeFile::frameQueue; -QMutex UBQuickTimeFile::frameQueueMutex; -QWaitCondition UBQuickTimeFile::frameBufferNotEmpty; - - -UBQuickTimeFile::UBQuickTimeFile(QObject * pParent) - : QThread(pParent) - , mVideoCompressionSession(0) - , mVideoMedia(0) - , mSoundMedia(0) - , mVideoOutputTrack(0) - , mSoundOutputTrack(0) - , mCVPixelBufferPool(0) - , mOutputMovie(0) - , mFramesPerSecond(-1) - , mTimeScale(100) - , mRecordAudio(true) - , mWaveRecorder(0) - , mSouldStopCompression(false) - , mCompressionSessionRunning(false) - , mPendingFrames(0) -{ - // NOOP -} - - -bool UBQuickTimeFile::init(const QString& pVideoFileName, const QString& pProfileData, int pFramesPerSecond - , const QSize& pFrameSize, bool pRecordAudio, const QString& audioRecordingDevice) -{ - mFrameSize = pFrameSize; - mFramesPerSecond = pFramesPerSecond; - mVideoFileName = pVideoFileName; - mRecordAudio = pRecordAudio && QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5; // Audio Queue are available in 10.5 +; - - if (mRecordAudio) - mAudioRecordingDeviceName = audioRecordingDevice; - else - mAudioRecordingDeviceName = ""; - - if (pProfileData.toLower() == "lossless") - mSpatialQuality = codecLosslessQuality; - if (pProfileData.toLower() == "high") - mSpatialQuality = codecHighQuality; - else if (pProfileData.toLower() == "normal") - mSpatialQuality = codecNormalQuality; - else if (pProfileData.toLower() == "low") - mSpatialQuality = codecLowQuality; - else - mSpatialQuality = codecHighQuality; - - qDebug() << "Quality " << pProfileData << mSpatialQuality; - - return true; - -} - - -void UBQuickTimeFile::run() -{ - EnterMoviesOnThread(kCSAcceptThreadSafeComponentsOnlyMode); - - mSouldStopCompression = false; - mPendingFrames = 0; - - createCompressionSession(); - - mCompressionSessionRunning = true; - emit compressionSessionStarted(); - - while(!mSouldStopCompression) - { - frameQueueMutex.lock(); - //qDebug() << "run .... wait" << QTime::currentTime(); - - frameBufferNotEmpty.wait(&UBQuickTimeFile::frameQueueMutex); - - //qDebug() << "awakend ..." << QTime::currentTime(); - if (!frameQueue.isEmpty()) - { - QQueue localQueue = frameQueue; - frameQueue.clear(); - - frameQueueMutex.unlock(); - - while (!localQueue.isEmpty()) - { - VideoFrame frame = localQueue.dequeue(); - appendVideoFrame(frame.buffer, frame.timestamp); - } - } - else - { - frameQueueMutex.unlock(); - } - } - - flushPendingFrames(); -} - - -bool UBQuickTimeFile::createCompressionSession() -{ - CodecType codecType = kH264CodecType; - - CFStringRef keys[] = {kCVPixelBufferPixelFormatTypeKey, kCVPixelBufferWidthKey, kCVPixelBufferHeightKey}; - - int width = mFrameSize.width(); - int height = mFrameSize.height(); - int pixelFormat = k32BGRAPixelFormat; - - CFTypeRef values[] = - { - (CFTypeRef)CFNumberCreate(0, kCFNumberIntType, (void*)&pixelFormat), - (CFTypeRef)CFNumberCreate(0, kCFNumberIntType, (void*)&width), - (CFTypeRef)CFNumberCreate(0, kCFNumberIntType, (void*)&height) - }; - - CFDictionaryRef pixelBufferAttributes = CFDictionaryCreate(kCFAllocatorDefault - , (const void **)keys, (const void **)values, 3, 0, 0); - - if(!pixelBufferAttributes) - { - setLastErrorMessage("Could not create CV buffer pool pixel buffer attributes"); - return false; - } - - OSStatus err = noErr; - ICMEncodedFrameOutputRecord encodedFrameOutputRecord = {NULL, NULL, NULL}; - ICMCompressionSessionOptionsRef sessionOptions = 0; - - err = ICMCompressionSessionOptionsCreate(0, &sessionOptions); - if(err) - { - setLastErrorMessage(QString("ICMCompressionSessionOptionsCreate() failed %1").arg(err)); - goto bail; - } - - // We must set this flag to enable P or B frames. - err = ICMCompressionSessionOptionsSetAllowTemporalCompression(sessionOptions, true); - if(err) - { - setLastErrorMessage(QString("ICMCompressionSessionOptionsSetAllowTemporalCompression() failed %1").arg(err)); - goto bail; - } - - // We must set this flag to enable B frames. - err = ICMCompressionSessionOptionsSetAllowFrameReordering(sessionOptions, true); - if(err) - { - setLastErrorMessage(QString("ICMCompressionSessionOptionsSetAllowFrameReordering() failed %1").arg(err)); - goto bail; - } - - // Set the maximum key frame interval, also known as the key frame rate. - err = ICMCompressionSessionOptionsSetMaxKeyFrameInterval(sessionOptions, mFramesPerSecond); - if(err) - { - setLastErrorMessage(QString("ICMCompressionSessionOptionsSetMaxKeyFrameInterval() failed %1").arg(err)); - goto bail; - } - - // This allows the compressor more flexibility (ie, dropping and coalescing frames). - err = ICMCompressionSessionOptionsSetAllowFrameTimeChanges(sessionOptions, true); - if(err) - { - setLastErrorMessage(QString("ICMCompressionSessionOptionsSetAllowFrameTimeChanges() failed %1").arg(err)); - goto bail; - } - - // Set the average quality. - err = ICMCompressionSessionOptionsSetProperty(sessionOptions, - kQTPropertyClass_ICMCompressionSessionOptions, - kICMCompressionSessionOptionsPropertyID_Quality, - sizeof(mSpatialQuality), - &mSpatialQuality); - if(err) - { - setLastErrorMessage(QString("ICMCompressionSessionOptionsSetProperty(Quality) failed %1").arg(err)); - goto bail; - } - - //qDebug() << "available quality" << mSpatialQuality; - - encodedFrameOutputRecord.encodedFrameOutputCallback = addEncodedFrameToMovie; - encodedFrameOutputRecord.encodedFrameOutputRefCon = this; - encodedFrameOutputRecord.frameDataAllocator = 0; - - err = ICMCompressionSessionCreate(0, mFrameSize.width(), mFrameSize.height(), codecType, mTimeScale, - sessionOptions, pixelBufferAttributes, &encodedFrameOutputRecord, &mVideoCompressionSession); - if(err) - { - setLastErrorMessage(QString("ICMCompressionSessionCreate() failed %1").arg(err)); - goto bail; - } - - mCVPixelBufferPool = ICMCompressionSessionGetPixelBufferPool(mVideoCompressionSession); - - if(!mCVPixelBufferPool) - { - setLastErrorMessage("ICMCompressionSessionGetPixelBufferPool() failed."); - err = !noErr; - goto bail; - } - - if(mRecordAudio) - { - mWaveRecorder = new UBAudioQueueRecorder(); - - if(mWaveRecorder->init(mAudioRecordingDeviceName)) - { - connect(mWaveRecorder, SIGNAL(newWaveBuffer(void*, long, int , const AudioStreamPacketDescription*)) - , this, SLOT(appendAudioBuffer(void*, long, int, const AudioStreamPacketDescription*))); - - connect(mWaveRecorder, SIGNAL(audioLevelChanged(quint8)), this, SIGNAL(audioLevelChanged(quint8))); - } - else - { - setLastErrorMessage(mWaveRecorder->lastErrorMessage()); - mWaveRecorder->deleteLater(); - } - } - - createMovie(); - -bail: - ICMCompressionSessionOptionsRelease(sessionOptions); - sessionOptions = 0; - - CFRelease(pixelBufferAttributes); - - return err == noErr; -} - - -void UBQuickTimeFile::stop() -{ - mSouldStopCompression = true; -} - -bool UBQuickTimeFile::flushPendingFrames() -{ - mCompressionSessionRunning = false; - - if (mWaveRecorder) - { - mWaveRecorder->close(); - mWaveRecorder->deleteLater(); - } - - //Flush pending frames in compression session - OSStatus err = ICMCompressionSessionCompleteFrames(mVideoCompressionSession, true, 0, 0); - if (err) - { - setLastErrorMessage(QString("ICMCompressionSessionCompleteFrames() failed %1").arg(err)); - return false; - } - - return true; -} - - -bool UBQuickTimeFile::closeCompressionSession() -{ - OSStatus err = noErr; - - if (mVideoMedia) - { - // End the media sample-adding session. - err = EndMediaEdits(mVideoMedia); - if (err) - { - setLastErrorMessage(QString("EndMediaEdits(mVideoMedia) failed %1").arg(err)); - return false; - } - - // Make sure things are extra neat. - ExtendMediaDecodeDurationToDisplayEndTime(mVideoMedia, 0); - - // Insert the stuff we added into the track, at the end. - Track videoTrack = GetMediaTrack(mVideoMedia); - - err = InsertMediaIntoTrack(videoTrack, - GetTrackDuration(videoTrack), - 0, GetMediaDisplayDuration(mVideoMedia), - fixed1); - mVideoMedia = 0; - - if (err) - { - setLastErrorMessage(QString("InsertMediaIntoTrack() failed %1").arg(err)); - return false; - } - - if (mSoundMedia) - { - err = EndMediaEdits(mSoundMedia); - if(err) - { - setLastErrorMessage(QString("EndMediaEdits(mAudioMedia) failed %1").arg(err)); - return false; - } - - Track soundTrack = GetMediaTrack(mSoundMedia); - - err = InsertMediaIntoTrack(soundTrack, - GetTrackDuration(soundTrack), - 0, GetMediaDisplayDuration(mSoundMedia), - fixed1); - - mSoundMedia = 0; - - if (err) - { - setLastErrorMessage(QString("InsertMediaIntoTrack(mAudioMedia) failed %1").arg(err)); - } - - TimeValue soundTrackDuration = GetTrackDuration(soundTrack); - TimeValue videoTrackDuration = GetTrackDuration(videoTrack); - - if (soundTrackDuration > videoTrackDuration) - { - qDebug() << "Sound track is longer then video track" << soundTrackDuration << ">" << videoTrackDuration; - DeleteTrackSegment(soundTrack, videoTrackDuration, soundTrackDuration - videoTrackDuration); - } - - DisposeHandle((Handle)mSoundDescription); - } - } - - // Write the movie header to the file. - err = AddMovieToStorage(mOutputMovie, mOutputMovieDataHandler); - if (err) - { - setLastErrorMessage(QString("AddMovieToStorage() failed %1").arg(err)); - return false; - } - - err = UpdateMovieInStorage(mOutputMovie, mOutputMovieDataHandler); - if (err) - { - setLastErrorMessage(QString("UpdateMovieInStorage() failed %1").arg(err)); - return false; - } - - err = CloseMovieStorage(mOutputMovieDataHandler); - if (err) - { - setLastErrorMessage(QString("CloseMovieStorage() failed %1").arg(err)); - return false; - } - - CVPixelBufferPoolRelease(mCVPixelBufferPool); - mCVPixelBufferPool = 0; - - mOutputMovie = 0; - mOutputMovieDataHandler = 0; - mVideoCompressionSession = 0; - - ExitMoviesOnThread(); - - return true; -} - - -OSStatus UBQuickTimeFile::addEncodedFrameToMovie(void *encodedFrameOutputRefCon, - ICMCompressionSessionRef session, - OSStatus err, - ICMEncodedFrameRef encodedFrame, - void *reserved) -{ - Q_UNUSED(session); - Q_UNUSED(reserved); - - UBQuickTimeFile *quickTimeFile = (UBQuickTimeFile *)encodedFrameOutputRefCon; - - if(quickTimeFile) - quickTimeFile->addEncodedFrame(encodedFrame, err); - - return noErr; -} - - -void UBQuickTimeFile::addEncodedFrame(ICMEncodedFrameRef encodedFrame, OSStatus frameErr) -{ - mPendingFrames--; - - //qDebug() << "addEncodedFrame" << mSouldStopCompression << mPendingFrames; - - if(frameErr == noErr) - { - if (mVideoMedia) - { - OSStatus err = AddMediaSampleFromEncodedFrame(mVideoMedia, encodedFrame, 0); - - if(err) - { - setLastErrorMessage(QString("AddMediaSampleFromEncodedFrame() failed %1").arg(err)); - } - } - } - else - { - setLastErrorMessage(QString("addEncodedFrame received an error %1").arg(frameErr)); - } - - if (mSouldStopCompression && mPendingFrames == 0) - { - closeCompressionSession(); - } -} - - -bool UBQuickTimeFile::createMovie() -{ - if(!mOutputMovie) - { - OSStatus err = noErr; - - Handle dataRef; - OSType dataRefType; - - CFStringRef filePath = CFStringCreateWithCString(0, mVideoFileName.toUtf8().constData(), kCFStringEncodingUTF8); - - QTNewDataReferenceFromFullPathCFString(filePath, kQTPOSIXPathStyle, 0, &dataRef, &dataRefType); - - err = CreateMovieStorage(dataRef, dataRefType, 'TVOD', 0, createMovieFileDeleteCurFile, &mOutputMovieDataHandler, &mOutputMovie); - if(err) - { - setLastErrorMessage(QString("CreateMovieStorage() failed %1").arg(err)); - return false; - } - - mVideoOutputTrack = NewMovieTrack(mOutputMovie, X2Fix(mFrameSize.width()), X2Fix(mFrameSize.height()), 0); - err = GetMoviesError(); - - if( err ) - { - setLastErrorMessage(QString("NewMovieTrack(Video) failed %1").arg(err)); - return false; - } - - if(!createVideoMedia()) - return false; - - if(mRecordAudio) - { - mSoundOutputTrack = NewMovieTrack(mOutputMovie, 0, 0, kFullVolume); - err = GetMoviesError(); - - if(err) - { - setLastErrorMessage(QString("NewMovieTrack(Sound) failed %1").arg(err)); - return false; - } - - if(!createAudioMedia()) - return false; - } - } - - return true; -} - - -bool UBQuickTimeFile::createVideoMedia() -{ - mVideoMedia = NewTrackMedia(mVideoOutputTrack, VideoMediaType, mTimeScale, 0, 0); - OSStatus err = GetMoviesError(); - - if (err) - { - setLastErrorMessage(QString("NewTrackMedia(VideoMediaType) failed %1").arg(err)); - return false; - } - - err = BeginMediaEdits(mVideoMedia); - if (err) - { - setLastErrorMessage(QString("BeginMediaEdits(VideoMediaType) failed %1").arg(err)); - return false; - } - - return true; -} - - -bool UBQuickTimeFile::createAudioMedia() -{ - if(mRecordAudio) - { - mAudioDataFormat = UBAudioQueueRecorder::audioFormat(); - - mSoundMedia = NewTrackMedia(mSoundOutputTrack, SoundMediaType, mAudioDataFormat.mSampleRate, 0, 0); - OSStatus err = GetMoviesError(); - if(err) - { - setLastErrorMessage(QString("NewTrackMedia(AudioMediaType) failed %1").arg(err)); - return false; - } - - err = BeginMediaEdits(mSoundMedia); - if(err) - { - setLastErrorMessage(QString("BeginMediaEdits(AudioMediaType) failed %1").arg(err)); - return false; - } - - err = QTSoundDescriptionCreate(&mAudioDataFormat, 0, 0, 0, 0, - kQTSoundDescriptionKind_Movie_LowestPossibleVersion, - &mSoundDescription); - if (err) - { - setLastErrorMessage(QString("QTSoundDescriptionCreate() failed %1").arg(err)); - return false; - } - - - err = QTSoundDescriptionGetProperty(mSoundDescription, kQTPropertyClass_SoundDescription, - kQTSoundDescriptionPropertyID_AudioStreamBasicDescription, - sizeof(mAudioDataFormat), &mAudioDataFormat, 0); - if (err) - { - setLastErrorMessage(QString("QTSoundDescriptionGetProperty() failed %1").arg(err)); - return false; - } - - } - - return true; -} - - -UBQuickTimeFile::~UBQuickTimeFile() -{ - // NOOP -} - - -CVPixelBufferRef UBQuickTimeFile::newPixelBuffer() -{ - CVPixelBufferRef pixelBuffer = 0; - - if(CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, mCVPixelBufferPool, &pixelBuffer) != kCVReturnSuccess) - { - setLastErrorMessage("Could not retreive CV buffer from pool"); - return 0; - } - - return pixelBuffer; -} - - -void UBQuickTimeFile::appendVideoFrame(CVPixelBufferRef pixelBuffer, long msTimeStamp) -{ - TimeValue64 msTimeStampScaled = msTimeStamp * mTimeScale / 1000; - - /* - { - CVPixelBufferLockBaseAddress(pixelBuffer, 0) ; - void *pixelBufferAddress = CVPixelBufferGetBaseAddress(pixelBuffer); - qDebug() << "will comp newVideoFrame - PixelBuffer @" << pixelBufferAddress - << QTime::currentTime().toString("ss:zzz") << QThread::currentThread(); - CVPixelBufferUnlockBaseAddress(pixelBuffer, 0); - } - */ - - OSStatus err = ICMCompressionSessionEncodeFrame(mVideoCompressionSession, pixelBuffer, - msTimeStampScaled, 0, kICMValidTime_DisplayTimeStampIsValid, - 0, 0, 0); - - if (err == noErr) - { - mPendingFrames++; - } - else - { - setLastErrorMessage(QString("Could not encode frame %1").arg(err)); - } - - CVPixelBufferRelease(pixelBuffer); -} - - -void UBQuickTimeFile::appendAudioBuffer(void* pBuffer, long pLength, int inNumberPacketDescriptions, const AudioStreamPacketDescription* inPacketDescs) -{ - Q_UNUSED(pLength); - //qDebug() << "appendAudioBuffer" << QThread::currentThread(); - - if(mRecordAudio) - { - for (int i = 0; i < inNumberPacketDescriptions; i++) - { - OSStatus err = AddMediaSample2(mSoundMedia, - (UInt8*)pBuffer + inPacketDescs[i].mStartOffset, - inPacketDescs[i].mDataByteSize, - mAudioDataFormat.mFramesPerPacket, - 0, - (SampleDescriptionHandle)mSoundDescription, - 1, - 0, - 0); - if (err) - { - setLastErrorMessage(QString("AddMediaSample2(soundMedia) failed %1").arg(err)); - } - } - } -#ifdef Q_OS_OSX - free((void*)inPacketDescs); -#endif -} - - -void UBQuickTimeFile::setLastErrorMessage(const QString& error) -{ - mLastErrorMessage = error; - qWarning() << "UBQuickTimeFile error" << error; -} - - diff --git a/src/podcast/quicktime/UBQuickTimeFile.h b/src/podcast/quicktime/UBQuickTimeFile.h index d6fe2ce6..1d1efd70 100644 --- a/src/podcast/quicktime/UBQuickTimeFile.h +++ b/src/podcast/quicktime/UBQuickTimeFile.h @@ -30,12 +30,29 @@ #include -#include -#include -#include +#include #include "UBAudioQueueRecorder.h" + + +// Trick to get around the fact that the C++ compiler doesn't +// like Objective C code. + +#ifdef __OBJC__ // defined by the Objective C compiler + @class AVAssetWriter; + @class AVAssetWriterInput; + @class AVAssetWriterInputPixelBufferAdaptor; + + typedef AVAssetWriter* AssetWriterPTR; + typedef AVAssetWriterInput* AssetWriterInputPTR; + typedef AVAssetWriterInputPixelBufferAdaptor* AssetWriterInputAdaptorPTR; +#else + typedef void* AssetWriterPTR; + typedef void* AssetWriterInputPTR; + typedef void* AssetWriterInputAdaptorPTR; +#endif + class UBQuickTimeFile : public QThread { Q_OBJECT; @@ -52,15 +69,11 @@ class UBQuickTimeFile : public QThread CVPixelBufferRef newPixelBuffer(); - bool isCompressionSessionRunning() - { - return mCompressionSessionRunning; - } + bool isCompressionSessionRunning() { return mCompressionSessionRunning; } - QString lastErrorMessage() const - { - return mLastErrorMessage; - } + QString lastErrorMessage() const { return mLastErrorMessage; } + + void endSession(); struct VideoFrame { @@ -79,47 +92,19 @@ class UBQuickTimeFile : public QThread protected: void run(); - private slots: - - void appendAudioBuffer(void* pBuffer, long pLength, int inNumberPacketDescriptions - , const AudioStreamPacketDescription* inPacketDescs); private: - static OSStatus addEncodedFrameToMovie(void *encodedFrameOutputRefCon, - ICMCompressionSessionRef session, - OSStatus err, - ICMEncodedFrameRef encodedFrame, - void *reserved); + bool beginSession(); void appendVideoFrame(CVPixelBufferRef pixelBuffer, long msTimeStamp); - void addEncodedFrame(ICMEncodedFrameRef encodedFrame, OSStatus err); - - bool createCompressionSession(); - bool closeCompressionSession(); - bool createMovie(); - - bool createVideoMedia(); - bool createAudioMedia(); - void setLastErrorMessage(const QString& error); bool flushPendingFrames(); - ICMCompressionSessionRef mVideoCompressionSession; - - Media mVideoMedia; - Media mSoundMedia; - Track mVideoOutputTrack; - Track mSoundOutputTrack; - volatile CVPixelBufferPoolRef mCVPixelBufferPool; - SoundDescriptionHandle mSoundDescription; - - Movie mOutputMovie; - DataHandler mOutputMovieDataHandler; int mFramesPerSecond; QSize mFrameSize; @@ -130,17 +115,17 @@ class UBQuickTimeFile : public QThread QString mLastErrorMessage; - AudioStreamBasicDescription mAudioDataFormat; - - QPointer mWaveRecorder; + QString mSpatialQuality; - CodecQ mSpatialQuality; - - volatile bool mSouldStopCompression; + volatile bool mShouldStopCompression; volatile bool mCompressionSessionRunning; QString mAudioRecordingDeviceName; volatile int mPendingFrames; + + AssetWriterPTR mVideoWriter; + AssetWriterInputPTR mVideoWriterInput; + AssetWriterInputAdaptorPTR mAdaptor; }; #endif /* UBQUICKTIMEFILE_H_ */ diff --git a/src/podcast/quicktime/UBQuickTimeFile.mm b/src/podcast/quicktime/UBQuickTimeFile.mm new file mode 100644 index 00000000..e6e18d72 --- /dev/null +++ b/src/podcast/quicktime/UBQuickTimeFile.mm @@ -0,0 +1,262 @@ +/* + * Copyright (C) 2013 Open Education Foundation + * + * Copyright (C) 2010-2013 Groupement d'Intérêt Public pour + * l'Education Numérique en Afrique (GIP ENA) + * + * This file is part of OpenBoard. + * + * OpenBoard is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 of the License, + * with a specific linking exception for the OpenSSL project's + * "OpenSSL" library (or with modified versions of it that use the + * same license as the "OpenSSL" library). + * + * OpenBoard is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OpenBoard. If not, see . + */ + + + + +#include "UBQuickTimeFile.h" + +#include +#import +#import +#import + +#include "UBAudioQueueRecorder.h" +#include + +#include "core/memcheck.h" + +QQueue UBQuickTimeFile::frameQueue; +QMutex UBQuickTimeFile::frameQueueMutex; +QWaitCondition UBQuickTimeFile::frameBufferNotEmpty; + + +UBQuickTimeFile::UBQuickTimeFile(QObject * pParent) + : QThread(pParent) + , mVideoWriter(0) + , mVideoWriterInput(0) + , mAdaptor(0) + , mCVPixelBufferPool(0) + , mFramesPerSecond(-1) + , mTimeScale(100) + , mRecordAudio(true) + , mShouldStopCompression(false) + , mCompressionSessionRunning(false) + , mPendingFrames(0) +{ + // NOOP +} + + +UBQuickTimeFile::~UBQuickTimeFile() +{ + // NOOP +} + +bool UBQuickTimeFile::init(const QString& pVideoFileName, const QString& pProfileData, int pFramesPerSecond + , const QSize& pFrameSize, bool pRecordAudio, const QString& audioRecordingDevice) +{ + mFrameSize = pFrameSize; + mFramesPerSecond = pFramesPerSecond; + mVideoFileName = pVideoFileName; + mRecordAudio = pRecordAudio; + mSpatialQuality = pProfileData; + + if (mRecordAudio) + mAudioRecordingDeviceName = audioRecordingDevice; + else + mAudioRecordingDeviceName = ""; + + + qDebug() << "UBQuickTimeFile created; video size: " << pFrameSize.width() << " x " << pFrameSize.height(); + + return true; + +} + + +void UBQuickTimeFile::run() +{ + mShouldStopCompression = false; + mPendingFrames = 0; + + if (!beginSession()) + return; + + mCompressionSessionRunning = true; + emit compressionSessionStarted(); + + do { + frameQueueMutex.lock(); + + frameBufferNotEmpty.wait(&UBQuickTimeFile::frameQueueMutex); + + if (!frameQueue.isEmpty()) { + QQueue localQueue = frameQueue; + frameQueue.clear(); + + frameQueueMutex.unlock(); + + while (!localQueue.isEmpty()) { + if ([mVideoWriterInput isReadyForMoreMediaData]) { + VideoFrame frame = localQueue.dequeue(); + appendVideoFrame(frame.buffer, frame.timestamp); + } + else + usleep(10000); + } + } + else + frameQueueMutex.unlock(); + } while(!mShouldStopCompression); + + endSession(); + +} + +/** + * \brief Initialize the AVAssetWriter, which handles writing the media to file + */ +bool UBQuickTimeFile::beginSession() +{ + NSError *outError; + NSString * outputPath = [[NSString alloc] initWithUTF8String: mVideoFileName.toUtf8().data()]; + NSURL * outputUrl = [[NSURL alloc] initFileURLWithPath: outputPath]; + + if (!outputUrl) { + qDebug() << "Podcast video URL invalid; not recording"; + return false; + } + + // Create and check the assetWriter + mVideoWriter = [[AVAssetWriter assetWriterWithURL:outputUrl + fileType:AVFileTypeQuickTimeMovie + error:&outError] retain]; + NSCParameterAssert(mVideoWriter); + + mVideoWriter.movieTimeScale = mTimeScale; + + int frameWidth = mFrameSize.width(); + int frameHeight = mFrameSize.height(); + + // Create the input and check it + NSDictionary * videoSettings = [NSDictionary dictionaryWithObjectsAndKeys: + AVVideoCodecH264, AVVideoCodecKey, + [NSNumber numberWithInt:frameWidth], AVVideoWidthKey, + [NSNumber numberWithInt:frameHeight], AVVideoHeightKey, + nil]; + + + mVideoWriterInput = [[AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo + outputSettings:videoSettings] retain]; + NSCParameterAssert(mVideoWriterInput); + + + + // Pixel Buffer Adaptor. This makes it possible to pass CVPixelBuffers to the WriterInput + NSDictionary* pixelBufSettings = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithInt:kCVPixelFormatType_32BGRA], kCVPixelBufferPixelFormatTypeKey, + [NSNumber numberWithInt: frameWidth], kCVPixelBufferWidthKey, + [NSNumber numberWithInt: frameHeight], kCVPixelBufferHeightKey, + nil]; + + mAdaptor = [[AVAssetWriterInputPixelBufferAdaptor + assetWriterInputPixelBufferAdaptorWithAssetWriterInput:mVideoWriterInput + sourcePixelBufferAttributes:pixelBufSettings] retain]; + + + + // Add the input(s) to the assetWriter + NSCParameterAssert([mVideoWriter canAddInput:mVideoWriterInput]); + [mVideoWriter addInput:mVideoWriterInput]; + + + // begin the writing session + bool canStartWriting = [mVideoWriter startWriting]; + [mVideoWriter startSessionAtSourceTime:CMTimeMake(0, mTimeScale)]; + + // return true if everything was created and started successfully + return (mVideoWriter != nil) && (mVideoWriterInput != nil) && canStartWriting; +} + +/** + * \brief Close the recording sesion and finish writing the video file + */ +void UBQuickTimeFile::endSession() +{ + [mVideoWriterInput markAsFinished]; + bool success = [mVideoWriter finishWriting]; + + [mAdaptor release]; + [mVideoWriterInput release]; + [mVideoWriter release]; + + mAdaptor = nil; + mVideoWriterInput = nil; + mVideoWriter = nil; +} + +/** + * \brief Request the recording to stop + */ +void UBQuickTimeFile::stop() +{ + mShouldStopCompression = true; +} + + +/** + * \brief Create a CVPixelBufferRef from the input adaptor's CVPixelBufferPool + */ +CVPixelBufferRef UBQuickTimeFile::newPixelBuffer() +{ + CVPixelBufferRef pixelBuffer = 0; + + if(CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, mAdaptor.pixelBufferPool, &pixelBuffer) != kCVReturnSuccess) + { + setLastErrorMessage("Could not retrieve CV buffer from pool"); + return 0; + } + + return pixelBuffer; +} + + +/** + * \brief Add a frame to the pixel buffer adaptor + */ +void UBQuickTimeFile::appendVideoFrame(CVPixelBufferRef pixelBuffer, long msTimeStamp) +{ + //qDebug() << "adding video frame at time: " << msTimeStamp; + + CMTime t = CMTimeMake((msTimeStamp * mTimeScale / 1000.0), mTimeScale); + + bool added = [mAdaptor appendPixelBuffer: pixelBuffer + withPresentationTime: t]; + + if (!added) + setLastErrorMessage(QString("Could not encode frame at time %1").arg(msTimeStamp)); + + + CVPixelBufferRelease(pixelBuffer); +} + +void UBQuickTimeFile::setLastErrorMessage(const QString& error) +{ + mLastErrorMessage = error; + qWarning() << "UBQuickTimeFile error" << error; +} + + + diff --git a/src/podcast/quicktime/UBQuickTimeVideoEncoder.cpp b/src/podcast/quicktime/UBQuickTimeVideoEncoder.cpp index ab0271be..e3497640 100644 --- a/src/podcast/quicktime/UBQuickTimeVideoEncoder.cpp +++ b/src/podcast/quicktime/UBQuickTimeVideoEncoder.cpp @@ -130,6 +130,14 @@ void UBQuickTimeVideoEncoder::newPixmap(const QImage& pImage, long timestamp) } } +/** + * \brief Encode QImage into a video frame and add it to the UBQuickTimeFile's queue. + * + * This method retrieves the raw image from the supplied QImage, and uses memcpy to + * dump it into a CVPixelBuffer, obtained through the UBQuickTimeFile member. The + * pixel buffer, along with the timestamp, constitute a video frame which is added + * to the member UBQuickTimeFile's queue. + */ void UBQuickTimeVideoEncoder::encodeFrame(const QImage& pImage, long timestamp) { Q_ASSERT(pImage.format() == QImage::QImage::Format_RGB32); // <=> CVPixelBuffers / k32BGRAPixelFormat @@ -157,7 +165,7 @@ void UBQuickTimeVideoEncoder::encodeFrame(const QImage& pImage, long timestamp) const uchar* imageBuffer = pImage.bits(); - memcpy((void*) pixelBufferAddress, imageBuffer, pImage.numBytes()); + memcpy((void*) pixelBufferAddress, imageBuffer, pImage.byteCount()); CVPixelBufferUnlockBaseAddress(pixelBuffer, 0); From 7ad77bb4113ba50411ce96ebdca8682055b0331e Mon Sep 17 00:00:00 2001 From: agriche Date: Fri, 20 Nov 2015 15:34:39 +0100 Subject: [PATCH 020/243] - Update the include header qwidget. --- src/core/UBApplicationController.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/UBApplicationController.h b/src/core/UBApplicationController.h index cdcb5051..bca300b7 100644 --- a/src/core/UBApplicationController.h +++ b/src/core/UBApplicationController.h @@ -28,8 +28,8 @@ #ifndef UBAPPLICATIONCONTROLLER_H_ #define UBAPPLICATIONCONTROLLER_H_ -#include - +//#include +#include class UBBoardView; class UBDocumentProxy; From 9f311766da4be647acd89ff0ba1e54e813256968 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Fri, 20 Nov 2015 16:59:08 +0100 Subject: [PATCH 021/243] fixed keyboard switching on Mac OS --- src/frameworks/UBPlatformUtils_mac.mm | 32 ++++++++++++++++----------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/frameworks/UBPlatformUtils_mac.mm b/src/frameworks/UBPlatformUtils_mac.mm index b2623080..531e6fd0 100644 --- a/src/frameworks/UBPlatformUtils_mac.mm +++ b/src/frameworks/UBPlatformUtils_mac.mm @@ -533,29 +533,35 @@ QString UBPlatformUtils::urlFromClipboard() void UBPlatformUtils::SetMacLocaleByIdentifier(const QString& id) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + @autoreleasepool { + // convert id from QString to CFString + // TODO: clean this up + const QByteArray utf8 = id.toUtf8(); + const char* cString = utf8.constData(); + NSString * ns = [[NSString alloc] initWithUTF8String:cString]; - const char * strName = id.toLatin1().data(); + CFStringRef iName = (__bridge CFStringRef)ns; - CFStringRef iName = CFStringCreateWithCString(NULL, strName, kCFStringEncodingISOLatin1 ); - CFStringRef keys[] = { kTISPropertyInputSourceCategory, kTISPropertyInputSourceID }; - CFStringRef values[] = { kTISCategoryKeyboardInputSource, iName }; - CFDictionaryRef dict = CFDictionaryCreate(NULL, (const void **)keys, (const void **)values, 2, NULL, NULL); + CFStringRef keys[] = { kTISPropertyInputSourceID }; + CFStringRef values[] = { iName }; + CFDictionaryRef dict = CFDictionaryCreate(NULL, (const void **)keys, (const void **)values, 1, NULL, NULL); - // get list of current enabled keyboard layouts. dict filters the list - CFArrayRef kbds = TISCreateInputSourceList(dict, true); - if (kbds!=NULL) - { - if (CFArrayGetCount(kbds)!=0) - { + // get list of current enabled keyboard layouts. dict filters the list + // false specifies that we search only through the active input sources + CFArrayRef kbds = TISCreateInputSourceList(dict, false); + + if (kbds && CFArrayGetCount(kbds) == 0) + // if not found in the active sources, we search again through all sources installed + kbds = TISCreateInputSourceList(dict, true); + + if (kbds && CFArrayGetCount(kbds)!=0) { TISInputSourceRef klRef = (TISInputSourceRef)CFArrayGetValueAtIndex(kbds, 0); if (klRef!=NULL) TISSelectInputSource(klRef); } } - [pool drain]; } /** From 007a1e1286ad82b785516357134a8ce48621a7b2 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Mon, 23 Nov 2015 14:36:43 +0100 Subject: [PATCH 022/243] Cleaned up UBGraphicsMediaItem* - Removed commented out obsolete code that had been added - Removed objects that were never used (mAudioOutput, audioFormat etc) - Re-made changes that had been reverted since commit cdb5633 --- src/domain/UBGraphicsMediaItem.cpp | 50 +++------------------- src/domain/UBGraphicsMediaItem.h | 16 ------- src/domain/UBGraphicsMediaItemDelegate.cpp | 2 +- 3 files changed, 7 insertions(+), 61 deletions(-) diff --git a/src/domain/UBGraphicsMediaItem.cpp b/src/domain/UBGraphicsMediaItem.cpp index 8ae95aec..7d6edabc 100644 --- a/src/domain/UBGraphicsMediaItem.cpp +++ b/src/domain/UBGraphicsMediaItem.cpp @@ -50,13 +50,8 @@ UBGraphicsMediaItem::UBGraphicsMediaItem(const QUrl& pMediaFileUrl, QGraphicsIte update(); - //mMediaObject = new Phonon::MediaObject(this); mMediaObject = new QMediaPlayer(this); - //playlist = new QMediaPlaylist; - //mMediaObject->setPlaylist(playlist); - - QString mediaPath = pMediaFileUrl.toString(); if ("" == mediaPath) mediaPath = pMediaFileUrl.toLocalFile(); @@ -65,50 +60,27 @@ UBGraphicsMediaItem::UBGraphicsMediaItem(const QUrl& pMediaFileUrl, QGraphicsIte { mMediaType = mediaType_Video; - //mAudioOutput = new Phonon::AudioOutput(Phonon::VideoCategory, this); - QAudioFormat format; // to define - format.setByteOrder(QAudioFormat::LittleEndian); - format.setSampleType(QAudioFormat::UnSignedInt); - - //mAudioOutput = new QAudioOutput(format, this); - mAudioOutput = new QMediaPlayer; + mMediaObject->setNotifyInterval(50); - //mMediaObject->setTickInterval(50); - mMediaObject->setPosition(50); - - //mVideoWidget = new Phonon::VideoWidget(); // owned and destructed by the scene ... mVideoWidget = new QVideoWidget(); // owned and destructed by the scene ... - //Phonon::createPath(mMediaObject, mVideoWidget); mMediaObject->setVideoOutput(mVideoWidget); if(mVideoWidget->sizeHint() == QSize(1,1)){ mVideoWidget->resize(320,240); } - //mVideoWidget->setMinimumSize(140,26); mVideoWidget->setMinimumSize(320,240); haveLinkedImage = true; - // DEBUGGING VIDEO - //***************** - qDebug() << "UBGraphicsMediaItem.cpp:" << mVideoWidget << "setMinimumSize(140,26)" ; } else if (mediaPath.toLower().contains("audios")) { mMediaType = mediaType_Audio; - QAudioFormat format; - format.setByteOrder(QAudioFormat::LittleEndian); - format.setSampleType(QAudioFormat::UnSignedInt); - - // mAudioOutput = new Phonon::AudioOutput(Phonon::MusicCategory, this); - //mAudioOutput = new QMediaPlayer(format, this); - mAudioOutput = new QMediaPlayer; - - //mMediaObject->setTickInterval(1000); + mMediaObject->setNotifyInterval(1000); mAudioWidget = new QWidget(); mAudioWidget->resize(320,26); mAudioWidget->setMinimumSize(150,26); @@ -116,10 +88,6 @@ UBGraphicsMediaItem::UBGraphicsMediaItem(const QUrl& pMediaFileUrl, QGraphicsIte haveLinkedImage = false; } - //Phonon::createPath(mMediaObject, mAudioOutput); - //mSource = Phonon::MediaSource(pMediaFileUrl); - - //mMediaObject->setCurrentSource(mSource); mMediaObject->setMedia(pMediaFileUrl); @@ -147,7 +115,7 @@ UBGraphicsMediaItem::UBGraphicsMediaItem(const QUrl& pMediaFileUrl, QGraphicsIte setData(UBGraphicsItemData::itemLayerType, QVariant(itemLayerType::ObjectItem)); //Necessary to set if we want z value to be assigned correctly connect(Delegate(), SIGNAL(showOnDisplayChanged(bool)), this, SLOT(showOnDisplayChanged(bool))); - connect(mMediaObject, SIGNAL(hasVideoChanged(bool)), this, SLOT(hasMediaChanged(bool))); + connect(mMediaObject, SIGNAL(videoAvailableChanged(bool)), this, SLOT(hasMediaChanged(bool))); } @@ -192,12 +160,8 @@ QVariant UBGraphicsMediaItem::itemChange(GraphicsItemChange change, const QVaria absoluteMediaFilename = mMediaFileUrl.toLocalFile(); if (absoluteMediaFilename.length() > 0) - //mMediaObject->setCurrentSource(QMediaSource(absoluteMediaFilename)); mMediaObject->setMedia(QUrl::fromLocalFile(absoluteMediaFilename)); - - - } } @@ -230,7 +194,7 @@ void UBGraphicsMediaItem::toggleMute() void UBGraphicsMediaItem::setMute(bool bMute) { mMuted = bMute; - mAudioOutput->setMuted(mMuted); + mMediaObject->setMuted(mMuted); mMutedByUserAction = mMuted; sIsMutedByDefault = mMuted; } @@ -240,7 +204,6 @@ void UBGraphicsMediaItem::hasMediaChanged(bool hasMedia) { if(hasMedia && mMediaObject->isSeekable()) { - //mMediaObject->seek(mInitialPos); mMediaObject->setPosition(mInitialPos); UBGraphicsMediaItemDelegate *med = dynamic_cast(Delegate()); @@ -268,12 +231,12 @@ void UBGraphicsMediaItem::showOnDisplayChanged(bool shown) if (!shown) { mMuted = true; - mAudioOutput->setMuted(mMuted); + mMediaObject->setMuted(mMuted); } else if (!mMutedByUserAction) { mMuted = false; - mAudioOutput->setMuted(mMuted); + mMediaObject->setMuted(mMuted); } } @@ -357,7 +320,6 @@ void UBGraphicsMediaItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) QPointF eventPos = mapFromScene( event->scenePos()); QPointF translation = eventPos - mouseMovePos; - //translate(translation.x(), translation.y()); setPos(translation.x(), translation.y()); } diff --git a/src/domain/UBGraphicsMediaItem.h b/src/domain/UBGraphicsMediaItem.h index 31ea7175..a0e9bcda 100644 --- a/src/domain/UBGraphicsMediaItem.h +++ b/src/domain/UBGraphicsMediaItem.h @@ -30,9 +30,6 @@ #include #include "UBGraphicsProxyWidget.h" -//#include -//#include -//#include #include #include @@ -73,9 +70,7 @@ public: virtual void mediaFileUrl(QUrl url){mMediaFileUrl=url;} - //Phonon::MediaObject* mediaObject() const QMediaPlayer* mediaObject() const - { return mMediaObject; } @@ -92,9 +87,7 @@ public: return mMuted; } - // Phonon::VideoWidget* videoWidget() const QVideoWidget* videoWidget() const - { return mVideoWidget; } @@ -129,17 +122,8 @@ protected: virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event); virtual void clearSource(); - //Phonon::MediaObject *mMediaObject; - //Phonon::VideoWidget *mVideoWidget; - //Phonon::AudioOutput *mAudioOutput; - //Phonon::MediaSource mSource; - QMediaPlayer *mMediaObject; - QMediaPlaylist *playlist; QVideoWidget *mVideoWidget; -// QAudioOutput *mAudioOutput; - QMediaPlayer *mAudioOutput; - QMediaService *mSource; QWidget *mAudioWidget; diff --git a/src/domain/UBGraphicsMediaItemDelegate.cpp b/src/domain/UBGraphicsMediaItemDelegate.cpp index 0c7c0683..2faeb9b8 100644 --- a/src/domain/UBGraphicsMediaItemDelegate.cpp +++ b/src/domain/UBGraphicsMediaItemDelegate.cpp @@ -252,7 +252,7 @@ void UBGraphicsMediaItemDelegate::togglePlayPause() media->play(); } - else if (media->error()) + if (media->error()) qDebug() << "Error appeared." << media->errorString(); } From 5f9d6b9c699664d5be7e29e2335038d9ac7e5b20 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Mon, 23 Nov 2015 14:48:17 +0100 Subject: [PATCH 023/243] fixed compilation error on Linux due to a bad include --- src/frameworks/UBPlatformUtils_linux.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/frameworks/UBPlatformUtils_linux.cpp b/src/frameworks/UBPlatformUtils_linux.cpp index 17011217..20a68d27 100644 --- a/src/frameworks/UBPlatformUtils_linux.cpp +++ b/src/frameworks/UBPlatformUtils_linux.cpp @@ -31,7 +31,6 @@ #include #include -#include #include #include "frameworks/UBFileSystemUtils.h" From 20ebdf3cc5033dd1cd295798c102f8f0c6446b90 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Tue, 24 Nov 2015 14:09:30 +0100 Subject: [PATCH 024/243] Hide dock and menubar on OSX; Due to QWidget::showFullScreen having side-effects on OSX (setting the dock and menubar to autohide, making it impossible to then set them as hidden), the calls to that method were replaced with UBPlatformUtils::showFullScreen(QWidget *). This function then calls QWidget::showMaximized() on OSX, or QWidget::showFullScreen() on Linux and Windows. It is currently still impossible to switch smoothly between showing or hiding the dock on OSX; current behaviour is to hide it all the time, even in desktop mode. --- src/core/UBDisplayManager.cpp | 10 ++-- src/desktop/UBCustomCaptureWindow.cpp | 3 +- src/desktop/UBDesktopAnnotationController.cpp | 2 +- src/frameworks/UBPlatformUtils.h | 1 + src/frameworks/UBPlatformUtils_linux.cpp | 9 +++- src/frameworks/UBPlatformUtils_mac.mm | 47 ++++++++++++++----- src/frameworks/UBPlatformUtils_win.cpp | 7 +++ 7 files changed, 58 insertions(+), 21 deletions(-) diff --git a/src/core/UBDisplayManager.cpp b/src/core/UBDisplayManager.cpp index 59e858af..21cb706d 100644 --- a/src/core/UBDisplayManager.cpp +++ b/src/core/UBDisplayManager.cpp @@ -158,7 +158,7 @@ void UBDisplayManager::setDisplayWidget(QWidget* pDisplayWidget) mDisplayWidget = pDisplayWidget; mDisplayWidget->setGeometry(mDesktop->screenGeometry(mDisplayScreenIndex)); if (UBSettings::settings()->appUseMultiscreen->get().toBool()) - mDisplayWidget->showFullScreen(); + UBPlatformUtils::showFullScreen(mDisplayWidget); } } @@ -209,14 +209,14 @@ void UBDisplayManager::positionScreens() { mControlWidget->hide(); mControlWidget->setGeometry(mDesktop->screenGeometry(mControlScreenIndex)); - mControlWidget->showFullScreen(); + UBPlatformUtils::showFullScreen(mControlWidget); } if (mDisplayWidget && mDisplayScreenIndex > -1) { mDisplayWidget->hide(); mDisplayWidget->setGeometry(mDesktop->screenGeometry(mDisplayScreenIndex)); - mDisplayWidget->showFullScreen(); + UBPlatformUtils::showFullScreen(mDisplayWidget); } else if(mDisplayWidget) { @@ -234,7 +234,7 @@ void UBDisplayManager::positionScreens() { QWidget* previous = mPreviousDisplayWidgets.at(psi); previous->setGeometry(mDesktop->screenGeometry(mPreviousScreenIndexes.at(psi))); - previous->showFullScreen(); + UBPlatformUtils::showFullScreen(previous); } } @@ -280,7 +280,7 @@ void UBDisplayManager::blackout() foreach(UBBlackoutWidget *blackoutWidget, mBlackoutWidgets) { - blackoutWidget->showFullScreen(); + UBPlatformUtils::showFullScreen(blackoutWidget); } } diff --git a/src/desktop/UBCustomCaptureWindow.cpp b/src/desktop/UBCustomCaptureWindow.cpp index 47eafdbe..36e8969b 100644 --- a/src/desktop/UBCustomCaptureWindow.cpp +++ b/src/desktop/UBCustomCaptureWindow.cpp @@ -30,6 +30,7 @@ #include "UBCustomCaptureWindow.h" +#include "frameworks/UBPlatformUtils.h" #include "gui/UBRubberBand.h" #include "core/memcheck.h" @@ -74,7 +75,7 @@ int UBCustomCaptureWindow::execute(const QPixmap &pScreenPixmap) int currentScreen = desktop->screenNumber(QCursor::pos()); setGeometry(desktop->screenGeometry(currentScreen)); - showFullScreen(); + UBPlatformUtils::showFullScreen(this); setWindowOpacity(1.0); return exec(); diff --git a/src/desktop/UBDesktopAnnotationController.cpp b/src/desktop/UBDesktopAnnotationController.cpp index 330093fe..879b39e4 100644 --- a/src/desktop/UBDesktopAnnotationController.cpp +++ b/src/desktop/UBDesktopAnnotationController.cpp @@ -332,7 +332,7 @@ void UBDesktopAnnotationController::showWindow() UBDrawingController::drawingController()->setStylusTool(mDesktopStylusTool); #ifndef Q_OS_LINUX - mTransparentDrawingView->showFullScreen(); + UBPlatformUtils::showFullScreen(mTransparentDrawingView); #else // this is necessary to avoid unity to hide the panels mTransparentDrawingView->show(); diff --git a/src/frameworks/UBPlatformUtils.h b/src/frameworks/UBPlatformUtils.h index e0b3f4ff..0b28c7dd 100644 --- a/src/frameworks/UBPlatformUtils.h +++ b/src/frameworks/UBPlatformUtils.h @@ -204,6 +204,7 @@ public: static QString urlFromClipboard(); static QStringList availableTranslations(); static void setFrontProcess(); + static void showFullScreen(QWidget * pWidget); #ifdef Q_OS_OSX static void SetMacLocaleByIdentifier(const QString& id); diff --git a/src/frameworks/UBPlatformUtils_linux.cpp b/src/frameworks/UBPlatformUtils_linux.cpp index 20a68d27..d4b4f690 100644 --- a/src/frameworks/UBPlatformUtils_linux.cpp +++ b/src/frameworks/UBPlatformUtils_linux.cpp @@ -429,7 +429,14 @@ QString UBPlatformUtils::urlFromClipboard() return qsRet; } - void UBPlatformUtils::setFrontProcess() { + // not used in Linux +} + + +void UBPlatformUtils::showFullScreen(QWidget *pWidget) +{ + pWidget->showFullScreen(); } + diff --git a/src/frameworks/UBPlatformUtils_mac.mm b/src/frameworks/UBPlatformUtils_mac.mm index 531e6fd0..17b87548 100644 --- a/src/frameworks/UBPlatformUtils_mac.mm +++ b/src/frameworks/UBPlatformUtils_mac.mm @@ -65,7 +65,7 @@ void UBPlatformUtils::init() //originalSetSystemUIMode = APEPatchCreate((const void *)SetSystemUIMode, (const void *)emptySetSystemUIMode); - setDesktopMode(false); + //setDesktopMode(false); NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; @@ -93,20 +93,24 @@ void UBPlatformUtils::init() void UBPlatformUtils::setDesktopMode(bool desktop) -{ /* -#ifndef OS_NEWER_THAN_OR_EQUAL_TO_1010 - //OSStatus (*functor)(SystemUIMode, SystemUIOptions) = (OSStatus (*)(SystemUIMode, SystemUIOptions))originalSetSystemUIMode; +{ - if (desktop) - { - functor(kUIModeNormal, 0); + //qDebug() << "setDesktopMode called. desktop = " << desktop; + + @try { + // temporarily disabled due to bug: when switching to desktop mode (and calling this), + // openboard switches right back to the board mode. clicking again on desktop mode works. + /*if (desktop) { + [NSApp setPresentationOptions:NSApplicationPresentationAutoHideMenuBar | NSApplicationPresentationAutoHideDock]; + } + else*/ + [NSApp setPresentationOptions:NSApplicationPresentationHideMenuBar | NSApplicationPresentationHideDock]; } - else - { - functor(kUIModeAllHidden, 0); + + @catch(NSException * exception) { + qDebug() << "Error setting presentation options"; } -#endif -*/ + } @@ -574,6 +578,23 @@ void UBPlatformUtils::setFrontProcess() // activate the application, forcing focus on it [app activateWithOptions: NSApplicationActivateIgnoringOtherApps]; - // other option:NSApplicationActivateAllWindows. This won't steal focus from another app, e.g + // other option: NSApplicationActivateAllWindows. This won't steal focus from another app, e.g // if the user is doing something else while waiting for OpenBoard to load } + + +/** + * @brief Full-screen a QWidget. Specific behaviour is platform-dependent. + * @param pWidget the QWidget to maximize + */ +void UBPlatformUtils::showFullScreen(QWidget *pWidget) +{ + pWidget->showMaximized(); + + /* On OS X, we want to hide the Dock and menu bar (aka "kiosk mode"). Qt's default behaviour + * when full-screening a QWidget is to set the dock and menu bar to auto-hide. + * Since it is impossible to later set different presentation options (i.e Hide dock & menu bar) + * to NSApplication, we have to avoid calling QWidget::showFullScreen on OSX. + */ +} + diff --git a/src/frameworks/UBPlatformUtils_win.cpp b/src/frameworks/UBPlatformUtils_win.cpp index ed698a39..1c1f453f 100644 --- a/src/frameworks/UBPlatformUtils_win.cpp +++ b/src/frameworks/UBPlatformUtils_win.cpp @@ -427,4 +427,11 @@ QString UBPlatformUtils::urlFromClipboard() void UBPlatformUtils::setFrontProcess() { + // not used in Windows +} + + +void UBPlatformUtils::showFullScreen(QWidget *pWidget) +{ + pWidget->showFullScreen(); } From 691eb2a8b30831790b0b82abb786b873e5b116d6 Mon Sep 17 00:00:00 2001 From: agriche Date: Tue, 24 Nov 2015 15:32:41 +0100 Subject: [PATCH 025/243] - Modify all paint buttons (close,reset,rotate,mark,resize buttons). --- src/tools/UBGraphicsProtractor.cpp | 219 +++++++++++++++++++++++------ src/tools/UBGraphicsProtractor.h | 13 +- 2 files changed, 189 insertions(+), 43 deletions(-) diff --git a/src/tools/UBGraphicsProtractor.cpp b/src/tools/UBGraphicsProtractor.cpp index 05b84257..eb9659fd 100644 --- a/src/tools/UBGraphicsProtractor.cpp +++ b/src/tools/UBGraphicsProtractor.cpp @@ -35,6 +35,10 @@ #include "core/memcheck.h" +#include + +//#include + const QRectF UBGraphicsProtractor::sDefaultRect = QRectF(-175, -175, 350, 350); @@ -78,7 +82,9 @@ UBGraphicsProtractor::UBGraphicsProtractor() setData(UBGraphicsItemData::itemLayerType, QVariant(itemLayerType::CppTool)); //Necessary to set if we want z value to be assigned correctly setFlag(QGraphicsItem::ItemIsSelectable, false); - setTransform(QTransform::fromScale(1.5, 1.5), true); + setScale(1.5); + + } @@ -181,7 +187,6 @@ void UBGraphicsProtractor::mousePressEvent(QGraphicsSceneMouseEvent *event) event->accept(); } - void UBGraphicsProtractor::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { QPointF currentPoint = event->pos(); @@ -190,6 +195,13 @@ void UBGraphicsProtractor::mouseMoveEvent(QGraphicsSceneMouseEvent *event) qreal angle = startLine.angleTo(currentLine); qreal scaleFactor = currentLine.length()/startLine.length(); + qreal mod_angle = 0; + if (angle>350) + { + mod_angle= angle - 360; // only for debugging + angle= angle - 360; + } + switch (mCurrentTool) { case Rotate : @@ -197,14 +209,18 @@ void UBGraphicsProtractor::mouseMoveEvent(QGraphicsSceneMouseEvent *event) mStartAngle = mStartAngle + angle; setStartAngle(mStartAngle * 16); mPreviousMousePos = currentPoint; + + //qDebug() << "UBGraphicsProtractor Rotate"<<"mStartAngle= "<setPos(pos_close_x,pos_close_y); + mCloseSvgItem->resetTransform(); - mCloseSvgItem->setTransform(QTransform::fromTranslate(-closeButtonRect().left(),-closeButtonRect().top()), true); - mCloseSvgItem->setRotation(rotation() -mStartAngle); - mCloseSvgItem->setTransform(QTransform::fromTranslate(closeButtonRect().left(), closeButtonRect().top()), true); - mCloseSvgItem->setTransform(QTransform::fromScale(scale * antiSc, scale * antiSc), true);//this do not impact the bounding box of thr svg item... + //mCloseSvgItem->translate(-closeButtonRect().left(),-closeButtonRect().top()); -- + mCloseSvgItem->setPos(-pos_close_x,-pos_close_y); + //mCloseSvgItem->setPos(-closeButtonRect().left(),-closeButtonRect().top()); + //mCloseSvgItem->rotate(-mStartAngle); -- + mCloseSvgItem->setRotation(rotation() - mStartAngle); + //mCloseSvgItem->translate(closeButtonRect().left(), closeButtonRect().top()); -- + mCloseSvgItem->setPos(pos_close_x, pos_close_y); + + //mCloseSvgItem->setPos(closeButtonRect().left(), closeButtonRect().top()); + //mCloseSvgItem->scale(scale * antiSc, scale * antiSc);//this do not impact the bounding box of thr svg item... + mCloseSvgItem->setScale(scale );//this do not impact the bounding box of thr svg item... + - mResetSvgItem->setPos(resetButtonRect().topLeft() + rect().center()); + // Determine and apply the position on the reset button object. + //------------------------------------------------------------ + qreal pos_reset_x = resetButtonRect().topLeft().x()* co; + qreal pos_reset_y = qAbs(resetButtonRect().topLeft().x()) * si + resetButtonRect().topLeft().y(); + + mResetSvgItem->setPos(pos_reset_x,pos_reset_y); + + //mResetSvgItem->setPos(resetButtonRect().topLeft() + rect().center()); mResetSvgItem->resetTransform(); - mResetSvgItem->setTransform(QTransform::fromTranslate(-resetButtonRect().left(), -resetButtonRect().top()), true); - mResetSvgItem->setRotation(rotation() -mStartAngle); - mResetSvgItem->setTransform(QTransform::fromTranslate(resetButtonRect().left(), resetButtonRect().top()), true); - mResetSvgItem->setTransform(QTransform::fromScale(scale * antiSc, scale * antiSc), true);//this do not impact the bounding box of thr svg item... + //mResetSvgItem->translate(-resetButtonRect().left(), -resetButtonRect().top());-- + mResetSvgItem->setPos(-pos_reset_x, -pos_reset_y); + + //mResetSvgItem->rotate(-mStartAngle);-- + mResetSvgItem->setRotation(-mStartAngle); + + //mResetSvgItem->translate(resetButtonRect().left(), resetButtonRect().top());-- + mResetSvgItem->setPos(pos_reset_x, pos_reset_y); + + //mResetSvgItem->scale(scale * antiSc, scale * antiSc);//this do not impact the bounding box of thr svg item... + mResetSvgItem->setScale(scale );//this do not impact the bounding box of thr svg item... + + + // Determine and apply the position on the resize button object. + //------------------------------------------------------------ + + qreal pos_resize_x = resizeButtonRect().topLeft().x()* co; + qreal pos_resize_y = -(resizeButtonRect().topLeft().x()) * si + resizeButtonRect().topLeft().y(); + + qDebug() << "pos_resize_x ="<setPos(resizeButtonRect().topLeft() + rect().center()); + // mResizeSvgItem->setPos(resizeButtonRect().topLeft() + rect().center()); + mResizeSvgItem->setPos(pos_resize_x,pos_resize_y); mResizeSvgItem->resetTransform(); - mResizeSvgItem->setTransform(QTransform::fromTranslate(-resizeButtonRect().left(), -resizeButtonRect().top()), true); - mResizeSvgItem->setRotation(rotation() -mStartAngle); - mResizeSvgItem->setTransform(QTransform::fromTranslate(resizeButtonRect().left(), resizeButtonRect().top()), true); - mResizeSvgItem->setTransform(QTransform::fromScale(scale * antiSc, scale * antiSc), true);//this do not impact the bounding box of thr svg item... + mResizeSvgItem->setPos(-pos_resize_x, -pos_resize_y); + //mResizeSvgItem->rotate(-mStartAngle);-- + mResizeSvgItem->setRotation(-mStartAngle); - mRotateSvgItem->setPos(rotateButtonRect().topLeft() + rect().center()); + //mResizeSvgItem->translate(-resizeButtonRect().left(), -resizeButtonRect().top());-- + mResizeSvgItem->setPos(pos_resize_x, pos_resize_y); + // mResizeSvgItem->scale(scale * antiSc, scale * antiSc);//this do not impact the bounding box of thr svg item... + mResizeSvgItem->setScale(scale);//this do not impact the bounding box of thr svg item... + + // Determine and apply the position on the rotate button object. + //-------------------------------------------------------------- + qreal qPow_x = qPow(rotateButtonRect().topLeft().x(),2); + qreal qPow_y = qPow(rotateButtonRect().topLeft().y(),2); + qreal module_rotate_pos = qSqrt(qPow_x + qPow_y); + + qreal arg_rotate_pos = (qAtan2(rotateButtonRect().topLeft().y(), rotateButtonRect().topLeft().x())); //argument in radian + qreal co_r = cos(-mStartAngle * PI/180 + arg_rotate_pos); // cos(rad) + qreal si_r = sin(-mStartAngle * PI/180 + arg_rotate_pos); //sin(rad) + + + qreal pos_rotate_x = (module_rotate_pos * co_r) ; + qreal pos_rotate_y = (module_rotate_pos * si_r) ; + + mRotateSvgItem->setPos(pos_rotate_x,pos_rotate_y); + //mRotateSvgItem->setPos(rotateButtonRect().topLeft() + rect().center()); -- mRotateSvgItem->resetTransform(); - mRotateSvgItem->setTransform(QTransform::fromTranslate(-rotateButtonRect().left(), -rotateButtonRect().top()), true); - mRotateSvgItem->setRotation(rotation() -mStartAngle); - mRotateSvgItem->setTransform(QTransform::fromTranslate(rotateButtonRect().left(), rotateButtonRect().top()), true); - mRotateSvgItem->setTransform(QTransform::fromScale(scale, scale), true);//this do not impact the bounding box of thr svg item... + mRotateSvgItem->setPos(-pos_rotate_x, -pos_rotate_y); + //mRotateSvgItem->rotate(-mStartAngle);-- + mRotateSvgItem->setRotation(-mStartAngle); + + mRotateSvgItem->setPos(pos_rotate_x, pos_rotate_y); + //mRotateSvgItem->scale(scale, scale);//this do not impact the bounding box of thr svg item... + mRotateSvgItem->setScale(scale);//this do not impact the bounding box of thr svg item... + + //qDebug()<<"UBGraphicsProtractor scale()"<<"scale ="<boundingRect().height() * radius()/(10 * mCloseSvgItem->boundingRect().width()));} QSizeF markerSizeReference () const{return QSizeF(radius() / 10, mMarkerSvgItem->boundingRect().height() * radius()/(10 * mMarkerSvgItem->boundingRect().width()));} QRectF resetButtonRect () const; + QRectF closeButtonRect () const; QRectF resizeButtonRect () const; QRectF rotateButtonRect () const{return QRectF(buttonSizeReference().width() * 5.5, -buttonSizeReference().width() * 5, buttonSizeReference().width(), buttonSizeReference().width());} From 8b6a9279d359efd25f64b789064f3cb3c372a718 Mon Sep 17 00:00:00 2001 From: agriche Date: Thu, 26 Nov 2015 08:52:07 +0100 Subject: [PATCH 026/243] - Bypass the boundRect() method at each resizepolygon. --- src/tools/UBGraphicsTriangle.cpp | 42 ++++++++++++++++++++++++++++++-- src/tools/UBGraphicsTriangle.h | 19 ++++++++++++--- 2 files changed, 56 insertions(+), 5 deletions(-) diff --git a/src/tools/UBGraphicsTriangle.cpp b/src/tools/UBGraphicsTriangle.cpp index c18c90a3..8c2e80c8 100644 --- a/src/tools/UBGraphicsTriangle.cpp +++ b/src/tools/UBGraphicsTriangle.cpp @@ -25,8 +25,10 @@ -#include +//#include + #include +#include #include "tools/UBGraphicsTriangle.h" #include "core/UBApplication.h" @@ -131,19 +133,38 @@ void UBGraphicsTriangle::setRect(qreal x, qreal y, qreal w, qreal h, UBGraphicsT polygon << QPointF(x, y) << QPoint(x, y + h) << QPoint(x+w, y + h); setPolygon(polygon); + // Save the bounds rect + bounds_rect.setX(x); bounds_rect.setY(y); bounds_rect.setWidth(w); bounds_rect.setHeight(h); + setOrientation(orientation); } void UBGraphicsTriangle::setOrientation(UBGraphicsTriangleOrientation orientation) { mOrientation = orientation; - calculatePoints(boundingRect()); + + //calculatePoints(boundingRect()); + calculatePoints(bounds_rect); QPolygonF polygon; polygon << A1 << B1 << C1; setPolygon(polygon); } + +QRectF UBGraphicsTriangle::bounding_Rect() const +{ + + QRectF bounds = QRectF(0,0,0,0); + bounds.setX(bounds_rect.x()); + bounds.setY(bounds_rect.y()); + bounds.setWidth(bounds_rect.width()); + bounds.setHeight(bounds_rect.height()); + + + return bounds; +} + UBGraphicsScene* UBGraphicsTriangle::scene() const { return static_cast(QGraphicsPolygonItem::scene()); @@ -151,6 +172,8 @@ UBGraphicsScene* UBGraphicsTriangle::scene() const void UBGraphicsTriangle::calculatePoints(const QRectF& r) { + //qDebug() << "UBGraphicsTriangle calculatePoints()"<<"r ="<setTransform(antiScaleTransform); mCloseSvgItem->setPos(closeButtonRect().topLeft()); + + qDebug() << "UBGraphicsTriangle Paint"<<"closeButtonRect().topLeft()=" + <setPos(hFlipRect().topLeft()); mVFlipSvgItem->setPos(vFlipRect().topLeft()); mRotateSvgItem->setPos(rotateRect().topLeft()); @@ -289,6 +316,8 @@ void UBGraphicsTriangle::paint(QPainter *painter, const QStyleOptionGraphicsItem if (mShowButtons || mResizing2) painter->drawPolygon(resize2Polygon()); } + + } QPainterPath UBGraphicsTriangle::shape() const @@ -296,6 +325,8 @@ QPainterPath UBGraphicsTriangle::shape() const QPainterPath tShape; QPolygonF tPolygon; + qDebug() << "UBGraphicsTriangle shape()"<<"A1 ="< Date: Thu, 26 Nov 2015 14:43:32 +0100 Subject: [PATCH 027/243] Audio recording for podcasts on OSX Re-coded this feature (which had been temporarily removed due to the old code being reliant on the obsolete QuickTime library). --- .../quicktime/UBAudioQueueRecorder.cpp | 41 +++-- src/podcast/quicktime/UBAudioQueueRecorder.h | 22 ++- src/podcast/quicktime/UBQuickTimeFile.h | 39 ++-- src/podcast/quicktime/UBQuickTimeFile.mm | 172 ++++++++++++++++-- 4 files changed, 219 insertions(+), 55 deletions(-) diff --git a/src/podcast/quicktime/UBAudioQueueRecorder.cpp b/src/podcast/quicktime/UBAudioQueueRecorder.cpp index 43c106f2..b1354149 100644 --- a/src/podcast/quicktime/UBAudioQueueRecorder.cpp +++ b/src/podcast/quicktime/UBAudioQueueRecorder.cpp @@ -37,15 +37,22 @@ UBAudioQueueRecorder::UBAudioQueueRecorder(QObject* pParent) , mIsRecording(false) , mBufferLengthInMs(500) { + + int sampleSize = sizeof(float); // TODO: check if this is system/ microphone-dependant + sAudioFormat.mSampleRate = 44100.0; - sAudioFormat.mFormatID = kAudioFormatMPEG4AAC; - sAudioFormat.mChannelsPerFrame = 2; - - sAudioFormat.mBytesPerFrame = 0; - sAudioFormat.mBitsPerChannel = 0; - sAudioFormat.mBytesPerPacket = 0; - sAudioFormat.mFramesPerPacket = 0; - sAudioFormat.mFormatFlags = 0; + sAudioFormat.mFormatID = kAudioFormatLinearPCM; + sAudioFormat.mChannelsPerFrame = 1; + + sAudioFormat.mBytesPerFrame = sampleSize; + sAudioFormat.mBitsPerChannel = 8 * sampleSize; + sAudioFormat.mBytesPerPacket = sampleSize; + sAudioFormat.mFramesPerPacket = 1; + sAudioFormat.mFormatFlags = kAudioFormatFlagIsFloat | + kAudioFormatFlagsNativeEndian | + kAudioFormatFlagIsPacked; + + } @@ -250,7 +257,7 @@ bool UBAudioQueueRecorder::init(const QString& waveInDeviceName) int nbBuffers = 6; mSampleBufferSize = sAudioFormat.mSampleRate * sAudioFormat.mChannelsPerFrame - * 2 * mBufferLengthInMs / 1000; // 44.1 Khz * stereo * 16bit * buffer length + * sAudioFormat.mChannelsPerFrame * mBufferLengthInMs / 1000; // 44.1 Khz * stereo * 16bit * buffer length for (int i = 0; i < nbBuffers; i++) { @@ -333,9 +340,12 @@ bool UBAudioQueueRecorder::close() } -void UBAudioQueueRecorder::audioQueueInputCallback (void *inUserData, AudioQueueRef inAQ, - AudioQueueBufferRef inBuffer, const AudioTimeStamp *inStartTime, - UInt32 inNumberPacketDescriptions, const AudioStreamPacketDescription *inPacketDescs) +void UBAudioQueueRecorder::audioQueueInputCallback (void *inUserData, + AudioQueueRef inAQ, + AudioQueueBufferRef inBuffer, + const AudioTimeStamp *inStartTime, + UInt32 inNumberPacketDescriptions, + const AudioStreamPacketDescription *inPacketDescs) { Q_UNUSED(inAQ); Q_UNUSED(inStartTime) @@ -356,12 +366,11 @@ void UBAudioQueueRecorder::audioQueueInputCallback (void *inUserData, AudioQueue void UBAudioQueueRecorder::emitNewWaveBuffer(AudioQueueBufferRef pBuffer, - int inNumberPacketDescriptions, const AudioStreamPacketDescription *inPacketDescs) + int inNumberPacketDescriptions, + const AudioStreamPacketDescription *inPacketDescs) { - AudioStreamPacketDescription* tmpPackages = (AudioStreamPacketDescription*)malloc(inNumberPacketDescriptions *sizeof(AudioStreamPacketDescription)); - memcpy(tmpPackages,inPacketDescs,inNumberPacketDescriptions * sizeof(AudioStreamPacketDescription)); - emit newWaveBuffer(pBuffer->mAudioData, pBuffer->mAudioDataByteSize, inNumberPacketDescriptions, tmpPackages); + emit newWaveBuffer(pBuffer->mAudioData, pBuffer->mAudioDataByteSize); qreal level = 0; UInt32 size; diff --git a/src/podcast/quicktime/UBAudioQueueRecorder.h b/src/podcast/quicktime/UBAudioQueueRecorder.h index 8027c9e9..0443ce7a 100644 --- a/src/podcast/quicktime/UBAudioQueueRecorder.h +++ b/src/podcast/quicktime/UBAudioQueueRecorder.h @@ -57,23 +57,29 @@ class UBAudioQueueRecorder : public QObject return mLastErrorMessage; } - static AudioStreamBasicDescription audioFormat() + AudioStreamBasicDescription * audioFormat() { - return sAudioFormat; + return &sAudioFormat; } signals: - void newWaveBuffer(void* pBuffer, long pLength, int inNumberPacketDescriptions, const AudioStreamPacketDescription *inPacketDescs); + void newWaveBuffer(void* pBuffer, + long pLength); void audioLevelChanged(quint8 level); private: - static void audioQueueInputCallback (void *inUserData, AudioQueueRef inAQ, - AudioQueueBufferRef inBuffer, const AudioTimeStamp *inStartTime, - UInt32 inNumberPacketDescriptions, const AudioStreamPacketDescription *inPacketDescs); - - void emitNewWaveBuffer(AudioQueueBufferRef pBuffer, int inNumberPacketDescriptions, const AudioStreamPacketDescription *inPacketDescs); + static void audioQueueInputCallback (void *inUserData, + AudioQueueRef inAQ, + AudioQueueBufferRef inBuffer, + const AudioTimeStamp *inStartTime, + UInt32 inNumberPacketDescriptions, + const AudioStreamPacketDescription *inPacketDescs); + + void emitNewWaveBuffer(AudioQueueBufferRef pBuffer, + int inNumberPacketDescriptions, + const AudioStreamPacketDescription *inPacketDescs); void emitAudioLevelChanged(quint8 level); diff --git a/src/podcast/quicktime/UBQuickTimeFile.h b/src/podcast/quicktime/UBQuickTimeFile.h index 1d1efd70..413ddffe 100644 --- a/src/podcast/quicktime/UBQuickTimeFile.h +++ b/src/podcast/quicktime/UBQuickTimeFile.h @@ -31,6 +31,7 @@ #include #include +#include #include "UBAudioQueueRecorder.h" @@ -92,40 +93,50 @@ class UBQuickTimeFile : public QThread protected: void run(); + private slots: + void appendAudioBuffer(void* pBuffer, long pLength); private: bool beginSession(); - - void appendVideoFrame(CVPixelBufferRef pixelBuffer, long msTimeStamp); - void setLastErrorMessage(const QString& error); - bool flushPendingFrames(); - volatile CVPixelBufferPoolRef mCVPixelBufferPool; + void appendVideoFrame(CVPixelBufferRef pixelBuffer, long msTimeStamp); + bool flushPendingFrames(); + + volatile bool mShouldStopCompression; + volatile bool mCompressionSessionRunning; + volatile int mPendingFrames; + QString mSpatialQuality; + int mFramesPerSecond; QSize mFrameSize; QString mVideoFileName; - long mTimeScale; bool mRecordAudio; + + + AssetWriterPTR mVideoWriter; - QString mLastErrorMessage; + AssetWriterInputPTR mVideoWriterInput; + AssetWriterInputAdaptorPTR mAdaptor; - QString mSpatialQuality; + AssetWriterInputPTR mAudioWriterInput; - volatile bool mShouldStopCompression; - volatile bool mCompressionSessionRunning; + QPointer mWaveRecorder; + CFAbsoluteTime mStartTime; + + CMAudioFormatDescriptionRef mAudioFormatDescription; + + long mTimeScale; + + QString mLastErrorMessage; QString mAudioRecordingDeviceName; - volatile int mPendingFrames; - AssetWriterPTR mVideoWriter; - AssetWriterInputPTR mVideoWriterInput; - AssetWriterInputAdaptorPTR mAdaptor; }; #endif /* UBQUICKTIMEFILE_H_ */ diff --git a/src/podcast/quicktime/UBQuickTimeFile.mm b/src/podcast/quicktime/UBQuickTimeFile.mm index e6e18d72..4893e97c 100644 --- a/src/podcast/quicktime/UBQuickTimeFile.mm +++ b/src/podcast/quicktime/UBQuickTimeFile.mm @@ -47,21 +47,20 @@ UBQuickTimeFile::UBQuickTimeFile(QObject * pParent) , mVideoWriter(0) , mVideoWriterInput(0) , mAdaptor(0) - , mCVPixelBufferPool(0) , mFramesPerSecond(-1) - , mTimeScale(100) + , mTimeScale(1000) , mRecordAudio(true) , mShouldStopCompression(false) , mCompressionSessionRunning(false) , mPendingFrames(0) { - // NOOP } UBQuickTimeFile::~UBQuickTimeFile() { - // NOOP + // destruction of mWaveRecorder is handled by endSession() + } bool UBQuickTimeFile::init(const QString& pVideoFileName, const QString& pProfileData, int pFramesPerSecond @@ -126,7 +125,11 @@ void UBQuickTimeFile::run() } /** - * \brief Initialize the AVAssetWriter, which handles writing the media to file + * \brief Begin the recording session; initialize the audio/video writer + * \return true if the session was initialized successfully + * + * This function initializes the AVAssetWriter and associated video and audio inputs. + * Video is encoded as H264; audio is encoded as AAC. */ bool UBQuickTimeFile::beginSession() { @@ -141,12 +144,17 @@ bool UBQuickTimeFile::beginSession() // Create and check the assetWriter mVideoWriter = [[AVAssetWriter assetWriterWithURL:outputUrl - fileType:AVFileTypeQuickTimeMovie - error:&outError] retain]; + fileType:AVFileTypeQuickTimeMovie + error:&outError] retain]; NSCParameterAssert(mVideoWriter); mVideoWriter.movieTimeScale = mTimeScale; + + + // Video + // + int frameWidth = mFrameSize.width(); int frameHeight = mFrameSize.height(); @@ -175,18 +183,72 @@ bool UBQuickTimeFile::beginSession() assetWriterInputPixelBufferAdaptorWithAssetWriterInput:mVideoWriterInput sourcePixelBufferAttributes:pixelBufSettings] retain]; - - - // Add the input(s) to the assetWriter NSCParameterAssert([mVideoWriter canAddInput:mVideoWriterInput]); [mVideoWriter addInput:mVideoWriterInput]; - // begin the writing session + + // Audio + // + + if(mRecordAudio) { + mWaveRecorder = new UBAudioQueueRecorder(); + + // Get the audio format description from mWaveRecorder + CMAudioFormatDescriptionCreate(kCFAllocatorDefault, mWaveRecorder->audioFormat(), + 0, NULL, 0, NULL, NULL, + &mAudioFormatDescription); + + if(mWaveRecorder->init(mAudioRecordingDeviceName)) { + connect(mWaveRecorder, &UBAudioQueueRecorder::newWaveBuffer, + this, &UBQuickTimeFile::appendAudioBuffer); + + connect(mWaveRecorder, SIGNAL(audioLevelChanged(quint8)), + this, SIGNAL(audioLevelChanged(quint8))); + } + else { + setLastErrorMessage(mWaveRecorder->lastErrorMessage()); + mWaveRecorder->deleteLater(); + mRecordAudio = false; + break; + } + + // Audio is mono, and compressed to AAC at 128kbps + + AudioChannelLayout audioChannelLayout = { + .mChannelLayoutTag = kAudioChannelLayoutTag_Mono, + .mChannelBitmap = 0, + .mNumberChannelDescriptions = 0 + }; + + NSData *channelLayoutAsData = [NSData dataWithBytes:&audioChannelLayout + length:offsetof(AudioChannelLayout, mChannelDescriptions)]; + + NSDictionary * compressionAudioSettings = @{ + AVFormatIDKey : [NSNumber numberWithUnsignedInt:kAudioFormatMPEG4AAC], + AVEncoderBitRateKey : [NSNumber numberWithInteger:128000], + AVSampleRateKey : [NSNumber numberWithInteger:44100], + AVChannelLayoutKey : channelLayoutAsData, + AVNumberOfChannelsKey : [NSNumber numberWithUnsignedInteger:1] + }; + + mAudioWriterInput = [[AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio + outputSettings:compressionAudioSettings] retain]; + + NSCParameterAssert([mVideoWriter canAddInput:mAudioWriterInput]); + [mVideoWriter addInput:mAudioWriterInput]; + + qDebug() << "audio writer input created and added"; + } + + + // Begin the writing session bool canStartWriting = [mVideoWriter startWriting]; [mVideoWriter startSessionAtSourceTime:CMTimeMake(0, mTimeScale)]; - // return true if everything was created and started successfully + mStartTime = CFAbsoluteTimeGetCurrent(); // used for audio timestamp calculation + + return (mVideoWriter != nil) && (mVideoWriterInput != nil) && canStartWriting; } @@ -201,10 +263,18 @@ void UBQuickTimeFile::endSession() [mAdaptor release]; [mVideoWriterInput release]; [mVideoWriter release]; + [mAudioWriterInput release]; mAdaptor = nil; mVideoWriterInput = nil; mVideoWriter = nil; + mAudioWriterInput = nil; + + if (mWaveRecorder) { + mWaveRecorder->close(); + mWaveRecorder->deleteLater(); + } + } /** @@ -235,11 +305,11 @@ CVPixelBufferRef UBQuickTimeFile::newPixelBuffer() /** * \brief Add a frame to the pixel buffer adaptor + * \param pixelBuffer The CVPixelBufferRef (video frame) to add to the movie + * \param msTimeStamp Timestamp, in milliseconds, of the frame */ void UBQuickTimeFile::appendVideoFrame(CVPixelBufferRef pixelBuffer, long msTimeStamp) { - //qDebug() << "adding video frame at time: " << msTimeStamp; - CMTime t = CMTimeMake((msTimeStamp * mTimeScale / 1000.0), mTimeScale); bool added = [mAdaptor appendPixelBuffer: pixelBuffer @@ -252,11 +322,79 @@ void UBQuickTimeFile::appendVideoFrame(CVPixelBufferRef pixelBuffer, long msTime CVPixelBufferRelease(pixelBuffer); } + + + +/** + * \brief Append an AudioQueue Buffer to the audio AVAssetWriterInput + * \param pBuffer The AudioQueueBufferRef to add. Must be uncompressed (LPCM). + * \param pLength The length of the buffer, in Bytes + * + * This function serves as an interface between the low-level audio stream + * (implemented in the UBAudioQueueRecorder class) and the recording, handled + * by the AVAssetWriterInput instance mAudioWriterInput. + */ +void UBQuickTimeFile::appendAudioBuffer(void* pBuffer, + long pLength) +{ + if(!mRecordAudio) + return; + + + // CMSampleBuffers require a CMBlockBuffer to hold the media data; we + // create a blockBuffer here from the AudioQueueBuffer's data. + CMBlockBufferRef blockBuffer; + CMBlockBufferCreateWithMemoryBlock(kCFAllocatorDefault, + pBuffer, + pLength, + kCFAllocatorNull, + NULL, + 0, + pLength, + kCMBlockBufferAssureMemoryNowFlag, + &blockBuffer); + + + // Timestamp of current sample + CFAbsoluteTime currentTime = CFAbsoluteTimeGetCurrent(); + CFTimeInterval elapsedTime = currentTime - mStartTime; + CMTime timeStamp = CMTimeMake(elapsedTime * mTimeScale, mTimeScale); + + // Number of samples in the buffer + long nSamples = pLength / mWaveRecorder->audioFormat()->mBytesPerFrame; + + CMSampleBufferRef sampleBuffer; + CMAudioSampleBufferCreateWithPacketDescriptions(kCFAllocatorDefault, + blockBuffer, + true, + NULL, + NULL, + mAudioFormatDescription, + nSamples, + timeStamp, + NULL, + &sampleBuffer); + + + // Add the audio sample to the asset writer input + if ([mAudioWriterInput isReadyForMoreMediaData]) + if(![mAudioWriterInput appendSampleBuffer:sampleBuffer]) + setLastErrorMessage(QString("Failed to append sample buffer to audio input: %1").arg(err)); + + else + setLastErrorMessage(QString("Audio Writer not ready; sample dropped")); + + + CFRelease(sampleBuffer); + CFRelease(blockBuffer); + // The audioQueueBuffers are all freed when UBAudioQueueRecorder::close() is called +} + +/** + * \brief Print an error message to the terminal, and store it + */ void UBQuickTimeFile::setLastErrorMessage(const QString& error) { mLastErrorMessage = error; qWarning() << "UBQuickTimeFile error" << error; } - - - From b40f52c48712cf7acf1edf07e7d7e3a81936891a Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Thu, 26 Nov 2015 14:54:26 +0100 Subject: [PATCH 028/243] Fixed compilation error on previous commit (8a9ae) Forgot to remove a couple of things when cleaning up the code for the previous commit --- src/podcast/quicktime/UBQuickTimeFile.mm | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/podcast/quicktime/UBQuickTimeFile.mm b/src/podcast/quicktime/UBQuickTimeFile.mm index 4893e97c..50007556 100644 --- a/src/podcast/quicktime/UBQuickTimeFile.mm +++ b/src/podcast/quicktime/UBQuickTimeFile.mm @@ -210,7 +210,6 @@ bool UBQuickTimeFile::beginSession() setLastErrorMessage(mWaveRecorder->lastErrorMessage()); mWaveRecorder->deleteLater(); mRecordAudio = false; - break; } // Audio is mono, and compressed to AAC at 128kbps @@ -379,7 +378,7 @@ void UBQuickTimeFile::appendAudioBuffer(void* pBuffer, // Add the audio sample to the asset writer input if ([mAudioWriterInput isReadyForMoreMediaData]) if(![mAudioWriterInput appendSampleBuffer:sampleBuffer]) - setLastErrorMessage(QString("Failed to append sample buffer to audio input: %1").arg(err)); + setLastErrorMessage(QString("Failed to append sample buffer to audio input")); else setLastErrorMessage(QString("Audio Writer not ready; sample dropped")); From 2c83c5e479799d82d4ffef9dde3a19a0c3c06923 Mon Sep 17 00:00:00 2001 From: agriche Date: Thu, 26 Nov 2015 15:14:30 +0100 Subject: [PATCH 029/243] - Update the mhttp variable. --- src/core/UBApplicationController.h | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/core/UBApplicationController.h b/src/core/UBApplicationController.h index bca300b7..9db9a130 100644 --- a/src/core/UBApplicationController.h +++ b/src/core/UBApplicationController.h @@ -31,6 +31,18 @@ //#include #include + +#include +//#include +//#include +#include + + +#include +#include +#include + + class UBBoardView; class UBDocumentProxy; class UBGraphicsScene; @@ -42,9 +54,13 @@ class UBVersion; class UBSoftwareUpdate; class QNetworkAccessManager; class QNetworkReply; -class QHttp; +class QHttpPart; +//class QHttp; class UBRightPalette; class UBOpenSankoreImporter; +class QScriptValue; +class QScriptEngine; +class QNetworkReply; class UBApplicationController : public QObject { @@ -144,8 +160,9 @@ class UBApplicationController : public QObject void checkAtLaunch(); private slots: - void updateRequestFinished(QNetworkReply * reply); - + void updateRequestFinished(int id, bool error); + //void updateHeaderReceived(QHttpResponseHeader header); + void updateHeaderReceived(QNetworkRequest header ); protected: @@ -183,6 +200,9 @@ class UBApplicationController : public QObject QNetworkAccessManager *networkAccessManager; void downloadJsonFinished(QString updateString); + QHttpPart* mHttp; + QNetworkAccessManager qnam; + QNetworkReply *mHttpreply; }; #endif /* UBAPPLICATIONCONTROLLER_H_ */ From 2b75543ee30bdb72098413c6ded658d78cb5d5de Mon Sep 17 00:00:00 2001 From: agriche Date: Mon, 30 Nov 2015 11:00:36 +0100 Subject: [PATCH 030/243] - comment all checkupdate(). --- src/core/UBApplicationController.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/core/UBApplicationController.cpp b/src/core/UBApplicationController.cpp index 6bfcbdef..f1cfa729 100644 --- a/src/core/UBApplicationController.cpp +++ b/src/core/UBApplicationController.cpp @@ -65,6 +65,8 @@ #include "ui_mainWindow.h" + + #ifdef Q_WS_MAC #include #endif @@ -496,6 +498,8 @@ void UBApplicationController::checkUpdate(QString urlString) mHttp->get(url.path()); */ + +#else if(mHttpreply) mHttpreply->deleteLater(); QUrl url(urlString); @@ -504,8 +508,6 @@ void UBApplicationController::checkUpdate(QString urlString) connect(mHttpreply, SIGNAL(responseHeaderReceived(QHttpResponseHeader)), this, SLOT(updateHeaderReceived(QHttpResponseHeader))); // mHttpreply->setUrl(url.path()); //mHttp->get(url.path()); -#else - #endif } @@ -585,14 +587,14 @@ void UBApplicationController::checkAtLaunch() if(UBSettings::settings()->appEnableAutomaticSoftwareUpdates->get().toBool()){ isNoUpdateDisplayed = false; - checkUpdate (); + //checkUpdate (); } } void UBApplicationController::checkUpdateRequest() { isNoUpdateDisplayed = true; - checkUpdate (); + //checkUpdate (); } void UBApplicationController::hideDesktop() From fc554baecd03f3bd5a6c270c88fed0596846c1d9 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Fri, 27 Nov 2015 08:48:53 +0100 Subject: [PATCH 031/243] clean-up; temporary solution for waiting until audio assetWriter is ready before appending sample buffers --- src/podcast/quicktime/UBQuickTimeFile.h | 18 ++---- src/podcast/quicktime/UBQuickTimeFile.mm | 72 +++++++++++++----------- 2 files changed, 45 insertions(+), 45 deletions(-) diff --git a/src/podcast/quicktime/UBQuickTimeFile.h b/src/podcast/quicktime/UBQuickTimeFile.h index 413ddffe..358d2a2b 100644 --- a/src/podcast/quicktime/UBQuickTimeFile.h +++ b/src/podcast/quicktime/UBQuickTimeFile.h @@ -101,24 +101,12 @@ class UBQuickTimeFile : public QThread bool beginSession(); void setLastErrorMessage(const QString& error); - void appendVideoFrame(CVPixelBufferRef pixelBuffer, long msTimeStamp); - bool flushPendingFrames(); - volatile bool mShouldStopCompression; - volatile bool mCompressionSessionRunning; - volatile int mPendingFrames; - - QString mSpatialQuality; - - int mFramesPerSecond; QSize mFrameSize; QString mVideoFileName; - bool mRecordAudio; - - AssetWriterPTR mVideoWriter; AssetWriterInputPTR mVideoWriterInput; @@ -132,6 +120,12 @@ class UBQuickTimeFile : public QThread CMAudioFormatDescriptionRef mAudioFormatDescription; long mTimeScale; + bool mRecordAudio; + + volatile bool mShouldStopCompression; + volatile bool mCompressionSessionRunning; + + QString mLastErrorMessage; diff --git a/src/podcast/quicktime/UBQuickTimeFile.mm b/src/podcast/quicktime/UBQuickTimeFile.mm index 50007556..39aa6ac1 100644 --- a/src/podcast/quicktime/UBQuickTimeFile.mm +++ b/src/podcast/quicktime/UBQuickTimeFile.mm @@ -41,18 +41,15 @@ QQueue UBQuickTimeFile::frameQueue; QMutex UBQuickTimeFile::frameQueueMutex; QWaitCondition UBQuickTimeFile::frameBufferNotEmpty; - UBQuickTimeFile::UBQuickTimeFile(QObject * pParent) : QThread(pParent) , mVideoWriter(0) , mVideoWriterInput(0) , mAdaptor(0) - , mFramesPerSecond(-1) , mTimeScale(1000) , mRecordAudio(true) , mShouldStopCompression(false) , mCompressionSessionRunning(false) - , mPendingFrames(0) { } @@ -67,10 +64,8 @@ bool UBQuickTimeFile::init(const QString& pVideoFileName, const QString& pProfil , const QSize& pFrameSize, bool pRecordAudio, const QString& audioRecordingDevice) { mFrameSize = pFrameSize; - mFramesPerSecond = pFramesPerSecond; mVideoFileName = pVideoFileName; mRecordAudio = pRecordAudio; - mSpatialQuality = pProfileData; if (mRecordAudio) mAudioRecordingDeviceName = audioRecordingDevice; @@ -88,7 +83,6 @@ bool UBQuickTimeFile::init(const QString& pVideoFileName, const QString& pProfil void UBQuickTimeFile::run() { mShouldStopCompression = false; - mPendingFrames = 0; if (!beginSession()) return; @@ -96,7 +90,8 @@ void UBQuickTimeFile::run() mCompressionSessionRunning = true; emit compressionSessionStarted(); - do { + do { + // Video frameQueueMutex.lock(); frameBufferNotEmpty.wait(&UBQuickTimeFile::frameQueueMutex); @@ -118,6 +113,7 @@ void UBQuickTimeFile::run() } else frameQueueMutex.unlock(); + } while(!mShouldStopCompression); endSession(); @@ -127,7 +123,7 @@ void UBQuickTimeFile::run() /** * \brief Begin the recording session; initialize the audio/video writer * \return true if the session was initialized successfully - * + * * This function initializes the AVAssetWriter and associated video and audio inputs. * Video is encoded as H264; audio is encoded as AAC. */ @@ -141,7 +137,7 @@ bool UBQuickTimeFile::beginSession() qDebug() << "Podcast video URL invalid; not recording"; return false; } - + // Create and check the assetWriter mVideoWriter = [[AVAssetWriter assetWriterWithURL:outputUrl fileType:AVFileTypeQuickTimeMovie @@ -149,7 +145,7 @@ bool UBQuickTimeFile::beginSession() NSCParameterAssert(mVideoWriter); mVideoWriter.movieTimeScale = mTimeScale; - + // Video @@ -158,7 +154,7 @@ bool UBQuickTimeFile::beginSession() int frameWidth = mFrameSize.width(); int frameHeight = mFrameSize.height(); - // Create the input and check it + // Create the input and check it NSDictionary * videoSettings = [NSDictionary dictionaryWithObjectsAndKeys: AVVideoCodecH264, AVVideoCodecKey, [NSNumber numberWithInt:frameWidth], AVVideoWidthKey, @@ -167,7 +163,7 @@ bool UBQuickTimeFile::beginSession() mVideoWriterInput = [[AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo - outputSettings:videoSettings] retain]; + outputSettings:videoSettings] retain]; NSCParameterAssert(mVideoWriterInput); @@ -193,7 +189,7 @@ bool UBQuickTimeFile::beginSession() if(mRecordAudio) { mWaveRecorder = new UBAudioQueueRecorder(); - + // Get the audio format description from mWaveRecorder CMAudioFormatDescriptionCreate(kCFAllocatorDefault, mWaveRecorder->audioFormat(), 0, NULL, 0, NULL, NULL, @@ -213,16 +209,16 @@ bool UBQuickTimeFile::beginSession() } // Audio is mono, and compressed to AAC at 128kbps - + AudioChannelLayout audioChannelLayout = { .mChannelLayoutTag = kAudioChannelLayoutTag_Mono, .mChannelBitmap = 0, .mNumberChannelDescriptions = 0 }; - NSData *channelLayoutAsData = [NSData dataWithBytes:&audioChannelLayout + NSData *channelLayoutAsData = [NSData dataWithBytes:&audioChannelLayout length:offsetof(AudioChannelLayout, mChannelDescriptions)]; - + NSDictionary * compressionAudioSettings = @{ AVFormatIDKey : [NSNumber numberWithUnsignedInt:kAudioFormatMPEG4AAC], AVEncoderBitRateKey : [NSNumber numberWithInteger:128000], @@ -231,12 +227,12 @@ bool UBQuickTimeFile::beginSession() AVNumberOfChannelsKey : [NSNumber numberWithUnsignedInteger:1] }; - mAudioWriterInput = [[AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio + mAudioWriterInput = [[AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio outputSettings:compressionAudioSettings] retain]; - + NSCParameterAssert([mVideoWriter canAddInput:mAudioWriterInput]); [mVideoWriter addInput:mAudioWriterInput]; - + qDebug() << "audio writer input created and added"; } @@ -247,7 +243,7 @@ bool UBQuickTimeFile::beginSession() mStartTime = CFAbsoluteTimeGetCurrent(); // used for audio timestamp calculation - + return (mVideoWriter != nil) && (mVideoWriterInput != nil) && canStartWriting; } @@ -257,7 +253,7 @@ bool UBQuickTimeFile::beginSession() void UBQuickTimeFile::endSession() { [mVideoWriterInput markAsFinished]; - bool success = [mVideoWriter finishWriting]; + [mVideoWriter finishWritingWithCompletionHandler:^{}]; [mAdaptor release]; [mVideoWriterInput release]; @@ -309,12 +305,12 @@ CVPixelBufferRef UBQuickTimeFile::newPixelBuffer() */ void UBQuickTimeFile::appendVideoFrame(CVPixelBufferRef pixelBuffer, long msTimeStamp) { - CMTime t = CMTimeMake((msTimeStamp * mTimeScale / 1000.0), mTimeScale); + CMTime t = CMTimeMake((msTimeStamp * mTimeScale / 1000.0), mTimeScale); bool added = [mAdaptor appendPixelBuffer: pixelBuffer withPresentationTime: t]; - if (!added) + if (!added) setLastErrorMessage(QString("Could not encode frame at time %1").arg(msTimeStamp)); @@ -333,10 +329,10 @@ void UBQuickTimeFile::appendVideoFrame(CVPixelBufferRef pixelBuffer, long msTime * (implemented in the UBAudioQueueRecorder class) and the recording, handled * by the AVAssetWriterInput instance mAudioWriterInput. */ -void UBQuickTimeFile::appendAudioBuffer(void* pBuffer, +void UBQuickTimeFile::appendAudioBuffer(void* pBuffer, long pLength) { - if(!mRecordAudio) + if(!mRecordAudio) return; @@ -368,24 +364,34 @@ void UBQuickTimeFile::appendAudioBuffer(void* pBuffer, true, NULL, NULL, - mAudioFormatDescription, + mAudioFormatDescription, nSamples, - timeStamp, + timeStamp, NULL, &sampleBuffer); - // Add the audio sample to the asset writer input - if ([mAudioWriterInput isReadyForMoreMediaData]) + // Wait until the AssetWriterInput is ready, but no more than 100ms + // (bit of a duct tape solution; cleaner solution would be to use a QQueue, + // similar to the VideoWriter) + int waitTime = 0; + while(![mAudioWriterInput isReadyForMoreMediaData] && waitTime < 100) { + waitTime += 10; + usleep(10000); + } + + if ([mAudioWriterInput isReadyForMoreMediaData]) { if(![mAudioWriterInput appendSampleBuffer:sampleBuffer]) setLastErrorMessage(QString("Failed to append sample buffer to audio input")); - - else - setLastErrorMessage(QString("Audio Writer not ready; sample dropped")); - + } + else + setLastErrorMessage(QString("AudioWriterInput not ready. Buffer dropped.")); + + CFRelease(sampleBuffer); CFRelease(blockBuffer); + // The audioQueueBuffers are all freed when UBAudioQueueRecorder::close() is called } From 427cdbb68d2453784adb99308b7752dc4ae3874c Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Mon, 30 Nov 2015 10:55:40 +0100 Subject: [PATCH 032/243] Podcast recording on OSX fixed. Details: The threading logic was changed somewhat. UBQuickTimeFile's run() function no longer handles enqueuing the video/audio samples in a while loop. Instead, it runs once, and uses Apple's Dispatch Queues to handle enqueuing samples. One dispatch queue was thus added for each input to the AssetWriter. Each input is associated to one queue, and the requestMediaDataWhenReady function insures that the inputs go and fetch any available samples when they are able to write them. As tested (for short podcasts, repeatedly), this solves all the problems encountered earlier, such as the program hanging due to one input not being ready, or corrupt files due (presumably) to missing samples. --- .../quicktime/UBAudioQueueRecorder.cpp | 3 +- src/podcast/quicktime/UBQuickTimeFile.h | 15 +- src/podcast/quicktime/UBQuickTimeFile.mm | 153 +++++++++++------- .../quicktime/UBQuickTimeVideoEncoder.cpp | 7 +- 4 files changed, 110 insertions(+), 68 deletions(-) diff --git a/src/podcast/quicktime/UBAudioQueueRecorder.cpp b/src/podcast/quicktime/UBAudioQueueRecorder.cpp index b1354149..02e23117 100644 --- a/src/podcast/quicktime/UBAudioQueueRecorder.cpp +++ b/src/podcast/quicktime/UBAudioQueueRecorder.cpp @@ -257,7 +257,8 @@ bool UBAudioQueueRecorder::init(const QString& waveInDeviceName) int nbBuffers = 6; mSampleBufferSize = sAudioFormat.mSampleRate * sAudioFormat.mChannelsPerFrame - * sAudioFormat.mChannelsPerFrame * mBufferLengthInMs / 1000; // 44.1 Khz * stereo * 16bit * buffer length + * sAudioFormat.mBitsPerChannel / 8 * mBufferLengthInMs / 1000; + // BufferSize [bytes] = Length [s] * 44100 frames per second [Fr./s] * channels per frame [Ch./Fr.] * bytes per channel [bytes/Ch.] for (int i = 0; i < nbBuffers; i++) { diff --git a/src/podcast/quicktime/UBQuickTimeFile.h b/src/podcast/quicktime/UBQuickTimeFile.h index 358d2a2b..1ad5959f 100644 --- a/src/podcast/quicktime/UBQuickTimeFile.h +++ b/src/podcast/quicktime/UBQuickTimeFile.h @@ -89,12 +89,13 @@ class UBQuickTimeFile : public QThread signals: void audioLevelChanged(quint8 level); void compressionSessionStarted(); + void compressionFinished(); protected: void run(); private slots: - void appendAudioBuffer(void* pBuffer, long pLength); + void enqueueAudioBuffer(void* pBuffer, long pLength); private: @@ -102,7 +103,7 @@ class UBQuickTimeFile : public QThread void setLastErrorMessage(const QString& error); void appendVideoFrame(CVPixelBufferRef pixelBuffer, long msTimeStamp); - + bool appendSampleBuffer(CMSampleBufferRef sampleBuffer); QSize mFrameSize; QString mVideoFileName; @@ -125,12 +126,16 @@ class UBQuickTimeFile : public QThread volatile bool mShouldStopCompression; volatile bool mCompressionSessionRunning; - - QString mLastErrorMessage; - QString mAudioRecordingDeviceName; + dispatch_queue_t mVideoDispatchQueue; + dispatch_queue_t mAudioDispatchQueue; + + static QQueue audioQueue; + static QMutex audioQueueMutex; + + static QMutex audioWriterMutex; }; #endif /* UBQUICKTIMEFILE_H_ */ diff --git a/src/podcast/quicktime/UBQuickTimeFile.mm b/src/podcast/quicktime/UBQuickTimeFile.mm index 39aa6ac1..572c0c0a 100644 --- a/src/podcast/quicktime/UBQuickTimeFile.mm +++ b/src/podcast/quicktime/UBQuickTimeFile.mm @@ -41,16 +41,25 @@ QQueue UBQuickTimeFile::frameQueue; QMutex UBQuickTimeFile::frameQueueMutex; QWaitCondition UBQuickTimeFile::frameBufferNotEmpty; + +QQueue UBQuickTimeFile::audioQueue; +QMutex UBQuickTimeFile::audioQueueMutex; +QMutex UBQuickTimeFile::audioWriterMutex; + UBQuickTimeFile::UBQuickTimeFile(QObject * pParent) : QThread(pParent) , mVideoWriter(0) , mVideoWriterInput(0) , mAdaptor(0) + , mAudioWriterInput(0) + , mWaveRecorder(0) , mTimeScale(1000) , mRecordAudio(true) , mShouldStopCompression(false) , mCompressionSessionRunning(false) { + mVideoDispatchQueue = dispatch_queue_create("org.oef.VideoDispatchQueue", NULL); + mAudioDispatchQueue = dispatch_queue_create("org.oef.AudioDispatchQueue", NULL); } @@ -66,6 +75,7 @@ bool UBQuickTimeFile::init(const QString& pVideoFileName, const QString& pProfil mFrameSize = pFrameSize; mVideoFileName = pVideoFileName; mRecordAudio = pRecordAudio; + //mRecordAudio = false; if (mRecordAudio) mAudioRecordingDeviceName = audioRecordingDevice; @@ -90,33 +100,36 @@ void UBQuickTimeFile::run() mCompressionSessionRunning = true; emit compressionSessionStarted(); - do { - // Video - frameQueueMutex.lock(); - - frameBufferNotEmpty.wait(&UBQuickTimeFile::frameQueueMutex); + [mVideoWriterInput requestMediaDataWhenReadyOnQueue:mVideoDispatchQueue + usingBlock:^{ + frameQueueMutex.lock(); + //frameBufferNotEmpty.wait(&UBQuickTimeFile::frameQueueMutex); // TODO: monitor performance with and without this - if (!frameQueue.isEmpty()) { - QQueue localQueue = frameQueue; - frameQueue.clear(); - - frameQueueMutex.unlock(); - - while (!localQueue.isEmpty()) { - if ([mVideoWriterInput isReadyForMoreMediaData]) { - VideoFrame frame = localQueue.dequeue(); + if (!mShouldStopCompression && + !frameQueue.isEmpty() && + [mVideoWriterInput isReadyForMoreMediaData]) + { + VideoFrame frame = frameQueue.dequeue(); appendVideoFrame(frame.buffer, frame.timestamp); - } - else - usleep(10000); } - } - else - frameQueueMutex.unlock(); - } while(!mShouldStopCompression); + frameQueueMutex.unlock(); + + }]; + + if (mRecordAudio) { + [mAudioWriterInput requestMediaDataWhenReadyOnQueue:mAudioDispatchQueue + usingBlock:^{ + audioQueueMutex.lock(); + if (!audioQueue.isEmpty() && + [mAudioWriterInput isReadyForMoreMediaData]) + { + appendSampleBuffer(audioQueue.dequeue()); + } + audioQueueMutex.unlock(); - endSession(); + }]; + } } @@ -197,7 +210,7 @@ bool UBQuickTimeFile::beginSession() if(mWaveRecorder->init(mAudioRecordingDeviceName)) { connect(mWaveRecorder, &UBAudioQueueRecorder::newWaveBuffer, - this, &UBQuickTimeFile::appendAudioBuffer); + this, &UBQuickTimeFile::enqueueAudioBuffer); connect(mWaveRecorder, SIGNAL(audioLevelChanged(quint8)), this, SIGNAL(audioLevelChanged(quint8))); @@ -223,7 +236,7 @@ bool UBQuickTimeFile::beginSession() AVFormatIDKey : [NSNumber numberWithUnsignedInt:kAudioFormatMPEG4AAC], AVEncoderBitRateKey : [NSNumber numberWithInteger:128000], AVSampleRateKey : [NSNumber numberWithInteger:44100], - AVChannelLayoutKey : channelLayoutAsData, + //AVChannelLayoutKey : channelLayoutAsData, AVNumberOfChannelsKey : [NSNumber numberWithUnsignedInteger:1] }; @@ -232,8 +245,6 @@ bool UBQuickTimeFile::beginSession() NSCParameterAssert([mVideoWriter canAddInput:mAudioWriterInput]); [mVideoWriter addInput:mAudioWriterInput]; - - qDebug() << "audio writer input created and added"; } @@ -252,23 +263,33 @@ bool UBQuickTimeFile::beginSession() */ void UBQuickTimeFile::endSession() { + //qDebug() << "Ending session"; + + [mVideoWriterInput markAsFinished]; - [mVideoWriter finishWritingWithCompletionHandler:^{}]; - [mAdaptor release]; - [mVideoWriterInput release]; - [mVideoWriter release]; - [mAudioWriterInput release]; + [mVideoWriter finishWritingWithCompletionHandler:^{ + [mAdaptor release]; + [mVideoWriterInput release]; - mAdaptor = nil; - mVideoWriterInput = nil; - mVideoWriter = nil; - mAudioWriterInput = nil; + if (mAudioWriterInput != 0) + [mAudioWriterInput release]; + + [mVideoWriter release]; - if (mWaveRecorder) { - mWaveRecorder->close(); - mWaveRecorder->deleteLater(); - } + mAdaptor = nil; + mVideoWriterInput = nil; + mVideoWriter = nil; + mAudioWriterInput = nil; + + if (mWaveRecorder) { + mWaveRecorder->close(); + mWaveRecorder->deleteLater(); + } + + + emit compressionFinished(); + }]; } @@ -277,12 +298,22 @@ void UBQuickTimeFile::endSession() */ void UBQuickTimeFile::stop() { + //qDebug() << "requested end of recording"; mShouldStopCompression = true; + + + frameQueueMutex.lock(); + audioQueueMutex.lock(); + endSession(); + frameQueueMutex.unlock(); + audioQueueMutex.unlock(); } /** - * \brief Create a CVPixelBufferRef from the input adaptor's CVPixelBufferPool + * \brief Create and return a CVPixelBufferRef + * + * The CVPixelBuffer is created from the input adaptor's CVPixelBufferPool */ CVPixelBufferRef UBQuickTimeFile::newPixelBuffer() { @@ -305,6 +336,7 @@ CVPixelBufferRef UBQuickTimeFile::newPixelBuffer() */ void UBQuickTimeFile::appendVideoFrame(CVPixelBufferRef pixelBuffer, long msTimeStamp) { + //qDebug() << "appending video frame"; CMTime t = CMTimeMake((msTimeStamp * mTimeScale / 1000.0), mTimeScale); bool added = [mAdaptor appendPixelBuffer: pixelBuffer @@ -329,10 +361,11 @@ void UBQuickTimeFile::appendVideoFrame(CVPixelBufferRef pixelBuffer, long msTime * (implemented in the UBAudioQueueRecorder class) and the recording, handled * by the AVAssetWriterInput instance mAudioWriterInput. */ -void UBQuickTimeFile::appendAudioBuffer(void* pBuffer, +void UBQuickTimeFile::enqueueAudioBuffer(void* pBuffer, long pLength) { - if(!mRecordAudio) + + if(!mRecordAudio || mShouldStopCompression) return; @@ -370,31 +403,37 @@ void UBQuickTimeFile::appendAudioBuffer(void* pBuffer, NULL, &sampleBuffer); + //qDebug() << "enqueueAudioBuffer, timeStamp = " << timeStamp.value << " / " << timeStamp.timescale; - // Wait until the AssetWriterInput is ready, but no more than 100ms - // (bit of a duct tape solution; cleaner solution would be to use a QQueue, - // similar to the VideoWriter) - int waitTime = 0; - while(![mAudioWriterInput isReadyForMoreMediaData] && waitTime < 100) { - waitTime += 10; - usleep(10000); - } + + audioQueueMutex.lock(); + audioQueue.enqueue(sampleBuffer); + audioQueueMutex.unlock(); + + //qDebug() << "buffer enqueued"; + + + +} - if ([mAudioWriterInput isReadyForMoreMediaData]) { - if(![mAudioWriterInput appendSampleBuffer:sampleBuffer]) - setLastErrorMessage(QString("Failed to append sample buffer to audio input")); - } - else - setLastErrorMessage(QString("AudioWriterInput not ready. Buffer dropped.")); +bool UBQuickTimeFile::appendSampleBuffer(CMSampleBufferRef sampleBuffer) +{ + bool success = [mAudioWriterInput appendSampleBuffer:sampleBuffer]; + + if (!success) + setLastErrorMessage(QString("Failed to append sample buffer to audio input")); + + CMBlockBufferRef blockBuffer = CMSampleBufferGetDataBuffer(sampleBuffer); CFRelease(sampleBuffer); CFRelease(blockBuffer); - // The audioQueueBuffers are all freed when UBAudioQueueRecorder::close() is called + return success; } + /** * \brief Print an error message to the terminal, and store it */ diff --git a/src/podcast/quicktime/UBQuickTimeVideoEncoder.cpp b/src/podcast/quicktime/UBQuickTimeVideoEncoder.cpp index e3497640..cd03d8ed 100644 --- a/src/podcast/quicktime/UBQuickTimeVideoEncoder.cpp +++ b/src/podcast/quicktime/UBQuickTimeVideoEncoder.cpp @@ -68,7 +68,7 @@ bool UBQuickTimeVideoEncoder::start() return false; } - connect(&mQuickTimeCompressionSession, SIGNAL(finished()), this, SLOT(compressionFinished())); + connect(&mQuickTimeCompressionSession, SIGNAL(compressionFinished()), this, SLOT(compressionFinished())); connect(&mQuickTimeCompressionSession, SIGNAL(audioLevelChanged(quint8)), this, SIGNAL(audioLevelChanged(quint8))); mQuickTimeCompressionSession.start(); @@ -79,10 +79,7 @@ bool UBQuickTimeVideoEncoder::start() bool UBQuickTimeVideoEncoder::stop() { - if (mQuickTimeCompressionSession.isRunning()) - { - mQuickTimeCompressionSession.stop(); - } + mQuickTimeCompressionSession.stop(); UBQuickTimeFile::frameBufferNotEmpty.wakeAll(); From ce521ede116f7186e134dae4725f8b26a9554934 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Thu, 3 Dec 2015 13:32:40 +0100 Subject: [PATCH 033/243] Video fixed on OS X QVideoWidget had to be abandoned in favour of QGraphicsVideoItem. This is because UBGraphicsMediaItem, i.e the class representing a media (audio or video) object on the board, is a QGraphicsProxyWidget, and is used to embed a QWidget into the Scene. With Phonon's video widget, it was possible to embed the video widget in this ProxyWidget. This is no longer possible (except on Windows, for some reason), so this commit is a workaround, to use a QGraphicsVideoItem instead of a QVideoWidget while modifying the rest of the class hierarchy as little as possible. Ultimately, a cleaner solution (not making UBGraphicsMediaItem inherit QGraphicsProxyWidget, for example) may be desirable. --- OpenBoard.pro | 8 +-- src/domain/UBGraphicsMediaItem.cpp | 83 ++++++++++++++++++++++++++---- src/domain/UBGraphicsMediaItem.h | 15 ++++-- src/domain/UBGraphicsScene.cpp | 6 +++ 4 files changed, 94 insertions(+), 18 deletions(-) diff --git a/OpenBoard.pro b/OpenBoard.pro index b6802c50..a9e2b737 100644 --- a/OpenBoard.pro +++ b/OpenBoard.pro @@ -9,9 +9,9 @@ CONFIG += debug_and_release \ VERSION_MAJ = 1 -VERSION_MIN = 02 -VERSION_TYPE = r # a = alpha, b = beta, rc = release candidate, r = release, other => error -VERSION_PATCH = 10 +VERSION_MIN = 1 +VERSION_TYPE = a # a = alpha, b = beta, rc = release candidate, r = release, other => error +VERSION_PATCH = 0 VERSION = "$${VERSION_MAJ}.$${VERSION_MIN}.$${VERSION_TYPE}.$${VERSION_PATCH}" VERSION = $$replace(VERSION, "\\.r", "") @@ -138,7 +138,7 @@ macx { CONFIG(debug, debug|release):CONFIG += x86_64 QMAKE_MAC_SDK = macosx - QMAKE_MACOSX_DEPLOYMENT_TARGET = "10.10" + QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.10 QMAKE_CXXFLAGS += -Wno-overloaded-virtual #VERSION_RC_PATH = "$$BUILD_DIR/version_rc" diff --git a/src/domain/UBGraphicsMediaItem.cpp b/src/domain/UBGraphicsMediaItem.cpp index 7d6edabc..ec3bcd57 100644 --- a/src/domain/UBGraphicsMediaItem.cpp +++ b/src/domain/UBGraphicsMediaItem.cpp @@ -35,11 +35,14 @@ #include "board/UBBoardController.h" #include "core/memcheck.h" +#include + bool UBGraphicsMediaItem::sIsMutedByDefault = false; UBGraphicsMediaItem::UBGraphicsMediaItem(const QUrl& pMediaFileUrl, QGraphicsItem *parent) : UBGraphicsProxyWidget(parent) - , mVideoWidget(NULL) + , mDummyVideoWidget(NULL) + , mVideoItem(NULL) , mAudioWidget(NULL) , mMuted(sIsMutedByDefault) , mMutedByUserAction(sIsMutedByDefault) @@ -62,19 +65,18 @@ UBGraphicsMediaItem::UBGraphicsMediaItem(const QUrl& pMediaFileUrl, QGraphicsIte mMediaObject->setNotifyInterval(50); - mVideoWidget = new QVideoWidget(); // owned and destructed by the scene ... - - mMediaObject->setVideoOutput(mVideoWidget); + mDummyVideoWidget = new QWidget(); // owned and destructed by the scene ... + mDummyVideoWidget->resize(320,240); + mDummyVideoWidget->setMinimumSize(320, 240); + mDummyVideoWidget->setWindowOpacity(0.0); + + mVideoItem = new QGraphicsVideoItem(); - if(mVideoWidget->sizeHint() == QSize(1,1)){ - mVideoWidget->resize(320,240); - } + mMediaObject->setVideoOutput(mVideoItem); - mVideoWidget->setMinimumSize(320,240); + mVideoItem->setSize(QSize(320,240)); haveLinkedImage = true; - - } else if (mediaPath.toLower().contains("audios")) { @@ -98,7 +100,7 @@ UBGraphicsMediaItem::UBGraphicsMediaItem(const QUrl& pMediaFileUrl, QGraphicsIte // delegate should be created earler because we setWidget calls resize event for graphics proxy widgt. // resize uses delegate. if (mediaType_Video == mMediaType) - setWidget(mVideoWidget); + setWidget(mDummyVideoWidget); else setWidget(mAudioWidget); @@ -165,6 +167,13 @@ QVariant UBGraphicsMediaItem::itemChange(GraphicsItemChange change, const QVaria } } + // Pass on geometry and position changes to the videoItem + else if (mVideoItem && change == QGraphicsItem::ItemTransformChange) + mVideoItem->setTransform(qvariant_cast(value)); + + else if (mVideoItem && change == QGraphicsItem::ItemPositionChange) + mVideoItem->setPos(qvariant_cast(value)); + return UBGraphicsProxyWidget::itemChange(change, value); } @@ -330,3 +339,55 @@ void UBGraphicsMediaItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) } +void UBGraphicsMediaItem::setPos(const QPointF &pos) +{ + QGraphicsItem::setPos(pos); + if (mVideoItem) + mVideoItem->setPos(pos); +} + +void UBGraphicsMediaItem::setPos(qreal x, qreal y) +{ + setPos(QPointF(x, y)); +} + + +void UBGraphicsMediaItem::setTransform(const QTransform &matrix, bool combine) +{ + QGraphicsItem::setTransform(matrix, combine); + + if (mVideoItem) + mVideoItem->setTransform(matrix, combine); +} + +void UBGraphicsMediaItem::resize(const QSizeF & pSize) +{ + // Resize the video, then the rest of the Item + + if (mVideoItem) { + qreal sizeX = 0; + qreal sizeY = 0; + + QSizeF minimumItemSize(mDummyVideoWidget->minimumSize()); + if (minimumItemSize.width() > pSize.width()) + sizeX = minimumItemSize.width(); + else + sizeX = pSize.width(); + + if (minimumItemSize.height() > pSize.height()) + sizeY = minimumItemSize.height(); + else + sizeY = pSize.height(); + + mVideoItem->setSize(QSizeF (sizeX, sizeY)); + } + + UBGraphicsProxyWidget::resize(pSize); +} + +void UBGraphicsMediaItem::resize(qreal w, qreal h) +{ + UBGraphicsMediaItem::resize(QSizeF(w, h)); +} + + diff --git a/src/domain/UBGraphicsMediaItem.h b/src/domain/UBGraphicsMediaItem.h index a0e9bcda..5846075b 100644 --- a/src/domain/UBGraphicsMediaItem.h +++ b/src/domain/UBGraphicsMediaItem.h @@ -43,6 +43,8 @@ #include "board/UBBoardController.h" #include "frameworks/UBFileSystemUtils.h" +class QGraphicsVideoItem; + class UBGraphicsMediaItem : public UBGraphicsProxyWidget { Q_OBJECT @@ -87,9 +89,9 @@ public: return mMuted; } - QVideoWidget* videoWidget() const + QGraphicsVideoItem * videoItem() const { - return mVideoWidget; + return mVideoItem; } bool hasLinkedImage(){return haveLinkedImage;} @@ -106,6 +108,12 @@ public: void setSelected(bool selected); + virtual void setPos(const QPointF &pos); + virtual void setPos(qreal x, qreal y); + virtual void setTransform(const QTransform &matrix, bool combine = false); + virtual void resize(qreal w, qreal h); + virtual void resize(const QSizeF & pSize); + public slots: @@ -123,7 +131,8 @@ protected: virtual void clearSource(); QMediaPlayer *mMediaObject; - QVideoWidget *mVideoWidget; + QWidget *mDummyVideoWidget; + QGraphicsVideoItem *mVideoItem; QWidget *mAudioWidget; diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index 78284a86..63197044 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include "frameworks/UBGeometryUtils.h" #include "frameworks/UBPlatformUtils.h" @@ -1328,6 +1329,11 @@ UBGraphicsMediaItem* UBGraphicsScene::addMedia(const QUrl& pMediaFileUrl, bool s addItem(mediaItem); + if (mediaItem->videoItem()) { + addItem(mediaItem->videoItem()); + mediaItem->videoItem()->show(); + } + mediaItem->show(); if (mUndoRedoStackEnabled) { //should be deleted after scene own undo stack implemented From 8254e807bd582b9a7e7e1d6e49d03ffdf4406271 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Thu, 3 Dec 2015 14:33:22 +0100 Subject: [PATCH 034/243] Fixed compilation on Windows; The project didn't compile on Windows.. list of modifications: - Added essential changes that hadn't been committed / pushed (Qt4->Qt5 changes; other misc. changes by Abdel) - Temporarily disabled podcasts, as the modules don't compile with Qt5.2/ 5.5 Currently, the application compiles on Windows, with MSVC2010 32-bit --- OpenBoard.pro | 2 ++ src/core/UBApplication.cpp | 2 +- src/desktop/UBWindowCaptureDelegate_win.cpp | 3 ++- src/frameworks/UBPlatformUtils_win.cpp | 3 ++- src/gui/UBRubberBand.cpp | 2 +- src/podcast/UBPodcastController.cpp | 8 ++++---- src/podcast/podcast.pri | 16 ++++++++-------- src/podcast/windowsmedia/UBWaveRecorder.cpp | 6 +++--- src/podcast/windowsmedia/UBWindowsMediaFile.cpp | 4 ++-- src/podcast/windowsmedia/UBWindowsMediaFile.h | 3 ++- 10 files changed, 27 insertions(+), 22 deletions(-) diff --git a/OpenBoard.pro b/OpenBoard.pro index a9e2b737..bcaf956d 100644 --- a/OpenBoard.pro +++ b/OpenBoard.pro @@ -124,6 +124,8 @@ win32 { system(echo "$$LONG_VERSION" > $$BUILD_DIR/longversion) system(echo "$$SVN_VERSION" > $$BUILD_DIR/svnversion) + DEFINES += NOMINMAX # avoids compilation error in qdatetime.h + } macx { diff --git a/src/core/UBApplication.cpp b/src/core/UBApplication.cpp index 24558e59..5f1b560c 100644 --- a/src/core/UBApplication.cpp +++ b/src/core/UBApplication.cpp @@ -646,7 +646,7 @@ bool UBApplication::isFromWeb(QString url) { bool res = true; - if( url.startsWith("uniboardTool://") || + if( url.startsWith("OpenboardTool://") || url.startsWith("file://") || url.startsWith("/")){ res = false; diff --git a/src/desktop/UBWindowCaptureDelegate_win.cpp b/src/desktop/UBWindowCaptureDelegate_win.cpp index 3db98ac9..cc43b489 100644 --- a/src/desktop/UBWindowCaptureDelegate_win.cpp +++ b/src/desktop/UBWindowCaptureDelegate_win.cpp @@ -27,6 +27,7 @@ #include "UBWindowCaptureDelegate_win.h" #include +#include #include "core/memcheck.h" @@ -79,7 +80,7 @@ int UBWindowCaptureDelegate::execute() mutex.lock(); sleep.wait(&mutex, 200); mutex.unlock(); - mCapturedPixmap = QPixmap::grabWindow(mCurrentWindow); + mCapturedPixmap = QPixmap::grabWindow((WId)mCurrentWindow); return QDialog::Accepted; } else diff --git a/src/frameworks/UBPlatformUtils_win.cpp b/src/frameworks/UBPlatformUtils_win.cpp index 1c1f453f..b4f25c67 100644 --- a/src/frameworks/UBPlatformUtils_win.cpp +++ b/src/frameworks/UBPlatformUtils_win.cpp @@ -126,11 +126,12 @@ void UBPlatformUtils::setDesktopMode(bool desktop) } void UBPlatformUtils::setWindowNonActivableFlag(QWidget* widget, bool nonAcivable) -{ +{/* long exStyle = (nonAcivable) ? GetWindowLong(widget->winId(), GWL_EXSTYLE) | WS_EX_NOACTIVATE : GetWindowLong(widget->winId(), GWL_EXSTYLE) & ~WS_EX_NOACTIVATE; SetWindowLong(widget->winId(), GWL_EXSTYLE, exStyle); + */ } #define KEYBTDECL(s1, s2, clSwitch) KEYBT(s1, s2, clSwitch, 0, 0, KEYCODE(s1), KEYCODE(s2)) diff --git a/src/gui/UBRubberBand.cpp b/src/gui/UBRubberBand.cpp index 8fdd3117..2dab3ede 100644 --- a/src/gui/UBRubberBand.cpp +++ b/src/gui/UBRubberBand.cpp @@ -47,7 +47,7 @@ UBRubberBand::UBRubberBand(Shape s, QWidget * p) customStyle = NULL; #ifdef Q_OS_WIN - customStyle = new QWindowsXPStyle(); + customStyle = QStyleFactory::create("windows"); #elif defined(Q_OS_OSX) customStyle = QStyleFactory::create("macintosh"); #elif defined(Q_OS_LINUX) diff --git a/src/podcast/UBPodcastController.cpp b/src/podcast/UBPodcastController.cpp index 12641434..98a5c79f 100644 --- a/src/podcast/UBPodcastController.cpp +++ b/src/podcast/UBPodcastController.cpp @@ -57,8 +57,8 @@ #ifdef Q_OS_WIN - #include "windowsmedia/UBWindowsMediaVideoEncoder.h" - #include "windowsmedia/UBWaveRecorder.h" + // #include "windowsmedia/UBWindowsMediaVideoEncoder.h" + // #include "windowsmedia/UBWaveRecorder.h" #elif defined(Q_OS_OSX) #include "quicktime/UBQuickTimeVideoEncoder.h" #include "quicktime/UBAudioQueueRecorder.h" @@ -304,7 +304,7 @@ void UBPodcastController::start() applicationMainModeChanged(UBApplication::applicationController->displayMode()); #ifdef Q_OS_WIN - mVideoEncoder = new UBWindowsMediaVideoEncoder(this); //deleted on stop + //mVideoEncoder = new UBWindowsMediaVideoEncoder(this); //deleted on stop #elif defined(Q_OS_OSX) mVideoEncoder = new UBQuickTimeVideoEncoder(this); //deleted on stop #endif @@ -794,7 +794,7 @@ QStringList UBPodcastController::audioRecordingDevices() QStringList devices; #ifdef Q_OS_WIN - devices = UBWaveRecorder::waveInDevices(); + //devices = UBWaveRecorder::waveInDevices(); #elif defined(Q_OS_OSX) devices = UBAudioQueueRecorder::waveInDevices(); #endif diff --git a/src/podcast/podcast.pri b/src/podcast/podcast.pri index 3dde6273..a9ced647 100644 --- a/src/podcast/podcast.pri +++ b/src/podcast/podcast.pri @@ -13,14 +13,14 @@ SOURCES += src/podcast/UBPodcastController.cpp \ win32 { - SOURCES += src/podcast/windowsmedia/UBWindowsMediaVideoEncoder.cpp \ - src/podcast/windowsmedia/UBWindowsMediaFile.cpp \ - src/podcast/windowsmedia/UBWaveRecorder.cpp - - HEADERS += src/podcast/windowsmedia/UBWindowsMediaVideoEncoder.h \ - src/podcast/windowsmedia/UBWindowsMediaFile.h \ - src/podcast/windowsmedia/UBWaveRecorder.h -} +# SOURCES += src/podcast/windowsmedia/UBWindowsMediaVideoEncoder.cpp \ +# src/podcast/windowsmedia/UBWindowsMediaFile.cpp \ +# src/podcast/windowsmedia/UBWaveRecorder.cpp +# +# HEADERS += src/podcast/windowsmedia/UBWindowsMediaVideoEncoder.h \ +# src/podcast/windowsmedia/UBWindowsMediaFile.h \ +# src/podcast/windowsmedia/UBWaveRecorder.h +} macx { diff --git a/src/podcast/windowsmedia/UBWaveRecorder.cpp b/src/podcast/windowsmedia/UBWaveRecorder.cpp index 4d0e55bd..31a27835 100644 --- a/src/podcast/windowsmedia/UBWaveRecorder.cpp +++ b/src/podcast/windowsmedia/UBWaveRecorder.cpp @@ -63,7 +63,7 @@ bool UBWaveRecorder::init(const QString& waveInDeviceName) { if (waveInGetDevCaps(i, &caps, sizeof(caps)) == MMSYSERR_NOERROR) { - QString deviceName = QString:: fromUtf16(caps.szPname); + QString deviceName = QString::fromWCharArray(caps.szPname); if (deviceName == waveInDeviceName) { @@ -237,7 +237,7 @@ QStringList UBWaveRecorder::waveInDevices() { if (waveInGetDevCaps(i, &caps, sizeof(caps)) == MMSYSERR_NOERROR) { - devices << QString::fromUtf16(caps.szPname); + devices << QString::fromWCharArray(caps.szPname); } else { @@ -253,7 +253,7 @@ QStringList UBWaveRecorder::waveInDevices() if (mixerGetDevCaps(i, &caps, sizeof(caps)) == MMSYSERR_NOERROR) { - qDebug() << "Mixer: " << QString::fromUtf16(caps.szPname); + qDebug() << "Mixer: " << QString::fromWCharArray(caps.szPname); } } diff --git a/src/podcast/windowsmedia/UBWindowsMediaFile.cpp b/src/podcast/windowsmedia/UBWindowsMediaFile.cpp index af33d0c6..dbb4fe06 100644 --- a/src/podcast/windowsmedia/UBWindowsMediaFile.cpp +++ b/src/podcast/windowsmedia/UBWindowsMediaFile.cpp @@ -383,7 +383,7 @@ bool UBWindowsMediaFile::appendVideoFrame(const QImage& pImage, long mstimestamp INSSBuffer *sampleBuffer = 0; - if (FAILED(mWMWriter->AllocateSample(pImage.numBytes(), &sampleBuffer))) + if (FAILED(mWMWriter->AllocateSample(pImage.byteCount(), &sampleBuffer))) { setLastErrorMessage("Unable to allocate memory for new video frame"); return false; @@ -400,7 +400,7 @@ bool UBWindowsMediaFile::appendVideoFrame(const QImage& pImage, long mstimestamp } const uchar * imageBuffer = pImage.bits(); - memcpy((void*) rawBuffer, imageBuffer, pImage.numBytes()); + memcpy((void*) rawBuffer, imageBuffer, pImage.byteCount()); HRESULT hrWriteSample = mWMWriter->WriteSample(mVideoInputIndex, msToSampleTime(mstimestamp), 0, sampleBuffer); diff --git a/src/podcast/windowsmedia/UBWindowsMediaFile.h b/src/podcast/windowsmedia/UBWindowsMediaFile.h index ff528c7a..703e027a 100644 --- a/src/podcast/windowsmedia/UBWindowsMediaFile.h +++ b/src/podcast/windowsmedia/UBWindowsMediaFile.h @@ -30,8 +30,9 @@ #include -#include +#include +#include class UBWindowsMediaFile : public QObject { From 16b4a8fc44eb92bf2596b9b3d5b97c4bef130d4b Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Fri, 4 Dec 2015 14:00:15 +0100 Subject: [PATCH 035/243] Added Vim files to .gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 6cdf42eb..624229a4 100644 --- a/.gitignore +++ b/.gitignore @@ -50,6 +50,9 @@ Thumbs.db .settings Makefile.Sankore* +*.swp +*.vim + # Build files # ############### build From b5b8c72249706f04a8c08af2910c8e697cb49ac8 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Fri, 4 Dec 2015 14:00:37 +0100 Subject: [PATCH 036/243] Fixed "Add to library" button showing up for apps Caused by one occurence of "uniboardtool" having been replaced by "OpenboardTool" instead of "openboardtool". For consistency's sake, this was changed to openboardtool, but these URL / application name changes require a clean-up (all occurences of "uniboardtool" are commented out; these should either be removed, or the changes reverted) --- src/core/UBApplication.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/UBApplication.cpp b/src/core/UBApplication.cpp index 5f1b560c..7c959167 100644 --- a/src/core/UBApplication.cpp +++ b/src/core/UBApplication.cpp @@ -646,7 +646,7 @@ bool UBApplication::isFromWeb(QString url) { bool res = true; - if( url.startsWith("OpenboardTool://") || + if( url.startsWith("openboardtool://") || url.startsWith("file://") || url.startsWith("/")){ res = false; From 7e96ab18ebceb272b2c0d30a844bac97475e0868 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Mon, 7 Dec 2015 16:20:55 +0100 Subject: [PATCH 037/243] Fixed protractor tool - Corrected and cleaned up rotation calculation - Fixed button position/size issues (clickable area didn't correspond to the button image) - Fixed tool flashing during resizing - (new feature) Buttons now scale proportionally to the protractor when it is resized - Everything is now drawn by default at a scale of 1 instead of 1.5 - Pen width set to 0 (i.e always 1 pixel thick regardless of zoom), to keep the old look & feel - Scaled the marker tool image (.svg) to look like it did before without scaling it in code - Removed debug messages Tested on OS X, works fine. --- resources/images/angleMarker.svg | 74 ++++++-- src/tools/UBGraphicsProtractor.cpp | 260 ++++++++--------------------- src/tools/UBGraphicsProtractor.h | 9 +- 3 files changed, 135 insertions(+), 208 deletions(-) diff --git a/resources/images/angleMarker.svg b/resources/images/angleMarker.svg index 6bd05c33..216eac4a 100644 --- a/resources/images/angleMarker.svg +++ b/resources/images/angleMarker.svg @@ -1,15 +1,59 @@ - - - - - - - + + + +image/svg+xml \ No newline at end of file diff --git a/src/tools/UBGraphicsProtractor.cpp b/src/tools/UBGraphicsProtractor.cpp index eb9659fd..1af3ffc6 100644 --- a/src/tools/UBGraphicsProtractor.cpp +++ b/src/tools/UBGraphicsProtractor.cpp @@ -37,10 +37,8 @@ #include -//#include - -const QRectF UBGraphicsProtractor::sDefaultRect = QRectF(-175, -175, 350, 350); +const QRectF UBGraphicsProtractor::sDefaultRect = QRectF(-250, -250, 500, 500); UBGraphicsProtractor::UBGraphicsProtractor() : QGraphicsEllipseItem(sDefaultRect) @@ -82,9 +80,11 @@ UBGraphicsProtractor::UBGraphicsProtractor() setData(UBGraphicsItemData::itemLayerType, QVariant(itemLayerType::CppTool)); //Necessary to set if we want z value to be assigned correctly setFlag(QGraphicsItem::ItemIsSelectable, false); - setScale(1.5); - - + mCloseSvgItem->setPos(closeButtonRect().topLeft()); + mResetSvgItem->setPos(resetButtonRect().topLeft()); + mResizeSvgItem->setPos(resizeButtonRect().topLeft()); + mMarkerSvgItem->setPos(markerButtonRect().topLeft()); + mRotateSvgItem->setPos(rotateButtonRect().topLeft()); } @@ -95,8 +95,11 @@ void UBGraphicsProtractor::paint(QPainter *painter, const QStyleOptionGraphicsIt Q_UNUSED(styleOption); Q_UNUSED(widget); + QPen pen_(drawColor()); + pen_.setWidth(0); // Line width = 1 pixel regardless of scale / zoom + painter->setPen(pen_); + painter->setFont(QFont("Arial")); - painter->setPen(drawColor()); painter->setBrush(fillBrush()); painter->drawPie(QRectF(rect().center().x() - radius(), rect().center().y() - radius(), 2 * radius(), 2 * radius()), mStartAngle * 16, mSpan * 16); paintGraduations(painter); @@ -195,12 +198,6 @@ void UBGraphicsProtractor::mouseMoveEvent(QGraphicsSceneMouseEvent *event) qreal angle = startLine.angleTo(currentLine); qreal scaleFactor = currentLine.length()/startLine.length(); - qreal mod_angle = 0; - if (angle>350) - { - mod_angle= angle - 360; // only for debugging - angle= angle - 360; - } switch (mCurrentTool) { @@ -210,17 +207,15 @@ void UBGraphicsProtractor::mouseMoveEvent(QGraphicsSceneMouseEvent *event) setStartAngle(mStartAngle * 16); mPreviousMousePos = currentPoint; - //qDebug() << "UBGraphicsProtractor Rotate"<<"mStartAngle= "<boundingRect().width(); + qreal height = mResetSvgItem->boundingRect().height(); + return QRectF(-refWidth * 7, -height/2.0, width, height); - if (buttonSizeReference().width() * antiSc <= buttonSizeReference().width() * 15) - return QRectF(-buttonSizeReference().width() * 7, -buttonSizeReference().height() * antiSc / 2, - buttonSizeReference().width() * antiSc, buttonSizeReference().height() * antiSc); - else - return QRectF(-buttonSizeReference().width() * antiSc / 2, -buttonSizeReference().height() * antiSc / 2, - buttonSizeReference().width() * antiSc, buttonSizeReference().height() * antiSc); + // Note: these hardcoded position values make it impossible + // to use setScale() on the buttons without affecting their + // relative position on the tool. } + QRectF UBGraphicsProtractor::closeButtonRect () const { - //qreal antiSc = antiScale(); - qreal antiSc = 1; + qreal refWidth = buttonSizeReference().width(); + qreal width = mCloseSvgItem->boundingRect().width(); + qreal height = mCloseSvgItem->boundingRect().height(); - - //qDebug() << "UBGraphicsProtractor closeButtonRect"<<"antiSc = "<boundingRect().width(); + qreal height = mResizeSvgItem->boundingRect().height(); + return QRectF(refWidth * 8, -height/2.0, width, height); } -QRectF UBGraphicsProtractor::resizeButtonRect () const +QRectF UBGraphicsProtractor::rotateButtonRect () const { - //qreal antiSc = antiScale(); - qreal antiSc = 1; + qreal refWidth = buttonSizeReference().width(); + qreal width = mRotateSvgItem->boundingRect().width(); + qreal height = mRotateSvgItem->boundingRect().height(); + + return QRectF(refWidth * 5.5, -refWidth * 5, width, height); - if (buttonSizeReference().width() * antiSc <= buttonSizeReference().width() * 15) - return QRectF(buttonSizeReference().width() * 8, -buttonSizeReference().height() * antiSc / 2, - buttonSizeReference().width() * antiSc, buttonSizeReference().height() * antiSc); - else - { - mResizeSvgItem->setZValue(zValue()+10); - return QRectF(-buttonSizeReference().width() * antiSc / 2, -buttonSizeReference().height() * antiSc / 2, - buttonSizeReference().width() * antiSc, buttonSizeReference().height() * antiSc); - } } +QRectF UBGraphicsProtractor::markerButtonRect () const +{ + qreal width = mMarkerSvgItem->boundingRect().width(); + qreal height = mMarkerSvgItem->boundingRect().height(); + return QRectF(radius() + 3, -height/2, width, height); +} void UBGraphicsProtractor::paintGraduations(QPainter *painter) { painter->save(); - const int tenDegreeGraduationLength = 15; - const int fiveDegreeGraduationLength = 10; - const int oneDegreeGraduationLength = 5; + const int tenDegreeGraduationLength = 22; + const int fiveDegreeGraduationLength = 15; + const int oneDegreeGraduationLength = 7; QFont font1 = painter->font(); #ifdef Q_OS_OSX - font1.setPointSizeF(font1.pointSizeF() - 3); + // TODO: remove this (?) + font1.setPointSizeF(font1.pointSizeF()); + font1.setWeight(QFont::Thin); #endif QFontMetricsF fm1(font1); @@ -429,7 +424,8 @@ void UBGraphicsProtractor::paintGraduations(QPainter *painter) qreal co = cos(((qreal)angle + mStartAngle) * PI/180); qreal si = sin(((qreal)angle + mStartAngle) * PI/180); if (0 == angle % 90) - painter->drawLine(QLineF(QPointF(center.x(), center.y()), QPointF(center.x() + co*tenDegreeGraduationLength, center.y() - si*tenDegreeGraduationLength))); + painter->drawLine(QLineF(QPointF(center.x(), center.y()), + QPointF(center.x() + co*tenDegreeGraduationLength, center.y() - si*tenDegreeGraduationLength))); //external arc painter->drawLine(QLineF(QPointF(center.x()+ rad*co, center.y() - rad*si), @@ -468,145 +464,34 @@ void UBGraphicsProtractor::paintButtons(QPainter *painter) { Q_UNUSED(painter); - - qreal co = cos(mStartAngle * PI/180); // cos(rad) - qreal si = sin(mStartAngle * PI/180); //sin(rad) - - if (mShowButtons) { - qreal scale = buttonSizeReference().width() / mCloseSvgItem->boundingRect().width(); - - /*qDebug() << "UBGraphicsProtractor paint()" - <<"closeButtonRect_Topleft="<setPos(pos_close_x,pos_close_y); - - mCloseSvgItem->resetTransform(); - //mCloseSvgItem->translate(-closeButtonRect().left(),-closeButtonRect().top()); -- - mCloseSvgItem->setPos(-pos_close_x,-pos_close_y); - //mCloseSvgItem->setPos(-closeButtonRect().left(),-closeButtonRect().top()); - //mCloseSvgItem->rotate(-mStartAngle); -- + mCloseSvgItem->setTransformOriginPoint(closeButtonRect().topLeft() * -1); mCloseSvgItem->setRotation(rotation() - mStartAngle); - //mCloseSvgItem->translate(closeButtonRect().left(), closeButtonRect().top()); -- - mCloseSvgItem->setPos(pos_close_x, pos_close_y); - - //mCloseSvgItem->setPos(closeButtonRect().left(), closeButtonRect().top()); - //mCloseSvgItem->scale(scale * antiSc, scale * antiSc);//this do not impact the bounding box of thr svg item... - mCloseSvgItem->setScale(scale );//this do not impact the bounding box of thr svg item... - - - // Determine and apply the position on the reset button object. - //------------------------------------------------------------ - qreal pos_reset_x = resetButtonRect().topLeft().x()* co; - qreal pos_reset_y = qAbs(resetButtonRect().topLeft().x()) * si + resetButtonRect().topLeft().y(); - - mResetSvgItem->setPos(pos_reset_x,pos_reset_y); - - //mResetSvgItem->setPos(resetButtonRect().topLeft() + rect().center()); - mResetSvgItem->resetTransform(); - //mResetSvgItem->translate(-resetButtonRect().left(), -resetButtonRect().top());-- - mResetSvgItem->setPos(-pos_reset_x, -pos_reset_y); - //mResetSvgItem->rotate(-mStartAngle);-- - mResetSvgItem->setRotation(-mStartAngle); + mResetSvgItem->setTransformOriginPoint(resetButtonRect().topLeft() * -1); + mResetSvgItem->setRotation(rotation() - mStartAngle); - //mResetSvgItem->translate(resetButtonRect().left(), resetButtonRect().top());-- - mResetSvgItem->setPos(pos_reset_x, pos_reset_y); + mResizeSvgItem->setTransformOriginPoint(resizeButtonRect().topLeft() * -1); + mResizeSvgItem->setRotation(rotation() - mStartAngle); - //mResetSvgItem->scale(scale * antiSc, scale * antiSc);//this do not impact the bounding box of thr svg item... - mResetSvgItem->setScale(scale );//this do not impact the bounding box of thr svg item... - - - // Determine and apply the position on the resize button object. - //------------------------------------------------------------ - - qreal pos_resize_x = resizeButtonRect().topLeft().x()* co; - qreal pos_resize_y = -(resizeButtonRect().topLeft().x()) * si + resizeButtonRect().topLeft().y(); - - qDebug() << "pos_resize_x ="<setPos(resizeButtonRect().topLeft() + rect().center()); - mResizeSvgItem->setPos(pos_resize_x,pos_resize_y); - mResizeSvgItem->resetTransform(); - mResizeSvgItem->setPos(-pos_resize_x, -pos_resize_y); - //mResizeSvgItem->rotate(-mStartAngle);-- - mResizeSvgItem->setRotation(-mStartAngle); - - //mResizeSvgItem->translate(-resizeButtonRect().left(), -resizeButtonRect().top());-- - mResizeSvgItem->setPos(pos_resize_x, pos_resize_y); - // mResizeSvgItem->scale(scale * antiSc, scale * antiSc);//this do not impact the bounding box of thr svg item... - mResizeSvgItem->setScale(scale);//this do not impact the bounding box of thr svg item... - - // Determine and apply the position on the rotate button object. - //-------------------------------------------------------------- - qreal qPow_x = qPow(rotateButtonRect().topLeft().x(),2); - qreal qPow_y = qPow(rotateButtonRect().topLeft().y(),2); - qreal module_rotate_pos = qSqrt(qPow_x + qPow_y); - - qreal arg_rotate_pos = (qAtan2(rotateButtonRect().topLeft().y(), rotateButtonRect().topLeft().x())); //argument in radian - qreal co_r = cos(-mStartAngle * PI/180 + arg_rotate_pos); // cos(rad) - qreal si_r = sin(-mStartAngle * PI/180 + arg_rotate_pos); //sin(rad) - - - qreal pos_rotate_x = (module_rotate_pos * co_r) ; - qreal pos_rotate_y = (module_rotate_pos * si_r) ; - - mRotateSvgItem->setPos(pos_rotate_x,pos_rotate_y); - //mRotateSvgItem->setPos(rotateButtonRect().topLeft() + rect().center()); -- - mRotateSvgItem->resetTransform(); - mRotateSvgItem->setPos(-pos_rotate_x, -pos_rotate_y); - //mRotateSvgItem->rotate(-mStartAngle);-- - mRotateSvgItem->setRotation(-mStartAngle); - - mRotateSvgItem->setPos(pos_rotate_x, pos_rotate_y); - //mRotateSvgItem->scale(scale, scale);//this do not impact the bounding box of thr svg item... - mRotateSvgItem->setScale(scale);//this do not impact the bounding box of thr svg item... - - //qDebug()<<"UBGraphicsProtractor scale()"<<"scale ="< Date: Mon, 7 Dec 2015 16:39:13 +0100 Subject: [PATCH 038/243] Protractor: fixed font size on windows --- src/tools/UBGraphicsProtractor.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/tools/UBGraphicsProtractor.cpp b/src/tools/UBGraphicsProtractor.cpp index 1af3ffc6..5b4b09ef 100644 --- a/src/tools/UBGraphicsProtractor.cpp +++ b/src/tools/UBGraphicsProtractor.cpp @@ -99,7 +99,7 @@ void UBGraphicsProtractor::paint(QPainter *painter, const QStyleOptionGraphicsIt pen_.setWidth(0); // Line width = 1 pixel regardless of scale / zoom painter->setPen(pen_); - painter->setFont(QFont("Arial")); + painter->setFont(QFont("Arial", 11)); painter->setBrush(fillBrush()); painter->drawPie(QRectF(rect().center().x() - radius(), rect().center().y() - radius(), 2 * radius(), 2 * radius()), mStartAngle * 16, mSpan * 16); paintGraduations(painter); @@ -402,8 +402,7 @@ void UBGraphicsProtractor::paintGraduations(QPainter *painter) QFont font1 = painter->font(); #ifdef Q_OS_OSX - // TODO: remove this (?) - font1.setPointSizeF(font1.pointSizeF()); + font1.setPointSizeF(font1.pointSizeF() + 3); font1.setWeight(QFont::Thin); #endif QFontMetricsF fm1(font1); From f5d1c3857f1e6be1184a50b18e98586abe9c0e48 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Tue, 8 Dec 2015 08:39:34 +0100 Subject: [PATCH 039/243] Rotating the protractor now sets cursor as rotation cursor --- src/tools/UBGraphicsProtractor.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tools/UBGraphicsProtractor.cpp b/src/tools/UBGraphicsProtractor.cpp index 5b4b09ef..228e873d 100644 --- a/src/tools/UBGraphicsProtractor.cpp +++ b/src/tools/UBGraphicsProtractor.cpp @@ -326,6 +326,8 @@ void UBGraphicsProtractor::hoverMoveEvent(QGraphicsSceneHoverEvent *event) if (currentTool == Move) setCursor(Qt::SizeAllCursor); + else if (currentTool == Rotate) + setCursor(rotateCursor()); else setCursor(Qt::ArrowCursor); From 2d796827a42a3182526d4b9d8930019d3a171b2c Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Tue, 8 Dec 2015 15:00:43 +0100 Subject: [PATCH 040/243] Copy z-Value when deep-copying a UBGraphicsPolygonItem --- src/domain/UBGraphicsPolygonItem.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/domain/UBGraphicsPolygonItem.cpp b/src/domain/UBGraphicsPolygonItem.cpp index 1f5b40c3..48530b97 100644 --- a/src/domain/UBGraphicsPolygonItem.cpp +++ b/src/domain/UBGraphicsPolygonItem.cpp @@ -197,6 +197,7 @@ void UBGraphicsPolygonItem::copyItemParameters(UBItem *copy) const cp->setColorOnDarkBackground(this->colorOnDarkBackground()); cp->setColorOnLightBackground(this->colorOnLightBackground()); + cp->setZValue(this->zValue()); cp->setData(UBGraphicsItemData::ItemLayerType, this->data(UBGraphicsItemData::ItemLayerType)); } } From 8ed2e2451dfb08000327e7a07e9a1f376ebda3d3 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Tue, 8 Dec 2015 16:58:13 +0100 Subject: [PATCH 041/243] Removed export of polygons outside of groups The lines removed in this commit led to (presumably) unintended behavior: when saving a document, pen strokes were saved not as a group, but just as their constituent polygons. This meant that the following block of code, that handles saving pen strokes correctly, was never executed. This doesn't fix the z-Value issue (#12), but it seems to be a step in the right direction. --- src/adaptors/UBSvgSubsetAdaptor.cpp | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/src/adaptors/UBSvgSubsetAdaptor.cpp b/src/adaptors/UBSvgSubsetAdaptor.cpp index 376a5f88..2ba03817 100644 --- a/src/adaptors/UBSvgSubsetAdaptor.cpp +++ b/src/adaptors/UBSvgSubsetAdaptor.cpp @@ -1077,20 +1077,6 @@ bool UBSvgSubsetAdaptor::UBSvgSubsetWriter::persistScene(int pageIndex) { QGraphicsItem *item = items.takeFirst(); - // Is the item a strokes group? - UBGraphicsStrokesGroup* strokesGroupItem = qgraphicsitem_cast(item); - - if(strokesGroupItem && strokesGroupItem->isVisible()){ - // Add the polygons - foreach(QGraphicsItem* item, strokesGroupItem->childItems()){ - UBGraphicsPolygonItem* poly = qgraphicsitem_cast(item); - if(NULL != poly){ - polygonItemToSvgPolygon(poly, true); - items.removeOne(poly); - } - } - } - // Is the item a polygon? UBGraphicsPolygonItem *polygonItem = qgraphicsitem_cast (item); if (polygonItem && polygonItem->isVisible()) @@ -2112,6 +2098,7 @@ UBGraphicsMediaItem* UBSvgSubsetAdaptor::UBSvgSubsetReader::videoItemFromSvg() void UBSvgSubsetAdaptor::UBSvgSubsetReader::graphicsItemFromSvg(QGraphicsItem* gItem) { + // TODO: check position QStringRef svgTransform = mXmlReader.attributes().value("transform"); QMatrix itemMatrix; From fb05343ed2a0bba470f3c5a9a55486d8ed051eb7 Mon Sep 17 00:00:00 2001 From: agriche Date: Wed, 9 Dec 2015 12:05:06 +0100 Subject: [PATCH 042/243] - Take in account the local systeme language. --- src/core/UBApplication.cpp | 117 ++++++++++++++++++++++++++++++++----- 1 file changed, 103 insertions(+), 14 deletions(-) diff --git a/src/core/UBApplication.cpp b/src/core/UBApplication.cpp index 7c959167..89ac932c 100644 --- a/src/core/UBApplication.cpp +++ b/src/core/UBApplication.cpp @@ -27,11 +27,15 @@ #include "UBApplication.h" -#include +#include + #include #include #include -#include + +#if defined(Q_WS_MACX) +#include +#endif #include "frameworks/UBPlatformUtils.h" #include "frameworks/UBFileSystemUtils.h" @@ -81,12 +85,33 @@ 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"); -#ifdef Q_OS_OSX +#ifdef Q_WS_MAC bool bIsMinimized = false; #endif QObject* UBApplication::staticMemoryCleaner = 0; +#if defined(Q_WS_MAC) +static OSStatus ub_appleEventProcessor(const AppleEvent *ae, AppleEvent *event, long handlerRefCon) +{ + Q_UNUSED(event); + OSType aeID = typeWildCard; + OSType aeClass = typeWildCard; + + AEGetAttributePtr(ae, keyEventClassAttr, typeType, 0, &aeClass, sizeof(aeClass), 0); + AEGetAttributePtr(ae, keyEventIDAttr, typeType, 0, &aeID, sizeof(aeID), 0); + + if (aeClass == kCoreEventClass && aeID == kAEReopenApplication) + { + // User clicked on Uniboard in the Dock + ((UBApplicationController*)handlerRefCon)->hideDesktop(); + return noErr; + } + + return eventNotHandledErr; +} +#endif + UBApplication::UBApplication(const QString &id, int &argc, char **argv) : QtSingleApplication(id, argc, argv) , mPreferencesController(NULL) @@ -129,11 +154,17 @@ UBApplication::UBApplication(const QString &id, int &argc, char **argv) : QtSing connect(settings->appToolBarDisplayText, SIGNAL(changed(QVariant)), this, SLOT(toolBarDisplayTextChanged(QVariant))); updateProtoActionsState(); -#ifndef Q_OS_OSX +#ifndef Q_WS_MAC setWindowIcon(QIcon(":/images/OpenBoard.png")); #endif - setStyle("fusion"); + + //QApplication::setStyle(new UBStyle()); // Style is owned and deleted by the application + + //QApplication::setStyle(QStyleFactory::create("Fusion")); + + //UBStyle *style_appli new UBStyle(); + //QApplication::setStyle(style_appli); // Style is owned and deleted by the application QString css = UBFileSystemUtils::readTextFile(UBPlatformUtils::applicationResourcesDirectory() + "/etc/"+ qApp->applicationName()+".css"); if (css.length() > 0) @@ -183,13 +214,21 @@ UBApplication::~UBApplication() QString UBApplication::checkLanguageAvailabilityForSankore(QString &language) { QStringList availableTranslations = UBPlatformUtils::availableTranslations(); + //QStringList availableTranslations ;availableTranslations<< "OpenBoard_fr"; if(availableTranslations.contains(language,Qt::CaseInsensitive)) return language; else{ if(language.length() > 2){ QString shortLanguageCode = language.left(2); - if(availableTranslations.contains(shortLanguageCode,Qt::CaseInsensitive)) - return shortLanguageCode; + //if(availableTranslations.contains(shortLanguageCode,Qt::CaseInsensitive)) + bool find_lang = false; + foreach (const QString &str, availableTranslations) { + if (str.contains(shortLanguageCode)) + return shortLanguageCode; + } + + //if(availableTranslations.contains(shortLanguageCode)) + //return shortLanguageCode; } } return QString(""); @@ -209,6 +248,12 @@ void UBApplication::setupTranslators(QStringList args) // forcedLanguage = setLanguage; // } + else{ + QString setLanguage = UBSettings::settings()->appPreferredLanguage->get().toString(); + if(!setLanguage.isEmpty()) + forcedLanguage = setLanguage; + } + QString language(""); if(!forcedLanguage.isEmpty()) @@ -216,6 +261,7 @@ void UBApplication::setupTranslators(QStringList args) if(language.isEmpty()){ QString systemLanguage = UBPlatformUtils::systemLanguage(); + //QString systemLanguage = "fr_CH"; language = checkLanguageAvailabilityForSankore(systemLanguage); } @@ -313,7 +359,7 @@ int UBApplication::exec(const QString& pFileToImport) connect(mainWindow->actionDesktop, SIGNAL(triggered(bool)), applicationController, SLOT(showDesktop(bool))); connect(mainWindow->actionDesktop, SIGNAL(triggered(bool)), this, SLOT(stopScript())); -#ifndef Q_OS_OSX +#ifndef Q_WS_MAC connect(mainWindow->actionHideApplication, SIGNAL(triggered()), mainWindow, SLOT(showMinimized())); #else connect(mainWindow->actionHideApplication, SIGNAL(triggered()), this, SLOT(showMinimized())); @@ -343,6 +389,11 @@ int UBApplication::exec(const QString& pFileToImport) if (pFileToImport.length() > 0) UBApplication::applicationController->importFile(pFileToImport); +#if defined(Q_OS_OSX) + static AEEventHandlerUPP ub_proc_ae_handlerUPP = AEEventHandlerUPP(ub_appleEventProcessor); + AEInstallEventHandler(kCoreEventClass, kAEReopenApplication, ub_proc_ae_handlerUPP, SRefCon(UBApplication::applicationController), true); +#endif + if (UBSettings::settings()->appStartMode->get().toInt()) applicationController->showDesktop(); else @@ -360,14 +411,14 @@ void UBApplication::onScreenCountChanged(int newCount) mainWindow->actionMultiScreen->setEnabled(displayManager.numScreens() > 1); } +#ifdef Q_WS_MAC void UBApplication::showMinimized() { -#ifdef Q_OS_OSX mainWindow->hide(); bIsMinimized = true; -#endif } +#endif void UBApplication::startScript() { @@ -509,7 +560,7 @@ void UBApplication::decorateActionMenu(QAction* action) menu->addSeparator(); -#ifndef Q_OS_LINUX // No Podcast on Linux yet +#ifndef Q_WS_X11 // No Podcast on Linux yet menu->addAction(mainWindow->actionPodcast); mainWindow->actionPodcast->setText(tr("Podcast")); #endif @@ -560,7 +611,11 @@ bool UBApplication::eventFilter(QObject *obj, QEvent *event) { QFileOpenEvent *fileToOpenEvent = static_cast(event); - UBPlatformUtils::setFrontProcess(); +#if defined(Q_WS_MACX) + ProcessSerialNumber psn; + GetCurrentProcess(&psn); + SetFrontProcess(&psn); +#endif applicationController->importFile(fileToOpenEvent->file()); } @@ -577,7 +632,7 @@ bool UBApplication::eventFilter(QObject *obj, QEvent *event) boardController->controlView()->setMultiselection(false); } -#ifdef Q_OS_OSX +#ifdef Q_WS_MAC if (bIsMinimized && event->type() == QEvent::ApplicationActivate){ if (mainWindow->isHidden()) mainWindow->show(); bIsMinimized = false; @@ -617,6 +672,39 @@ void UBApplication::cleanup() documentController = NULL; } +void UBStyle::drawItemText(QPainter *painter, const QRect &rect, int alignment, const QPalette &pal, + bool enabled, const QString& text, QPalette::ColorRole textRole) const +{ + if (text.isEmpty()) + return; + + QPen savedPen; + if (textRole != QPalette::NoRole) + { + savedPen = painter->pen(); + painter->setPen(QPen(pal.brush(textRole), savedPen.widthF())); + } + + if (!enabled) + { + QPen pen = painter->pen(); + QColor half = pen.color(); + + half.setRed(half.red() / 2); + half.setGreen(half.green() / 2); + half.setBlue(half.blue() / 2); + + painter->setPen(half); + painter->drawText(rect, alignment, text); + painter->setPen(pen); + } + + painter->drawText(rect, alignment, text); + + if (textRole != QPalette::NoRole) + painter->setPen(savedPen); +} + QString UBApplication::urlFromHtml(QString html) { QString _html; @@ -646,7 +734,8 @@ bool UBApplication::isFromWeb(QString url) { bool res = true; - if( url.startsWith("openboardtool://") || + if( //url.startsWith("uniboardTool://") || + url.startsWith("OpenboardTool://") || url.startsWith("file://") || url.startsWith("/")){ res = false; From 3c44bfb94a46ac004a3ea340dad3761ff480b1d9 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Wed, 9 Dec 2015 12:08:45 +0100 Subject: [PATCH 043/243] Removed old debug messages --- src/board/UBBoardView.cpp | 1 - src/domain/UBSelectionFrame.cpp | 4 ---- 2 files changed, 5 deletions(-) diff --git a/src/board/UBBoardView.cpp b/src/board/UBBoardView.cpp index 57b61d6f..670ee9e3 100644 --- a/src/board/UBBoardView.cpp +++ b/src/board/UBBoardView.cpp @@ -1083,7 +1083,6 @@ void UBBoardView::mouseMoveEvent (QMouseEvent *event) // QTime mouseMoveTime = QTime::currentTime(); if(!mIsDragInProgress && ((mapToScene(event->pos()) - mLastPressedMousePos).manhattanLength() < QApplication::startDragDistance())) { - qDebug() << "mouse move event canceled"; return; } diff --git a/src/domain/UBSelectionFrame.cpp b/src/domain/UBSelectionFrame.cpp index 89da1c6d..653e50f2 100644 --- a/src/domain/UBSelectionFrame.cpp +++ b/src/domain/UBSelectionFrame.cpp @@ -243,9 +243,6 @@ void UBSelectionFrame::mouseReleaseEvent(QGraphicsSceneMouseEvent */*event*/) void UBSelectionFrame::onZoomChanged(qreal pZoom) { - qDebug() << "Pzoom" << pZoom; - qDebug() << "Board current zoom" << UBApplication::boardController->currentZoom(); - qDebug() << "UBApplication::boardController->systemScaleFactor()" << UBApplication::boardController->systemScaleFactor(); mAntiscaleRatio = 1 / (UBApplication::boardController->systemScaleFactor() * pZoom); } @@ -458,7 +455,6 @@ QList UBSelectionFrame::sortedByZ(const QList & QList UBSelectionFrame::buttonsForFlags(UBGraphicsFlags fls) { - qDebug() << "buttons for flags" << QString::number((int)fls, 2); QList result; if (!mDeleteButton) { From 4d74341c689ffad7644c88127f845ea59eb0581a Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Wed, 9 Dec 2015 12:12:01 +0100 Subject: [PATCH 044/243] Fixed pen strokes' zLevels not being saved to file (Issue #12) --- src/adaptors/UBSvgSubsetAdaptor.cpp | 2 +- src/domain/UBGraphicsScene.cpp | 4 ++++ src/domain/UBGraphicsStrokesGroup.cpp | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/adaptors/UBSvgSubsetAdaptor.cpp b/src/adaptors/UBSvgSubsetAdaptor.cpp index 2ba03817..bfd1a0b0 100644 --- a/src/adaptors/UBSvgSubsetAdaptor.cpp +++ b/src/adaptors/UBSvgSubsetAdaptor.cpp @@ -1111,7 +1111,7 @@ bool UBSvgSubsetAdaptor::UBSvgSubsetWriter::persistScene(int pageIndex) if (colorOnDarkBackground.isValid() && colorOnLightBackground.isValid()) { mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "z-value" - , QString("%1").arg(polygonItem->zValue())); + , QString("%1").arg(polygonItem->strokesGroup()->zValue())); mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri , "fill-on-dark-background", colorOnDarkBackground.name()); diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index 63197044..a9acebbd 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -262,6 +262,10 @@ qreal UBZLayerController::changeZLevelTo(QGraphicsItem *item, moveDestination de } //Return new z value assigned to item + + // experimental + item->setZValue(item->data(UBGraphicsItemData::ItemOwnZValue).toReal()); + return item->data(UBGraphicsItemData::ItemOwnZValue).toReal(); } diff --git a/src/domain/UBGraphicsStrokesGroup.cpp b/src/domain/UBGraphicsStrokesGroup.cpp index b7eb51c3..e5aa0884 100644 --- a/src/domain/UBGraphicsStrokesGroup.cpp +++ b/src/domain/UBGraphicsStrokesGroup.cpp @@ -185,6 +185,7 @@ void UBGraphicsStrokesGroup::copyItemParameters(UBItem *copy) const cp->setFlag(QGraphicsItem::ItemIsSelectable, true); cp->setData(UBGraphicsItemData::ItemLayerType, this->data(UBGraphicsItemData::ItemLayerType)); cp->setData(UBGraphicsItemData::ItemLocked, this->data(UBGraphicsItemData::ItemLocked)); + cp->setZValue(this->zValue()); } } From 88f8a7bc5b051f72f6a44dae9b2b3e3208dae67b Mon Sep 17 00:00:00 2001 From: agriche Date: Wed, 9 Dec 2015 12:25:20 +0100 Subject: [PATCH 045/243] Revert "- Take in account the local systeme language." This reverts commit fb05343ed2a0bba470f3c5a9a55486d8ed051eb7. --- src/core/UBApplication.cpp | 117 +++++-------------------------------- 1 file changed, 14 insertions(+), 103 deletions(-) diff --git a/src/core/UBApplication.cpp b/src/core/UBApplication.cpp index 89ac932c..7c959167 100644 --- a/src/core/UBApplication.cpp +++ b/src/core/UBApplication.cpp @@ -27,15 +27,11 @@ #include "UBApplication.h" -#include - +#include #include #include #include - -#if defined(Q_WS_MACX) -#include -#endif +#include #include "frameworks/UBPlatformUtils.h" #include "frameworks/UBFileSystemUtils.h" @@ -85,33 +81,12 @@ 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"); -#ifdef Q_WS_MAC +#ifdef Q_OS_OSX bool bIsMinimized = false; #endif QObject* UBApplication::staticMemoryCleaner = 0; -#if defined(Q_WS_MAC) -static OSStatus ub_appleEventProcessor(const AppleEvent *ae, AppleEvent *event, long handlerRefCon) -{ - Q_UNUSED(event); - OSType aeID = typeWildCard; - OSType aeClass = typeWildCard; - - AEGetAttributePtr(ae, keyEventClassAttr, typeType, 0, &aeClass, sizeof(aeClass), 0); - AEGetAttributePtr(ae, keyEventIDAttr, typeType, 0, &aeID, sizeof(aeID), 0); - - if (aeClass == kCoreEventClass && aeID == kAEReopenApplication) - { - // User clicked on Uniboard in the Dock - ((UBApplicationController*)handlerRefCon)->hideDesktop(); - return noErr; - } - - return eventNotHandledErr; -} -#endif - UBApplication::UBApplication(const QString &id, int &argc, char **argv) : QtSingleApplication(id, argc, argv) , mPreferencesController(NULL) @@ -154,17 +129,11 @@ UBApplication::UBApplication(const QString &id, int &argc, char **argv) : QtSing connect(settings->appToolBarDisplayText, SIGNAL(changed(QVariant)), this, SLOT(toolBarDisplayTextChanged(QVariant))); updateProtoActionsState(); -#ifndef Q_WS_MAC +#ifndef Q_OS_OSX setWindowIcon(QIcon(":/images/OpenBoard.png")); #endif - - //QApplication::setStyle(new UBStyle()); // Style is owned and deleted by the application - - //QApplication::setStyle(QStyleFactory::create("Fusion")); - - //UBStyle *style_appli new UBStyle(); - //QApplication::setStyle(style_appli); // Style is owned and deleted by the application + setStyle("fusion"); QString css = UBFileSystemUtils::readTextFile(UBPlatformUtils::applicationResourcesDirectory() + "/etc/"+ qApp->applicationName()+".css"); if (css.length() > 0) @@ -214,21 +183,13 @@ UBApplication::~UBApplication() QString UBApplication::checkLanguageAvailabilityForSankore(QString &language) { QStringList availableTranslations = UBPlatformUtils::availableTranslations(); - //QStringList availableTranslations ;availableTranslations<< "OpenBoard_fr"; if(availableTranslations.contains(language,Qt::CaseInsensitive)) return language; else{ if(language.length() > 2){ QString shortLanguageCode = language.left(2); - //if(availableTranslations.contains(shortLanguageCode,Qt::CaseInsensitive)) - bool find_lang = false; - foreach (const QString &str, availableTranslations) { - if (str.contains(shortLanguageCode)) - return shortLanguageCode; - } - - //if(availableTranslations.contains(shortLanguageCode)) - //return shortLanguageCode; + if(availableTranslations.contains(shortLanguageCode,Qt::CaseInsensitive)) + return shortLanguageCode; } } return QString(""); @@ -248,12 +209,6 @@ void UBApplication::setupTranslators(QStringList args) // forcedLanguage = setLanguage; // } - else{ - QString setLanguage = UBSettings::settings()->appPreferredLanguage->get().toString(); - if(!setLanguage.isEmpty()) - forcedLanguage = setLanguage; - } - QString language(""); if(!forcedLanguage.isEmpty()) @@ -261,7 +216,6 @@ void UBApplication::setupTranslators(QStringList args) if(language.isEmpty()){ QString systemLanguage = UBPlatformUtils::systemLanguage(); - //QString systemLanguage = "fr_CH"; language = checkLanguageAvailabilityForSankore(systemLanguage); } @@ -359,7 +313,7 @@ int UBApplication::exec(const QString& pFileToImport) connect(mainWindow->actionDesktop, SIGNAL(triggered(bool)), applicationController, SLOT(showDesktop(bool))); connect(mainWindow->actionDesktop, SIGNAL(triggered(bool)), this, SLOT(stopScript())); -#ifndef Q_WS_MAC +#ifndef Q_OS_OSX connect(mainWindow->actionHideApplication, SIGNAL(triggered()), mainWindow, SLOT(showMinimized())); #else connect(mainWindow->actionHideApplication, SIGNAL(triggered()), this, SLOT(showMinimized())); @@ -389,11 +343,6 @@ int UBApplication::exec(const QString& pFileToImport) if (pFileToImport.length() > 0) UBApplication::applicationController->importFile(pFileToImport); -#if defined(Q_OS_OSX) - static AEEventHandlerUPP ub_proc_ae_handlerUPP = AEEventHandlerUPP(ub_appleEventProcessor); - AEInstallEventHandler(kCoreEventClass, kAEReopenApplication, ub_proc_ae_handlerUPP, SRefCon(UBApplication::applicationController), true); -#endif - if (UBSettings::settings()->appStartMode->get().toInt()) applicationController->showDesktop(); else @@ -411,14 +360,14 @@ void UBApplication::onScreenCountChanged(int newCount) mainWindow->actionMultiScreen->setEnabled(displayManager.numScreens() > 1); } -#ifdef Q_WS_MAC void UBApplication::showMinimized() { +#ifdef Q_OS_OSX mainWindow->hide(); bIsMinimized = true; +#endif } -#endif void UBApplication::startScript() { @@ -560,7 +509,7 @@ void UBApplication::decorateActionMenu(QAction* action) menu->addSeparator(); -#ifndef Q_WS_X11 // No Podcast on Linux yet +#ifndef Q_OS_LINUX // No Podcast on Linux yet menu->addAction(mainWindow->actionPodcast); mainWindow->actionPodcast->setText(tr("Podcast")); #endif @@ -611,11 +560,7 @@ bool UBApplication::eventFilter(QObject *obj, QEvent *event) { QFileOpenEvent *fileToOpenEvent = static_cast(event); -#if defined(Q_WS_MACX) - ProcessSerialNumber psn; - GetCurrentProcess(&psn); - SetFrontProcess(&psn); -#endif + UBPlatformUtils::setFrontProcess(); applicationController->importFile(fileToOpenEvent->file()); } @@ -632,7 +577,7 @@ bool UBApplication::eventFilter(QObject *obj, QEvent *event) boardController->controlView()->setMultiselection(false); } -#ifdef Q_WS_MAC +#ifdef Q_OS_OSX if (bIsMinimized && event->type() == QEvent::ApplicationActivate){ if (mainWindow->isHidden()) mainWindow->show(); bIsMinimized = false; @@ -672,39 +617,6 @@ void UBApplication::cleanup() documentController = NULL; } -void UBStyle::drawItemText(QPainter *painter, const QRect &rect, int alignment, const QPalette &pal, - bool enabled, const QString& text, QPalette::ColorRole textRole) const -{ - if (text.isEmpty()) - return; - - QPen savedPen; - if (textRole != QPalette::NoRole) - { - savedPen = painter->pen(); - painter->setPen(QPen(pal.brush(textRole), savedPen.widthF())); - } - - if (!enabled) - { - QPen pen = painter->pen(); - QColor half = pen.color(); - - half.setRed(half.red() / 2); - half.setGreen(half.green() / 2); - half.setBlue(half.blue() / 2); - - painter->setPen(half); - painter->drawText(rect, alignment, text); - painter->setPen(pen); - } - - painter->drawText(rect, alignment, text); - - if (textRole != QPalette::NoRole) - painter->setPen(savedPen); -} - QString UBApplication::urlFromHtml(QString html) { QString _html; @@ -734,8 +646,7 @@ bool UBApplication::isFromWeb(QString url) { bool res = true; - if( //url.startsWith("uniboardTool://") || - url.startsWith("OpenboardTool://") || + if( url.startsWith("openboardtool://") || url.startsWith("file://") || url.startsWith("/")){ res = false; From 5a1468a77a5afd117b56d198aa95f4e60aaab02b Mon Sep 17 00:00:00 2001 From: agriche Date: Wed, 9 Dec 2015 12:50:36 +0100 Subject: [PATCH 046/243] - Take in account the system language. --- src/core/UBApplication.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/core/UBApplication.cpp b/src/core/UBApplication.cpp index 7c959167..b518e491 100644 --- a/src/core/UBApplication.cpp +++ b/src/core/UBApplication.cpp @@ -183,13 +183,20 @@ UBApplication::~UBApplication() QString UBApplication::checkLanguageAvailabilityForSankore(QString &language) { QStringList availableTranslations = UBPlatformUtils::availableTranslations(); + //QStringList availableTranslations ;availableTranslations<< "OpenBoard_fr"; if(availableTranslations.contains(language,Qt::CaseInsensitive)) return language; else{ if(language.length() > 2){ QString shortLanguageCode = language.left(2); - if(availableTranslations.contains(shortLanguageCode,Qt::CaseInsensitive)) - return shortLanguageCode; + //if(availableTranslations.contains(shortLanguageCode,Qt::CaseInsensitive)) + foreach (const QString &str, availableTranslations) { + if (str.contains(shortLanguageCode)) + return shortLanguageCode; + } + + //if(availableTranslations.contains(shortLanguageCode)) + //return shortLanguageCode; } } return QString(""); From 67522011547617a272cf2cdb3d23ff92ea5d750c Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Wed, 9 Dec 2015 13:02:14 +0100 Subject: [PATCH 047/243] Fixed saving of all graphicsItems' zValues Simply added copying of zValue to the deep copy functions. As tested on OSX, this does pose any problems when duplicating an item on-page (i.e generating a new item with a zValue equal to its original). --- src/domain/UBGraphicsMediaItem.cpp | 2 ++ src/domain/UBGraphicsPDFItem.cpp | 1 + src/domain/UBGraphicsPixmapItem.cpp | 2 ++ src/domain/UBGraphicsSvgItem.cpp | 1 + src/domain/UBGraphicsTextItem.cpp | 1 + src/domain/UBGraphicsWidgetItem.cpp | 1 + 6 files changed, 8 insertions(+) diff --git a/src/domain/UBGraphicsMediaItem.cpp b/src/domain/UBGraphicsMediaItem.cpp index ec3bcd57..ad9dcfeb 100644 --- a/src/domain/UBGraphicsMediaItem.cpp +++ b/src/domain/UBGraphicsMediaItem.cpp @@ -275,6 +275,8 @@ void UBGraphicsMediaItem::copyItemParameters(UBItem *copy) const cp->setSourceUrl(this->sourceUrl()); cp->resize(this->size()); + cp->setZValue(this->zValue()); + connect(UBApplication::boardController, SIGNAL(activeSceneChanged()), cp, SLOT(activeSceneChanged())); // TODO UB 4.7 complete all members } diff --git a/src/domain/UBGraphicsPDFItem.cpp b/src/domain/UBGraphicsPDFItem.cpp index 03bb763c..09e68b9a 100644 --- a/src/domain/UBGraphicsPDFItem.cpp +++ b/src/domain/UBGraphicsPDFItem.cpp @@ -122,6 +122,7 @@ void UBGraphicsPDFItem::copyItemParameters(UBItem *copy) const cp->setFlag(QGraphicsItem::ItemIsSelectable, true); cp->setData(UBGraphicsItemData::ItemLayerType, this->data(UBGraphicsItemData::ItemLayerType)); cp->setSourceUrl(this->sourceUrl()); + cp->setZValue(this->zValue()); } } diff --git a/src/domain/UBGraphicsPixmapItem.cpp b/src/domain/UBGraphicsPixmapItem.cpp index be1a3551..44a532d5 100644 --- a/src/domain/UBGraphicsPixmapItem.cpp +++ b/src/domain/UBGraphicsPixmapItem.cpp @@ -156,6 +156,8 @@ void UBGraphicsPixmapItem::copyItemParameters(UBItem *copy) const cp->setData(UBGraphicsItemData::ItemLayerType, this->data(UBGraphicsItemData::ItemLayerType)); cp->setData(UBGraphicsItemData::ItemLocked, this->data(UBGraphicsItemData::ItemLocked)); cp->setSourceUrl(this->sourceUrl()); + + cp->setZValue(this->zValue()); } } diff --git a/src/domain/UBGraphicsSvgItem.cpp b/src/domain/UBGraphicsSvgItem.cpp index 8b8e6b82..172fd0c3 100644 --- a/src/domain/UBGraphicsSvgItem.cpp +++ b/src/domain/UBGraphicsSvgItem.cpp @@ -180,6 +180,7 @@ void UBGraphicsSvgItem::copyItemParameters(UBItem *copy) const cp->setData(UBGraphicsItemData::ItemLayerType, this->data(UBGraphicsItemData::ItemLayerType)); cp->setData(UBGraphicsItemData::ItemLocked, this->data(UBGraphicsItemData::ItemLocked)); cp->setSourceUrl(this->sourceUrl()); + cp->setZValue(this->zValue()); } } diff --git a/src/domain/UBGraphicsTextItem.cpp b/src/domain/UBGraphicsTextItem.cpp index a9f949b2..aa389856 100644 --- a/src/domain/UBGraphicsTextItem.cpp +++ b/src/domain/UBGraphicsTextItem.cpp @@ -280,6 +280,7 @@ void UBGraphicsTextItem::copyItemParameters(UBItem *copy) const cp->setTextHeight(this->textHeight()); cp->setSourceUrl(this->sourceUrl()); + cp->setZValue(this->zValue()); } } diff --git a/src/domain/UBGraphicsWidgetItem.cpp b/src/domain/UBGraphicsWidgetItem.cpp index 9ec12d59..757f0c63 100644 --- a/src/domain/UBGraphicsWidgetItem.cpp +++ b/src/domain/UBGraphicsWidgetItem.cpp @@ -744,6 +744,7 @@ void UBGraphicsAppleWidgetItem::copyItemParameters(UBItem *copy) const } cp->setSourceUrl(this->sourceUrl()); + cp->setZValue(this->zValue()); } } From 64002a17063f2068e8af59f5a5cfb76c04681549 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Wed, 9 Dec 2015 15:03:24 +0100 Subject: [PATCH 048/243] Set zValue during deepCopy for W3C widget and curtain item --- src/domain/UBGraphicsWidgetItem.cpp | 2 ++ src/tools/UBGraphicsCurtainItem.cpp | 1 + 2 files changed, 3 insertions(+) diff --git a/src/domain/UBGraphicsWidgetItem.cpp b/src/domain/UBGraphicsWidgetItem.cpp index 757f0c63..6dabaeec 100644 --- a/src/domain/UBGraphicsWidgetItem.cpp +++ b/src/domain/UBGraphicsWidgetItem.cpp @@ -1229,6 +1229,8 @@ void UBGraphicsW3CWidgetItem::copyItemParameters(UBItem *copy) const { cp->setDatastoreEntry(key, mDatastore.value(key)); } + + cp->setZValue(this->zValue()); } } diff --git a/src/tools/UBGraphicsCurtainItem.cpp b/src/tools/UBGraphicsCurtainItem.cpp index 93389975..9e7c512d 100644 --- a/src/tools/UBGraphicsCurtainItem.cpp +++ b/src/tools/UBGraphicsCurtainItem.cpp @@ -167,6 +167,7 @@ void UBGraphicsCurtainItem::copyItemParameters(UBItem *copy) const cp->setFlag(QGraphicsItem::ItemIsMovable, true); cp->setFlag(QGraphicsItem::ItemIsSelectable, true); cp->setData(UBGraphicsItemData::ItemLayerType, this->data(UBGraphicsItemData::ItemLayerType)); + cp->setZValue(this->zValue()); } } From c266165af32bc47782fea4704980c0f698b09fa6 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Thu, 10 Dec 2015 12:59:36 +0100 Subject: [PATCH 049/243] Updated version number (1.10alpha1 release) --- OpenBoard.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenBoard.pro b/OpenBoard.pro index bcaf956d..fdde384c 100644 --- a/OpenBoard.pro +++ b/OpenBoard.pro @@ -11,7 +11,7 @@ CONFIG += debug_and_release \ VERSION_MAJ = 1 VERSION_MIN = 1 VERSION_TYPE = a # a = alpha, b = beta, rc = release candidate, r = release, other => error -VERSION_PATCH = 0 +VERSION_PATCH = 1 VERSION = "$${VERSION_MAJ}.$${VERSION_MIN}.$${VERSION_TYPE}.$${VERSION_PATCH}" VERSION = $$replace(VERSION, "\\.r", "") From 82e5f92ca611f19c83ab7e07fc9aad4201d2384a Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Thu, 10 Dec 2015 13:00:27 +0100 Subject: [PATCH 050/243] Fixed bad video URL encoding in .svg --- src/adaptors/UBSvgSubsetAdaptor.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/adaptors/UBSvgSubsetAdaptor.cpp b/src/adaptors/UBSvgSubsetAdaptor.cpp index bfd1a0b0..840747fa 100644 --- a/src/adaptors/UBSvgSubsetAdaptor.cpp +++ b/src/adaptors/UBSvgSubsetAdaptor.cpp @@ -2012,11 +2012,7 @@ void UBSvgSubsetAdaptor::UBSvgSubsetWriter::videoItemToLinkedVideo(UBGraphicsMed mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "position", QString("%1").arg(pos)); } - QString videoFileHref = videoItem->mediaFileUrl().toString(); - - videoFileHref = UBFileSystemUtils::removeLocalFilePrefix(videoFileHref); - if(videoFileHref.startsWith(mDocumentPath)) - videoFileHref = videoFileHref.replace(mDocumentPath + "/",""); + QString videoFileHref = "videos/" + videoItem->mediaFileUrl().fileName(); mXmlWriter.writeAttribute(nsXLink, "href", videoFileHref); mXmlWriter.writeEndElement(); From c220bf470f704c0ca047eaa7fd886b5a4090d2a1 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Thu, 10 Dec 2015 13:44:58 +0100 Subject: [PATCH 051/243] Fix bad URL encoding in .svg --- src/adaptors/UBSvgSubsetAdaptor.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/adaptors/UBSvgSubsetAdaptor.cpp b/src/adaptors/UBSvgSubsetAdaptor.cpp index 840747fa..48fc20b4 100644 --- a/src/adaptors/UBSvgSubsetAdaptor.cpp +++ b/src/adaptors/UBSvgSubsetAdaptor.cpp @@ -1983,10 +1983,7 @@ void UBSvgSubsetAdaptor::UBSvgSubsetWriter::audioItemToLinkedAudio(UBGraphicsMed mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "position", QString("%1").arg(pos)); } - QString audioFileHref = audioItem->mediaFileUrl().toString(); - audioFileHref = UBFileSystemUtils::removeLocalFilePrefix(audioFileHref); - if(audioFileHref.startsWith(mDocumentPath)) - audioFileHref = audioFileHref.replace(mDocumentPath + "/",""); + QString audioFileHref = "audios/" + audioItem->mediaFileUrl().fileName(); mXmlWriter.writeAttribute(nsXLink, "href", audioFileHref); mXmlWriter.writeEndElement(); @@ -2225,7 +2222,7 @@ void UBSvgSubsetAdaptor::UBSvgSubsetWriter::graphicsItemToSvg(QGraphicsItem* ite QUrl sourceUrl = ubItem->sourceUrl(); if (!sourceUrl.isEmpty()) - mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "source", sourceUrl.toString()); + mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "source", sourceUrl.path()); } @@ -2285,8 +2282,10 @@ void UBSvgSubsetAdaptor::UBSvgSubsetWriter::graphicsWidgetToSvg(UBGraphicsWidget widgetRootUrl = widgetTargetDir; } + QString widgetPath = "widgets/" + widgetRootUrl.fileName(); + mXmlWriter.writeStartElement("foreignObject"); - mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "src", widgetRootUrl.toString()); + mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "src", widgetPath); graphicsItemToSvg(item); @@ -2307,6 +2306,8 @@ void UBSvgSubsetAdaptor::UBSvgSubsetWriter::graphicsWidgetToSvg(UBGraphicsWidget else startFileUrl = widgetRootUrl.toString() + "/" + item->mainHtmlFileName(); + startFileUrl = QUrl::fromPercentEncoding(startFileUrl.toUtf8()); + mXmlWriter.writeAttribute("src", startFileUrl); mXmlWriter.writeEndElement(); //iFrame From 76636f73d7216f9265cefa35d7ad56a4172693ca Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Fri, 11 Dec 2015 10:13:49 +0100 Subject: [PATCH 052/243] Fix video loading from file - Added an overload for setMatrix in UBGraphicsMediaItem, to propagate matrix changes to the child videoItem - Upon loading a video, the child videoItem is now added correctly, and set to the right position --- src/adaptors/UBSvgSubsetAdaptor.cpp | 5 +++++ src/domain/UBGraphicsMediaItem.cpp | 7 +++++++ src/domain/UBGraphicsMediaItem.h | 1 + 3 files changed, 13 insertions(+) diff --git a/src/adaptors/UBSvgSubsetAdaptor.cpp b/src/adaptors/UBSvgSubsetAdaptor.cpp index 48fc20b4..ecefa5b8 100644 --- a/src/adaptors/UBSvgSubsetAdaptor.cpp +++ b/src/adaptors/UBSvgSubsetAdaptor.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include "domain/UBGraphicsSvgItem.h" #include "domain/UBGraphicsPixmapItem.h" @@ -652,6 +653,10 @@ UBGraphicsScene* UBSvgSubsetAdaptor::UBSvgSubsetReader::loadScene() videoItem->setFlag(QGraphicsItem::ItemIsSelectable, true); mScene->addItem(videoItem); + mScene->addItem(videoItem->videoItem()); + + // Update the child QGraphicsVideoItem's transformation matrix + videoItem->setMatrix(videoItem->matrix()); videoItem->show(); diff --git a/src/domain/UBGraphicsMediaItem.cpp b/src/domain/UBGraphicsMediaItem.cpp index ad9dcfeb..c3cf8ec6 100644 --- a/src/domain/UBGraphicsMediaItem.cpp +++ b/src/domain/UBGraphicsMediaItem.cpp @@ -353,6 +353,13 @@ void UBGraphicsMediaItem::setPos(qreal x, qreal y) setPos(QPointF(x, y)); } +void UBGraphicsMediaItem::setMatrix(const QMatrix &matrix, bool combine) +{ + QGraphicsItem::setMatrix(matrix, combine); + + if (mVideoItem) + mVideoItem->setMatrix(matrix, combine); +} void UBGraphicsMediaItem::setTransform(const QTransform &matrix, bool combine) { diff --git a/src/domain/UBGraphicsMediaItem.h b/src/domain/UBGraphicsMediaItem.h index 5846075b..e83facef 100644 --- a/src/domain/UBGraphicsMediaItem.h +++ b/src/domain/UBGraphicsMediaItem.h @@ -110,6 +110,7 @@ public: virtual void setPos(const QPointF &pos); virtual void setPos(qreal x, qreal y); + virtual void setMatrix(const QMatrix &matrix, bool combine = false); virtual void setTransform(const QTransform &matrix, bool combine = false); virtual void resize(qreal w, qreal h); virtual void resize(const QSizeF & pSize); From d6503534db69aee2044354706b2ef044c686704b Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Fri, 11 Dec 2015 12:58:09 +0100 Subject: [PATCH 053/243] Fixed duplication of groups Previously, duplication did not copy the transformation matrices of group members correctly. This made grouped objects move away when saving and re-opening a document. This should now be fixed. --- src/domain/UBGraphicsScene.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index a9acebbd..27bd0560 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -1114,11 +1114,11 @@ UBGraphicsScene* UBGraphicsScene::sceneDeepCopy() const UBGraphicsGroupContainerItem* groupCloned = group->deepCopyNoChildDuplication(); groupCloned->resetMatrix(); groupCloned->resetTransform(); + groupCloned->setMatrix(group->matrix()); + groupCloned->setTransform(group->transform()); + foreach(QGraphicsItem* eachItem ,group->childItems()){ QGraphicsItem* copiedChild = dynamic_cast(dynamic_cast(eachItem)->deepCopy()); - copiedChild->resetTransform(); - copiedChild->resetMatrix(); - copiedChild->setMatrix(eachItem->sceneMatrix()); copy->addItem(copiedChild); groupCloned->addToGroup(copiedChild); } From c6cc0d3a19d13b6255a6557488b31e63c16e3b61 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Fri, 11 Dec 2015 15:07:15 +0100 Subject: [PATCH 054/243] Fixed partial screenshot in desktop mode Note: the screenshot can only be taken on the primary display now (rather than on the display in which the mouse is, as was the case before). --- src/desktop/UBCustomCaptureWindow.cpp | 3 +-- src/desktop/UBDesktopAnnotationController.cpp | 8 +++----- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/desktop/UBCustomCaptureWindow.cpp b/src/desktop/UBCustomCaptureWindow.cpp index 36e8969b..19e3434a 100644 --- a/src/desktop/UBCustomCaptureWindow.cpp +++ b/src/desktop/UBCustomCaptureWindow.cpp @@ -74,8 +74,7 @@ int UBCustomCaptureWindow::execute(const QPixmap &pScreenPixmap) QDesktopWidget *desktop = QApplication::desktop(); int currentScreen = desktop->screenNumber(QCursor::pos()); setGeometry(desktop->screenGeometry(currentScreen)); - - UBPlatformUtils::showFullScreen(this); + this->show(); setWindowOpacity(1.0); return exec(); diff --git a/src/desktop/UBDesktopAnnotationController.cpp b/src/desktop/UBDesktopAnnotationController.cpp index 879b39e4..cc15b94a 100644 --- a/src/desktop/UBDesktopAnnotationController.cpp +++ b/src/desktop/UBDesktopAnnotationController.cpp @@ -501,12 +501,10 @@ QPixmap UBDesktopAnnotationController::getScreenPixmap() { QDesktopWidget *desktop = QApplication::desktop(); - // we capture the screen in which the mouse is. - const QRect primaryScreenRect = desktop->screenGeometry(QCursor::pos()); - QCoreApplication::flush(); - return QPixmap::grabWindow(desktop->winId(), primaryScreenRect.x() - , primaryScreenRect.y(), primaryScreenRect.width(), primaryScreenRect.height()); + QScreen * screen = QApplication::primaryScreen(); + return screen->grabWindow(desktop->effectiveWinId()); + } From 8ae88cfcb35c35a13fd02269c06773da80f058ce Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Mon, 14 Dec 2015 11:53:45 +0100 Subject: [PATCH 055/243] Fix compilation error on windows (inheritance prob.) --- src/domain/UBGraphicsWidgetItem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/domain/UBGraphicsWidgetItem.cpp b/src/domain/UBGraphicsWidgetItem.cpp index 6dabaeec..cfa974da 100644 --- a/src/domain/UBGraphicsWidgetItem.cpp +++ b/src/domain/UBGraphicsWidgetItem.cpp @@ -1220,7 +1220,7 @@ void UBGraphicsW3CWidgetItem::copyItemParameters(UBItem *copy) const cp->resize(this->size()); - foreach(QString key, UBGraphicsWidgetItem::preferences().keys()) + foreach(QString key, this->UBGraphicsWidgetItem::preferences().keys()) { cp->setPreference(key, UBGraphicsWidgetItem::preferences().value(key)); } From 2fa97ecf796b18918b9ad85dcbaf889c32dac76e Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Mon, 14 Dec 2015 11:54:15 +0100 Subject: [PATCH 056/243] Updated release scripts for Windows --- OpenBoard.iss | 102 ++++++++++++++++++++++++++----------------- release.win7.vc9.bat | 16 +++---- 2 files changed, 70 insertions(+), 48 deletions(-) diff --git a/OpenBoard.iss b/OpenBoard.iss index 0a2e0f29..bc55ba00 100644 --- a/OpenBoard.iss +++ b/OpenBoard.iss @@ -8,7 +8,7 @@ ; NOTE: The value of AppId uniquely identifies this application. ; Do not use the same AppId value in installers for other applications. ; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) -AppId={{F6E79ADE-83AE-4A2E-92D7-145BDC014271} +AppId={{8CCA6AC7-BBF9-4DD2-8E70-A907E0FCA38F}} AppName=OpenBoard AppVerName=OpenBoard {#ApplicationVersion} AppPublisher=Open Education Foundation @@ -46,58 +46,80 @@ Type: filesandordirs ; Name: "{app}\plugins" Type: filesandordirs ; Name: "{app}\i18n" Type: files ; Name: "{app}\*.dll" + +#define QtLibs GetEnv('QT_BIN') +#define QtDir GetEnv('QT_DIR') + [Files] Source: "..\OpenBoard-ThirdParty\microsoft\vcredist_x86.exe"; DestDir:"{tmp}" Source: "build\win32\release\product\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs ;OpenSSL -Source: "..\OpenBoard-ThirdParty\openssl\openssl-1.0.0d\out32dll\libeay32.dll"; DestDir:"{app}"; Flags: ignoreversion -Source: "..\OpenBoard-ThirdParty\openssl\openssl-1.0.0d\out32dll\ssleay32.dll"; DestDir:"{app}"; Flags: ignoreversion +Source: "..\OpenBoard-ThirdParty\openssl\openssl-1.0.2-win32\lib\libeay32.lib"; DestDir:"{app}"; Flags: ignoreversion +Source: "..\OpenBoard-ThirdParty\openssl\openssl-1.0.2-win32\lib\ssleay32.lib"; DestDir:"{app}"; Flags: ignoreversion ;Qt base dll -Source: "..\Qt-4.8\lib\QtScript4.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\Qt-4.8\lib\QtGui4.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\Qt-4.8\lib\QtXml4.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\Qt-4.8\lib\QtCore4.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\Qt-4.8\lib\QtWebKit4.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\Qt-4.8\lib\phonon4.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\Qt-4.8\lib\QtNetwork4.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\Qt-4.8\lib\QtSvg4.dll"; DestDir: "{app}"; Flags: ignoreversion - -;Qt plugins -Source: "..\Qt-4.8\plugins\accessible\qtaccessiblecompatwidgets4.dll"; DestDir: "{app}\accessible"; Flags: ignoreversion -Source: "..\Qt-4.8\plugins\accessible\qtaccessiblewidgets4.dll"; DestDir: "{app}\accessible"; Flags: ignoreversion -Source: "..\Qt-4.8\plugins\bearer\qgenericbearer4.dll"; DestDir: "{app}\bearer"; Flags: ignoreversion -Source: "..\Qt-4.8\plugins\bearer\qnativewifibearer4.dll"; DestDir: "{app}\bearer"; Flags: ignoreversion -Source: "..\Qt-4.8\plugins\codecs\qcncodecs4.dll"; DestDir: "{app}\codecs"; Flags: ignoreversion -Source: "..\Qt-4.8\plugins\codecs\qjpcodecs4.dll"; DestDir: "{app}\codecs"; Flags: ignoreversion -Source: "..\Qt-4.8\plugins\codecs\qkrcodecs4.dll"; DestDir: "{app}\codecs"; Flags: ignoreversion -Source: "..\Qt-4.8\plugins\codecs\qtwcodecs4.dll"; DestDir: "{app}\codecs"; Flags: ignoreversion -Source: "..\Qt-4.8\plugins\graphicssystems\qglgraphicssystem4.dll"; DestDir: "{app}\graphicssystems"; Flags: ignoreversion -Source: "..\Qt-4.8\plugins\graphicssystems\qtracegraphicssystem4.dll"; DestDir: "{app}\graphicssystems"; Flags: ignoreversion -Source: "..\Qt-4.8\plugins\iconengines\qsvgicon4.dll"; DestDir: "{app}\iconengines"; Flags: ignoreversion -Source: "..\Qt-4.8\plugins\imageformats\qgif4.dll"; DestDir: "{app}\imageformats"; Flags: ignoreversion -Source: "..\Qt-4.8\plugins\imageformats\qico4.dll"; DestDir: "{app}\imageformats"; Flags: ignoreversion -Source: "..\Qt-4.8\plugins\imageformats\qjpeg4.dll"; DestDir: "{app}\imageformats"; Flags: ignoreversion -Source: "..\Qt-4.8\plugins\imageformats\qmng4.dll"; DestDir: "{app}\imageformats"; Flags: ignoreversion -Source: "..\Qt-4.8\plugins\imageformats\qsvg4.dll"; DestDir: "{app}\imageformats"; Flags: ignoreversion -Source: "..\Qt-4.8\plugins\imageformats\qtiff4.dll"; DestDir: "{app}\imageformats"; Flags: ignoreversion -Source: "..\Qt-4.8\plugins\phonon_backend\phonon_ds94.dll"; DestDir: "{app}\phonon_backend"; Flags: ignoreversion +;Source: "OpenBoard.exe"; DestDir: "{app}" +Source: "{#QtLibs}\Qt5Core.dll"; DestDir: "{app}" +Source: "{#QtLibs}\Qt5Gui.dll"; DestDir: "{app}" +Source: "{#QtLibs}\Qt5Multimedia.dll"; DestDir: "{app}" +Source: "{#QtLibs}\Qt5MultimediaWidgets.dll"; DestDir: "{app}" +Source: "{#QtLibs}\Qt5Network.dll"; DestDir: "{app}" +Source: "{#QtLibs}\Qt5Opengl.dll"; DestDir: "{app}" +Source: "{#QtLibs}\Qt5PrintSupport.dll"; DestDir: "{app}" +Source: "{#QtLibs}\Qt5Qml.dll"; DestDir: "{app}" +Source: "{#QtLibs}\Qt5Script.dll"; DestDir: "{app}" +Source: "{#QtLibs}\Qt5Sql.dll"; DestDir: "{app}" +Source: "{#QtLibs}\Qt5Svg.dll"; DestDir: "{app}" +;Source: "Qt5V8.dll"; DestDir: "{app}" +Source: "{#QtLibs}\Qt5WebKit.dll"; DestDir: "{app}" +Source: "{#QtLibs}\Qt5WebKitWidgets.dll"; DestDir: "{app}" +Source: "{#QtLibs}\Qt5Widgets.dll"; DestDir: "{app}" +Source: "{#QtLibs}\Qt5Xml.dll"; DestDir: "{app}" +Source: "{#QtLibs}\libGLESv2.dll"; DestDir: "{app}" +Source: "{#QtLibs}\Qt5Quick.dll"; DestDir: "{app}" +Source: "{#QtLibs}\Qt5Positioning.dll"; DestDir: "{app}" +Source: "{#QtLibs}\Qt5Sensors.dll"; DestDir: "{app}" +Source: "{#QtLibs}\Qt5WebChannel.dll"; DestDir: "{app}" +Source: "{#QtLibs}\libEGL.dll"; DestDir: "{app}" +;Source: "/etc/freezedWidgetWrapper.html"; DestDir: "{app}" +;Source: "*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs + +Source: "{#QtLibs}\icudt54.dll"; DestDir: "{app}" +Source: "{#QtLibs}\icuin54.dll"; DestDir: "{app}" +Source: "{#QtLibs}\icuuc54.dll"; DestDir: "{app}" + ; NOTE: Don't use "Flags: ignoreversion" on any shared system files -;qt multimedia plugins -Source: "c:\OpenBoard\plugins\mediaservice\qtmedia_audioengine.dll"; DestDir: "c:\OpenBoard\plugins\mediaservice"; Flags: ignoreversion -Source: "c:\OpenBoard\plugins\mediaservice\qtmedia_audioengined.dll"; DestDir: "c:\OpenBoard\plugins\mediaservice"; Flags: ignoreversion -Source: "c:\OpenBoard\plugins\mediaservice\dsengine.dll"; DestDir: "c:\OpenBoard\plugins\mediaservice"; Flags: ignoreversion -Source: "c:\OpenBoard\plugins\mediaservice\dsengined.dll"; DestDir: "c:\OpenBoard\plugins\mediaservice"; Flags: ignoreversion +;Qt windows plugins +Source: "{#QtDir}\plugins\platforms\qminimal.dll"; DestDir: "{app}\platforms"; Flags: ignoreversion +Source: "{#QtDir}\plugins\platforms\qoffscreen.dll"; DestDir: "{app}\platforms"; Flags: ignoreversion +Source: "{#QtDir}\plugins\platforms\qwindows.dll"; DestDir: "{app}\platforms"; Flags: ignoreversion -Source: "c:\OpenBoard\plugins\playlistformats\qtmultimediakit_m3u.dll"; DestDir: "c:\OpenBoard\plugins\playlistformats"; Flags: ignoreversion -Source: "c:\OpenBoard\plugins\playlistformats\qtmultimediakit_m3ud.dll"; DestDir: "c:\OpenBoard\plugins\playlistformats"; Flags: ignoreversion + +;Qt images formats plugins +Source: "{#QtDir}\plugins\imageformats\qgif.dll"; DestDir: "{app}\imageformats"; Flags: ignoreversion +Source: "{#QtDir}\plugins\imageformats\qico.dll"; DestDir: "{app}\imageformats"; Flags: ignoreversion +Source: "{#QtDir}\plugins\imageformats\qjpeg.dll"; DestDir: "{app}\imageformats"; Flags: ignoreversion +Source: "{#QtDir}\plugins\imageformats\qmng.dll"; DestDir: "{app}\imageformats"; Flags: ignoreversion +Source: "{#QtDir}\plugins\imageformats\qsvg.dll"; DestDir: "{app}\imageformats"; Flags: ignoreversion +Source: "{#QtDir}\plugins\imageformats\qtiff.dll"; DestDir: "{app}\imageformats"; Flags: ignoreversion + +;qt icon engine plugins +Source: "{#QtDir}\plugins\iconengines\qsvgicon.dll"; DestDir: "{app}\iconengines"; Flags: ignoreversion + +;qt multimedia plugins +Source: "{#QtDir}\plugins\mediaservice\dsengine.dll"; DestDir: "\plugins\mediaservice"; Flags: ignoreversion +Source: "{#QtDir}\plugins\mediaservice\dsengined.dll"; DestDir: "\plugins\mediaservice"; Flags: ignoreversion +Source: "{#QtDir}\plugins\mediaservice\qtmedia_audioengine.dll"; DestDir: "\plugins\mediaservice"; Flags: ignoreversion +Source: "{#QtDir}\plugins\mediaservice\qtmedia_audioengined.dll"; DestDir: "\plugins\mediaservice"; Flags: ignoreversion +Source: "{#QtDir}\plugins\mediaservice\wmfengine.dll"; DestDir: "\plugins\mediaservice"; Flags: ignoreversion +Source: "{#QtDir}\plugins\mediaservice\wmfengined.dll"; DestDir: "\plugins\mediaservice"; Flags: ignoreversion ;OpenBoardImporter Source: "..\OpenBoard-Importer\release\OpenBoardImporter.exe"; DestDir: "c:\OpenBoard\Importer"; Flags: ignoreversion -Source: "..\Qt-4.8\lib\QtGui4.dll"; DestDir: "c:\OpenBoard\Importer"; Flags: ignoreversion -Source: "..\Qt-4.8\lib\QtCore4.dll"; DestDir: "c:\OpenBoard\Importer"; Flags: ignoreversion +Source: "{#QtLibs}\Qt5Core.dll"; DestDir: "{app}" +Source: "{#QtLibs}\Qt5Gui.dll"; DestDir: "{app}" ;fonts for xpdf Source: "resources\windows\xpdfrc"; DestDir: "{app}"; Flags: ignoreversion diff --git a/release.win7.vc9.bat b/release.win7.vc9.bat index b53a6b22..0052307f 100644 --- a/release.win7.vc9.bat +++ b/release.win7.vc9.bat @@ -16,13 +16,13 @@ REM --------------------------------------------------------------------- set APPLICATION_NAME=OpenBoard -set QT_DIR=..\Qt-4.8 +set QT_DIR=C:\Qt\5.5\msvc2010 set QT_BIN=%QT_DIR%\bin -set PROGRAMS_FILE_PATH=C:\Program Files +set PROGRAMS_FILE_PATH=C:\Program Files (x86) set GIT_BIN=%PROGRAMS_FILE_PATH%\Git\bin -set VS_BIN=%PROGRAMS_FILE_PATH%\Microsoft Visual Studio 9.0\VC\bin +set VS_BIN=%PROGRAMS_FILE_PATH%\Microsoft Visual Studio 10.0\VC\bin set WIN_SDK_BIN=%PROGRAMS_FILE_PATH%\Microsoft SDKs\Windows\v6.0A\Bin set INNO_EXE=%PROGRAMS_FILE_PATH%\Inno Setup 5\iscc.exe set BUILD_DIR=build\win32\release @@ -37,7 +37,7 @@ echo %PATH% REM Third party impoter application set IMPORTER_NAME=OpenBoardImporter -set IMPORTER_PATH="%cd%\..\OpenBoard-Importer" +set IMPORTER_PATH="..\OpenBoard-Importer" IF NOT EXIST "%IMPORTER_PATH%" GOTO EXIT_WITH_ERROR set HOME_DIR="%cd%" @@ -47,7 +47,7 @@ IF EXIST "debug" (del "debug\*.*" /Q) IF EXIST "MakeFile" (del "MakeFile*" /Q) IF EXIST "MakeFile" (del "MakeFile*" /Q) IF EXIST "%IMPORTER_NAME%.exe" (del "%IMPORTER_NAME%.exe" /Q) -"%QT_BIN%\qmake.exe" %IMPORTER_NAME%.pro" +"%QT_BIN%\qmake.exe" %IMPORTER_NAME%.pro nmake release IF NOT EXIST release\"%IMPORTER_NAME%.exe" GOTO EXIT_WITH_ERROR cd %HOME_DIR% @@ -55,7 +55,7 @@ cd %HOME_DIR% REM this checks if the custom qt directory path REM is correct. This is important because installer REM pick up dll from this directory -IF NOT EXIST "%QT_DIR%\lib\QtCore4.dll" GOTO EXIT_WITH_ERROR +REM IF NOT EXIST "%QT_DIR%\bin\Qt5Core.dll" GOTO EXIT_WITH_ERROR rmdir /S /Q %BUILD_DIR% rmdir /S /Q install @@ -81,8 +81,8 @@ REM echo %LAST_TAG_VERSION% nmake release-install IF NOT EXIST build\win32\release\product\%APPLICATION_NAME%.exe GOTO EXIT_WITH_ERROR -xcopy C:\%APPLICATION_NAME%\lib\*.dll build\win32\release\product\ -xcopy %QT_DIR%\lib\QtOpenGL4.dll build\win32\release\product\ +xcopy C:\%APPLICATION_NAME%\bin\*.dll build\win32\release\product\ +xcopy %QT_DIR%\bin\Qt5OpenGL.dll build\win32\release\product\ set CUSTOMIZATIONS=build\win32\release\product\customizations mkdir %CUSTOMIZATIONS% From 2cec22c91dfd119a0b63b3fe6f28f4c6e0f3cb88 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Mon, 14 Dec 2015 16:49:35 +0100 Subject: [PATCH 057/243] Quick fix for issue #14 Page DPI is now saved as the DPI that was read when opening the file. While not a perfectly fool-proof fix, it will at least allow files to be migrated between OB 1.02 and 1.10. --- src/adaptors/UBSvgSubsetAdaptor.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/adaptors/UBSvgSubsetAdaptor.cpp b/src/adaptors/UBSvgSubsetAdaptor.cpp index ecefa5b8..5a38311e 100644 --- a/src/adaptors/UBSvgSubsetAdaptor.cpp +++ b/src/adaptors/UBSvgSubsetAdaptor.cpp @@ -1034,7 +1034,11 @@ void UBSvgSubsetAdaptor::UBSvgSubsetWriter::writeSvgElement() mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "crossed-background", mScene->isCrossedBackground() ? xmlTrue : xmlFalse); QDesktopWidget* desktop = UBApplication::desktop(); - mXmlWriter.writeAttribute("pageDpi", QString("%1").arg((desktop->physicalDpiX() + desktop->physicalDpiY()) / 2)); + + if (UBSettings::settings()->pageDpi->get() != 0) + mXmlWriter.writeAttribute("pageDpi", (UBSettings::settings()->pageDpi->get()).toString()); + else + mXmlWriter.writeAttribute("pageDpi", QString("%1").arg((desktop->physicalDpiX() + desktop->physicalDpiY()) / 2)); mXmlWriter.writeStartElement("rect"); mXmlWriter.writeAttribute("fill", mScene->isDarkBackground() ? "black" : "white"); From c71305e9dceacde7aa2a1270cae05968d79d9eae Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Mon, 14 Dec 2015 17:04:38 +0100 Subject: [PATCH 058/243] Updated release script for OSX --- release.macx.sh | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/release.macx.sh b/release.macx.sh index 8db95f16..b3a0d3a4 100755 --- a/release.macx.sh +++ b/release.macx.sh @@ -16,21 +16,21 @@ APPLICATION_NAME="OpenBoard" -BASE_TROLLTECH_DIRECTORY=/usr/local/Trolltech/Qt-4.8.0 +BASE_QT_DIR=~/Qt/5.5/clang_64 # Executables -QMAKE=$BASE_TROLLTECH_DIRECTORY/bin/qmake -MACDEPLOYQT=$BASE_TROLLTECH_DIRECTORY/bin/macdeployqt -DMGUTIL="`pwd`/../Sankore-ThirdParty/refnum/dmgutil/dmgutil.pl" +QMAKE=$BASE_QT_DIR/bin/qmake +MACDEPLOYQT=$BASE_QT_DIR/bin/macdeployqt +DMGUTIL="`pwd`/../OpenBoard-ThirdParty/refnum/dmgutil/dmgutil.pl" DSYMUTIL=/usr/bin/dsymutil STRIP=/usr/bin/strip PLISTBUDDY=/usr/libexec/PlistBuddy ICEBERG=/usr/local/bin/freeze -LRELEASE=$BASE_TROLLTECH_DIRECTORY/bin/lrelease +LRELEASE=$BASE_QT_DIR/bin/lrelease # Directories BUILD_DIR="build/macx/release" PRODUCT_DIR="$BUILD_DIR/product" -BASE_QT_TRANSLATIONS_DIRECTORY=../Qt4.8/translations +BASE_QT_TRANSLATIONS_DIRECTORY=$BASE_QT_DIR/translations function notify { GROWLNOTIFY=`which growlnotify` @@ -90,8 +90,8 @@ function addImporter { fi cd ${importerDir} - git reset --hard - git pull +# git reset --hard +# git pull rm -rf ${importerName}.app rm MakeFile* rm -rf release @@ -149,7 +149,7 @@ notify "Compiling ..." make -j4 release notify "Qt Translations ..." -$LRELEASE $BASE_QT_TRANSLATIONS_DIRECTORY/translations.pro +#$LRELEASE $BASE_QT_TRANSLATIONS_DIRECTORY/translations.pro addQtTranslations cp -R resources/customizations $PRODUCT_DIR/$APPLICATION_NAME.app/Contents/Resources @@ -159,19 +159,19 @@ VERSION=`cat "$BUILD_DIR/version"` if [ ! -f "$BUILD_DIR/version" ]; then echo "version not found" exit 1 -else - notify "Tagging ..." - LAST_COMMITED_VERSION="`git describe $(git rev-list --tags --max-count=1)`" - if [ "v$VERSION" != "$LAST_COMMITED_VERSION" ]; then - echo creating a tag with the version $VERSION +#else +# notify "Tagging ..." +# LAST_COMMITED_VERSION="`git describe $(git rev-list --tags --max-count=1)`" +# if [ "v$VERSION" != "$LAST_COMMITED_VERSION" ]; then +# echo creating a tag with the version $VERSION # git tag -a "v$VERSION" -m "Generated setup for v$VERSION" # git push origin --tags - fi +# fi fi -if [ $? != 0 ]; then - abort "compilation failed" -fi +#if [ $? != 0 ]; then +# abort "compilation failed" +#fi DMG="$APPLICATION_NAME.dmg" From 2881790f3c57264c27d7f4e6c714ba5f435e066d Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Mon, 14 Dec 2015 17:12:28 +0100 Subject: [PATCH 059/243] Removed 'Go to content source' option --- src/domain/UBGraphicsMediaItemDelegate.cpp | 3 +-- src/domain/UBGraphicsPixmapItem.cpp | 3 +-- src/domain/UBGraphicsSvgItem.cpp | 3 +-- src/domain/UBGraphicsWidgetItemDelegate.cpp | 3 +-- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/domain/UBGraphicsMediaItemDelegate.cpp b/src/domain/UBGraphicsMediaItemDelegate.cpp index 2faeb9b8..839ad434 100644 --- a/src/domain/UBGraphicsMediaItemDelegate.cpp +++ b/src/domain/UBGraphicsMediaItemDelegate.cpp @@ -46,8 +46,7 @@ UBGraphicsMediaItemDelegate::UBGraphicsMediaItemDelegate(UBGraphicsMediaItem* pDelegated, QMediaPlayer* pMedia, QObject * parent) : UBGraphicsItemDelegate(pDelegated, parent, GF_COMMON | GF_RESPECT_RATIO - | GF_TOOLBAR_USED - | GF_SHOW_CONTENT_SOURCE) + | GF_TOOLBAR_USED) , mPlayPauseButton(NULL) , mMedia(pMedia) , mToolBarShowTimer(NULL) diff --git a/src/domain/UBGraphicsPixmapItem.cpp b/src/domain/UBGraphicsPixmapItem.cpp index 44a532d5..a2191321 100644 --- a/src/domain/UBGraphicsPixmapItem.cpp +++ b/src/domain/UBGraphicsPixmapItem.cpp @@ -51,8 +51,7 @@ UBGraphicsPixmapItem::UBGraphicsPixmapItem(QGraphicsItem* parent) | GF_FLIPPABLE_ALL_AXIS | GF_REVOLVABLE | GF_RESPECT_RATIO - | GF_TOOLBAR_USED - | GF_SHOW_CONTENT_SOURCE)); + | GF_TOOLBAR_USED)); setData(UBGraphicsItemData::ItemLayerType, UBItemLayerType::Object); setTransformationMode(Qt::SmoothTransformation); diff --git a/src/domain/UBGraphicsSvgItem.cpp b/src/domain/UBGraphicsSvgItem.cpp index 172fd0c3..b2afec66 100644 --- a/src/domain/UBGraphicsSvgItem.cpp +++ b/src/domain/UBGraphicsSvgItem.cpp @@ -74,8 +74,7 @@ void UBGraphicsSvgItem::init() setDelegate(new UBGraphicsItemDelegate(this, 0, GF_COMMON | GF_RESPECT_RATIO - | GF_REVOLVABLE - | GF_SHOW_CONTENT_SOURCE)); + | GF_REVOLVABLE)); UBGraphicsFlags dfl = Delegate()->ubflags(); Delegate()->setUBFlags(dfl | GF_FLIPPABLE_ALL_AXIS | GF_REVOLVABLE); diff --git a/src/domain/UBGraphicsWidgetItemDelegate.cpp b/src/domain/UBGraphicsWidgetItemDelegate.cpp index 82ed610e..7e4dc7c6 100644 --- a/src/domain/UBGraphicsWidgetItemDelegate.cpp +++ b/src/domain/UBGraphicsWidgetItemDelegate.cpp @@ -43,8 +43,7 @@ UBGraphicsWidgetItemDelegate::UBGraphicsWidgetItemDelegate(UBGraphicsWidgetItem* pDelegated, int widgetType) : UBGraphicsItemDelegate(pDelegated, 0, GF_COMMON - | GF_RESPECT_RATIO - | GF_SHOW_CONTENT_SOURCE) + | GF_RESPECT_RATIO) , freezeAction(0) , setAsToolAction(0) { From f086277d6ff234c382f132bc4cbb7b4daea2bbe3 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Mon, 14 Dec 2015 17:24:41 +0100 Subject: [PATCH 060/243] Updated release script on Linux --- buildDebianPackage.sh | 62 +++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/buildDebianPackage.sh b/buildDebianPackage.sh index e7adcbca..b35927c6 100755 --- a/buildDebianPackage.sh +++ b/buildDebianPackage.sh @@ -35,9 +35,9 @@ initializeVariables() STANDARD_QT_USED=false PRODUCT_PATH="build/linux/release/product" - QT_PATH="/usr/local/Trolltech/Qt-4.8.0" + QT_PATH="/opt/qt55" PLUGINS_PATH="$QT_PATH/plugins" - GUI_TRANSLATIONS_DIRECTORY_PATH="../Qt-4.8/translations" + GUI_TRANSLATIONS_DIRECTORY_PATH="$QT_PATH/translations" QT_LIBRARY_DEST_PATH="$PRODUCT_PATH/qtlib" QT_LIBRARY_SOURCE_PATH="$QT_PATH/lib" if [ -z $ARCHITECTURE ]; then @@ -107,7 +107,9 @@ copyQtLibrary(){ buildWithStandardQt(){ - STANDARD_QT=`which qmake-qt4` + # if both Qt4 and Qt5 are installed, choose Qt5 + export QT_SELECT=5 + STANDARD_QT=`which qmake` if [ $? == "0" ]; then QT_VERSION=`$STANDARD_QT --version | grep -i "Using Qt version" | sed -e "s/Using Qt version \(.*\) in.*/\1/"` if [ `echo $QT_VERSION | sed -e "s/\.//g"` -gt 480 ]; then @@ -115,12 +117,7 @@ buildWithStandardQt(){ STANDARD_QT_USED=true QMAKE_PATH=$STANDARD_QT LRELEASES=`which lrelease` - if [ "`arch`" == "i686" ] || [ "$ARCHITECTURE" == "i386" ]; then - QT_PATH="/usr/lib/i386-linux-gnu" - else - QT_PATH="/usr/lib/`arch`-linux-gnu" - fi - PLUGINS_PATH="$QT_PATH/qt4/plugins" + PLUGINS_PATH="$STANDARD_QT/../plugins" fi fi } @@ -135,8 +132,8 @@ buildImporter(){ rm -rf debug release rm *.o - git reset --hard - git pull + #git reset --hard + #git pull $QMAKE_PATH ${IMPORTER_NAME}.pro make clean @@ -165,7 +162,7 @@ do done initializeVariables -buildWithStandardQt +#buildWithStandardQt alertIfPreviousVersionInstalled @@ -212,14 +209,14 @@ VERSION=`cat build/linux/release/version` if [ ! -f build/linux/release/version ]; then notifyError "version not found" -else - LAST_COMMITED_VERSION="`git describe $(git rev-list --tags --max-count=1)`" - if [ "v$VERSION" != "$LAST_COMMITED_VERSION" ]; then - if [ $MAKE_TAG == true ]; then - git tag -a "OBv$VERSION" -m "OpenBoard setup for v$VERSION" - git push origin --tags - fi - fi +#else +# LAST_COMMITED_VERSION="`git describe $(git rev-list --tags --max-count=1)`" +# if [ "v$VERSION" != "$LAST_COMMITED_VERSION" ]; then +# if [ $MAKE_TAG == true ]; then +# git tag -a "OBv$VERSION" -m "OpenBoard setup for v$VERSION" +# git push origin --tags +# fi +# fi fi cp resources/linux/run.sh $PRODUCT_PATH @@ -240,19 +237,22 @@ cp -R ${IMPORTER_DIR}/${IMPORTER_NAME} $PRODUCT_PATH/Importer if [ $STANDARD_QT_USED == false ]; then #copying custom qt library mkdir -p $QT_LIBRARY_DEST_PATH - copyQtLibrary libQtDBus - copyQtLibrary libQtScript - copyQtLibrary libQtSvg - copyQtLibrary libQtXmlPatterns - copyQtLibrary libQtNetwork - copyQtLibrary libQtXml - copyQtLibrary libQtGui - copyQtLibrary libQtCore - copyQtLibrary libphonon - copyQtLibrary libQtWebKit + copyQtLibrary libQt5Core + copyQtLibrary libQt5Gui + copyQtLibrary libQt5Multimedia + copyQtLibrary libQt5MultimediaWidgets + copyQtLibrary libQt5Network + copyQtLibrary libQt5OpenGL + copyQtLibrary libQt5PrintSupport + copyQtLibrary libQt5Script + copyQtLibrary libQt5Svg + copyQtLibrary libQt5WebKit + copyQtLibrary libQt5WebKitWidgets + copyQtLibrary libQt5Xml + copyQtLibrary libQt5XmlPatterns fi -notifyProgress "QT" "Internalization" +notifyProgress "QT" "Internationalization" if [ ! -e $PRODUCT_PATH/i18n ]; then mkdir $PRODUCT_PATH/i18n fi From a389a7568421ec5393c618f0ed030dfa2eb7bdc3 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Tue, 15 Dec 2015 10:54:20 +0100 Subject: [PATCH 061/243] Updated translations --- resources/i18n/OpenBoard_ar.ts | 48 +++++++++++-------- resources/i18n/OpenBoard_bg.ts | 48 +++++++++++-------- resources/i18n/OpenBoard_ca.ts | 50 +++++++++++--------- resources/i18n/OpenBoard_cs.ts | 48 +++++++++++-------- resources/i18n/OpenBoard_da.ts | 48 +++++++++++-------- resources/i18n/OpenBoard_de.ts | 48 +++++++++++-------- resources/i18n/OpenBoard_el.ts | 48 +++++++++++-------- resources/i18n/OpenBoard_en.ts | 78 +++++++------------------------ resources/i18n/OpenBoard_en_UK.ts | 78 +++++++------------------------ resources/i18n/OpenBoard_es.ts | 48 +++++++++++-------- resources/i18n/OpenBoard_fr.ts | 50 +++++++++++--------- resources/i18n/OpenBoard_fr_CH.ts | 48 +++++++++++-------- resources/i18n/OpenBoard_it.ts | 48 +++++++++++-------- resources/i18n/OpenBoard_iw.ts | 48 +++++++++++-------- resources/i18n/OpenBoard_ja.ts | 52 ++++++++++----------- resources/i18n/OpenBoard_ko.ts | 48 +++++++++++-------- resources/i18n/OpenBoard_mg.ts | 48 +++++++++++-------- resources/i18n/OpenBoard_nb.ts | 48 +++++++++++-------- resources/i18n/OpenBoard_nl.ts | 52 ++++++++++----------- resources/i18n/OpenBoard_pl.ts | 48 +++++++++++-------- resources/i18n/OpenBoard_pt.ts | 48 +++++++++++-------- resources/i18n/OpenBoard_ro.ts | 48 +++++++++++-------- resources/i18n/OpenBoard_ru.ts | 48 +++++++++++-------- resources/i18n/OpenBoard_sk.ts | 48 +++++++++++-------- resources/i18n/OpenBoard_sv.ts | 48 +++++++++++-------- resources/i18n/OpenBoard_tr.ts | 48 +++++++++++-------- resources/i18n/OpenBoard_zh.ts | 48 +++++++++++-------- resources/i18n/OpenBoard_zh_CN.ts | 48 +++++++++++-------- resources/i18n/OpenBoard_zh_TW.ts | 48 +++++++++++-------- 29 files changed, 785 insertions(+), 679 deletions(-) diff --git a/resources/i18n/OpenBoard_ar.ts b/resources/i18n/OpenBoard_ar.ts index 3b671e77..d57e6321 100644 --- a/resources/i18n/OpenBoard_ar.ts +++ b/resources/i18n/OpenBoard_ar.ts @@ -1,6 +1,6 @@ - + BlackoutWidget @@ -842,11 +842,11 @@ QObject Element ID = - معرّ٠المكوّن = + معرّ٠المكوّن = Content is not supported in destination format. - المحتوى غير مدعوم ÙÙŠ النسق الهدÙ. + المحتوى غير مدعوم ÙÙŠ النسق الهدÙ. Remove Page @@ -937,6 +937,14 @@ Ungroup تÙريق + + Saving document... + + + + Document has just been saved... + + UBBoardPaletteManager @@ -1232,23 +1240,23 @@ UBExportCFF Export to IWB - التصدير للـIWB + التصدير للـIWB Export as IWB File - التصدير كمل٠IWB + التصدير كمل٠IWB Exporting document... - تصدير الوثيقة... + تصدير الوثيقة... Export successful. - تصدير ناجح. + تصدير ناجح. Export failed. - Ùشل التصدير. + Ùشل التصدير. @@ -1543,23 +1551,23 @@ UBImportCFF Common File Format ( - شكل مل٠مشترك ( + شكل مل٠مشترك ( Importing file %1... - استيراد مل٠1%... + استيراد مل٠1%... Import of file %1 failed. - Ùشل تصدير المل٠1% + Ùشل تصدير المل٠1% Import successful. - استيراد ناجح + استيراد ناجح Import failed. - استيراد Ùاشل. + استيراد Ùاشل. @@ -1685,10 +1693,6 @@ Do you want to ignore these errors for this host? Open-Sankore Documents Detected - - 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. - - Show this panel next time @@ -1705,6 +1709,10 @@ Do you want to ignore these errors for this host? Proceed + + 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. + + UBPersistenceManager @@ -2485,7 +2493,7 @@ p, li { white-space: pre-wrap; } Network شبكة - + version : … نسخة: @@ -2529,11 +2537,11 @@ p, li { white-space: pre-wrap; } Credits الشكر إلى - + Open-Sankoré Importer - + Check if Open-Sankoré data could be imported at launch diff --git a/resources/i18n/OpenBoard_bg.ts b/resources/i18n/OpenBoard_bg.ts index fe203f60..17e988c5 100644 --- a/resources/i18n/OpenBoard_bg.ts +++ b/resources/i18n/OpenBoard_bg.ts @@ -1,6 +1,6 @@ - + BlackoutWidget @@ -842,11 +842,11 @@ QObject Element ID = - Ðомер на елемента = + Ðомер на елемента = Content is not supported in destination format. - Това Ñъдържание не Ñе поддържа Ð²ÐºÑ€Ð°Ð¹Ð½Ð¸Ñ Ñ„Ð¾Ñ€Ð¼Ð°Ñ‚. + Това Ñъдържание не Ñе поддържа Ð²ÐºÑ€Ð°Ð¹Ð½Ð¸Ñ Ñ„Ð¾Ñ€Ð¼Ð°Ñ‚. Remove Page @@ -937,6 +937,14 @@ Ungroup Премахни групирането + + Saving document... + + + + Document has just been saved... + + UBBoardPaletteManager @@ -1224,23 +1232,23 @@ UBExportCFF Export to IWB - ЕкÑпортирай към интерактивната дъÑка + ЕкÑпортирай към интерактивната дъÑка Export as IWB File - ЕкÑпортирай като файл за интерактивна дъÑка + ЕкÑпортирай като файл за интерактивна дъÑка Exporting document... - ЕкÑпортиране на документ... + ЕкÑпортиране на документ... Export successful. - ЕкÑпортирането уÑпешно. + ЕкÑпортирането уÑпешно. Export failed. - ЕкÑпортирането Ñе провали. + ЕкÑпортирането Ñе провали. @@ -1535,23 +1543,23 @@ UBImportCFF Common File Format ( - Общ формат на файла ( + Общ формат на файла ( Importing file %1... - Импортиране на файл %1... + Импортиране на файл %1... Import of file %1 failed. - Импортирането на файл %1 Ñе провали. + Импортирането на файл %1 Ñе провали. Import successful. - Импортирането уÑпешно. + Импортирането уÑпешно. Import failed. - Грешка при импортирането. + Грешка при импортирането. @@ -1683,10 +1691,6 @@ Do you want to ignore these errors for this host? Open-Sankore Documents Detected - - 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. - - Show this panel next time @@ -1703,6 +1707,10 @@ Do you want to ignore these errors for this host? Proceed + + 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. + + UBPersistenceManager @@ -2472,7 +2480,7 @@ p, li { white-space: pre-wrap; } Marker Маркер - + version : … верÑиÑ: ... @@ -2524,11 +2532,11 @@ p, li { white-space: pre-wrap; } Credits Изготвили - + Open-Sankoré Importer - + Check if Open-Sankoré data could be imported at launch diff --git a/resources/i18n/OpenBoard_ca.ts b/resources/i18n/OpenBoard_ca.ts index 10100e75..21b7589c 100644 --- a/resources/i18n/OpenBoard_ca.ts +++ b/resources/i18n/OpenBoard_ca.ts @@ -1,6 +1,6 @@ - + BlackoutWidget @@ -842,11 +842,11 @@ QObject Element ID = - ID de l'element = + ID de l'element = Content is not supported in destination format. - Aquest contingut no està suportat pel format escollit. + Aquest contingut no està suportat pel format escollit. Remove Page @@ -937,6 +937,14 @@ Ungroup Desagrupa + + Saving document... + + + + Document has just been saved... + + UBBoardPaletteManager @@ -1118,7 +1126,6 @@ Esteu segur que voleu eliminar %n pàgina del document seleccionat '%1'? Esteu segur que voleu eliminar %n pàgines del document seleccionat '%1'? - Esteu segur que voleu eliminar %n pàgines del document seleccionat '%1'? @@ -1199,7 +1206,6 @@ %1 pàgina copiada %1 pàgines copiades - %1 pàgines copiades @@ -1225,23 +1231,23 @@ UBExportCFF Export to IWB - Exporta a IWB + Exporta a IWB Export as IWB File - Exporta com a fitxer IWB + Exporta com a fitxer IWB Exporting document... - S'està exportant el document... + S'està exportant el document... Export successful. - L'exportació ha estat correcta. + L'exportació ha estat correcta. Export failed. - L'exportació ha fallat. + L'exportació ha fallat. @@ -1536,23 +1542,23 @@ UBImportCFF Common File Format ( - Format de fitxer comú ( + Format de fitxer comú ( Importing file %1... - S'està important el fitxer %1... + S'està important el fitxer %1... Import of file %1 failed. - Ha fallat la importació del fitxer %1. + Ha fallat la importació del fitxer %1. Import successful. - La importació ha estat correcta. + La importació ha estat correcta. Import failed. - Ha fallat la importació. + Ha fallat la importació. @@ -1684,10 +1690,6 @@ Voleu ignorar aquests errors per a aquest amfitrió? Open-Sankore Documents Detected - - 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. - - Show this panel next time @@ -1704,6 +1706,10 @@ Voleu ignorar aquests errors per a aquest amfitrió? Proceed + + 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. + + UBPersistenceManager @@ -2387,7 +2393,7 @@ p, li { white-space: pre-wrap; } Preferences Preferències - + version : … versió: … @@ -2519,11 +2525,11 @@ p, li { white-space: pre-wrap; } Credits Crèdits - + Open-Sankoré Importer - + Check if Open-Sankoré data could be imported at launch diff --git a/resources/i18n/OpenBoard_cs.ts b/resources/i18n/OpenBoard_cs.ts index f2bdf7af..b589137f 100644 --- a/resources/i18n/OpenBoard_cs.ts +++ b/resources/i18n/OpenBoard_cs.ts @@ -1,6 +1,6 @@ - + BlackoutWidget @@ -843,11 +843,11 @@ QObject Element ID = - ID objektu = + ID objektu = Content is not supported in destination format. - Obsah není podporován v cílovém formátu. + Obsah není podporován v cílovém formátu. Remove Page @@ -938,6 +938,14 @@ Ungroup Odseskupit + + Saving document... + + + + Document has just been saved... + + UBBoardPaletteManager @@ -1226,23 +1234,23 @@ UBExportCFF Export to IWB - Export do IWB + Export do IWB Export as IWB File - Exportovat jako IWB soubor + Exportovat jako IWB soubor Exporting document... - Exportuje se dokument... + Exportuje se dokument... Export successful. - Export byl úspěšnÄ› dokonÄen. + Export byl úspěšnÄ› dokonÄen. Export failed. - Export se nezdaÅ™il. + Export se nezdaÅ™il. @@ -1537,23 +1545,23 @@ UBImportCFF Importing file %1... - Importuje se soubor %1... + Importuje se soubor %1... Import failed. - Import se nezdaÅ™il. + Import se nezdaÅ™il. Import of file %1 failed. - Import souboru %1 se nezdaÅ™il. + Import souboru %1 se nezdaÅ™il. Common File Format ( - Univerzální IWB soubor ( + Univerzální IWB soubor ( Import successful. - Import byl úspěšnÄ› dokonÄen. + Import byl úspěšnÄ› dokonÄen. @@ -1685,10 +1693,6 @@ Chcete ignorovat tyto chyby na tomto serveru? Open-Sankore Documents Detected - - 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. - - Show this panel next time @@ -1705,6 +1709,10 @@ Chcete ignorovat tyto chyby na tomto serveru? Proceed + + 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. + + UBPersistenceManager @@ -2479,7 +2487,7 @@ p, li { white-space: pre-wrap; } Preferences PÅ™edvolby - + version : … verze:... @@ -2527,11 +2535,11 @@ p, li { white-space: pre-wrap; } Credits Zásluhy - + Open-Sankoré Importer - + Check if Open-Sankoré data could be imported at launch diff --git a/resources/i18n/OpenBoard_da.ts b/resources/i18n/OpenBoard_da.ts index ea083a5c..e066e3ce 100644 --- a/resources/i18n/OpenBoard_da.ts +++ b/resources/i18n/OpenBoard_da.ts @@ -1,6 +1,6 @@ - + BlackoutWidget @@ -842,11 +842,11 @@ QObject Element ID = - Element-ID = + Element-ID = Content is not supported in destination format. - Indholdet understøttes ikke i destinationsformatet. + Indholdet understøttes ikke i destinationsformatet. Remove Page @@ -937,6 +937,14 @@ Ungroup Opdel gruppe + + Saving document... + + + + Document has just been saved... + + UBBoardPaletteManager @@ -1223,23 +1231,23 @@ UBExportCFF Export to IWB - Eksporter til IWB + Eksporter til IWB Export as IWB File - Eksporter som IWB-fil + Eksporter som IWB-fil Exporting document... - Eksporterer dokument... + Eksporterer dokument... Export successful. - Eksport gennemført. + Eksport gennemført. Export failed. - Eksport mislykkedes. + Eksport mislykkedes. @@ -1534,23 +1542,23 @@ UBImportCFF Common File Format ( - Almindelig filformat ( + Almindelig filformat ( Importing file %1... - Importerer fil %1... + Importerer fil %1... Import of file %1 failed. - Import af fil %1 mislykkedes. + Import af fil %1 mislykkedes. Import successful. - Import gennemført. + Import gennemført. Import failed. - Import mislykkedes. + Import mislykkedes. @@ -1682,10 +1690,6 @@ Do you want to ignore these errors for this host? Open-Sankore Documents Detected - - 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. - - Show this panel next time @@ -1702,6 +1706,10 @@ Do you want to ignore these errors for this host? Proceed + + 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. + + UBPersistenceManager @@ -2388,7 +2396,7 @@ p, li { white-space: pre-wrap; } Preferences Indstillinger - + version : … version: ... @@ -2520,11 +2528,11 @@ p, li { white-space: pre-wrap; } Credits Anerkendelse - + Open-Sankoré Importer - + Check if Open-Sankoré data could be imported at launch diff --git a/resources/i18n/OpenBoard_de.ts b/resources/i18n/OpenBoard_de.ts index 8a3de763..2ee3c433 100644 --- a/resources/i18n/OpenBoard_de.ts +++ b/resources/i18n/OpenBoard_de.ts @@ -1,6 +1,6 @@ - + BlackoutWidget @@ -842,11 +842,11 @@ QObject Element ID = - Element ID = + Element ID = Content is not supported in destination format. - Inhalt wird im Zielformat nicht unterstützt. + Inhalt wird im Zielformat nicht unterstützt. Remove Page @@ -937,6 +937,14 @@ Ungroup Gruppierung auflösen + + Saving document... + + + + Document has just been saved... + + UBBoardPaletteManager @@ -1223,23 +1231,23 @@ UBExportCFF Export to IWB - Exportieren nach IWB + Exportieren nach IWB Export as IWB File - Exportieren als IWB-Datei + Exportieren als IWB-Datei Exporting document... - Dokument wird exportiert... + Dokument wird exportiert... Export successful. - Export erfolgreich. + Export erfolgreich. Export failed. - Export fehlgeschlagen. + Export fehlgeschlagen. @@ -1534,23 +1542,23 @@ UBImportCFF Common File Format ( - Standard-Dateiformat ( + Standard-Dateiformat ( Importing file %1... - Datei %1 wird importiert... + Datei %1 wird importiert... Import of file %1 failed. - Import der Datei %1 fehlgeschlagen. + Import der Datei %1 fehlgeschlagen. Import successful. - Import erfolgreich. + Import erfolgreich. Import failed. - Import fehlgeschlagen. + Import fehlgeschlagen. @@ -1682,10 +1690,6 @@ Möchten Sie diese Fehler auf diesem Computer ignorieren? Open-Sankore Documents Detected - - 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. - - Show this panel next time @@ -1702,6 +1706,10 @@ Möchten Sie diese Fehler auf diesem Computer ignorieren? Proceed + + 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. + + UBPersistenceManager @@ -2392,7 +2400,7 @@ p, li { white-space: pre-wrap; } Preferences Einstellungen - + version : … Version: ... @@ -2525,11 +2533,11 @@ p, li { white-space: pre-wrap; } do not translate! - + Open-Sankoré Importer - + Check if Open-Sankoré data could be imported at launch diff --git a/resources/i18n/OpenBoard_el.ts b/resources/i18n/OpenBoard_el.ts index 0c29d31f..d3700202 100644 --- a/resources/i18n/OpenBoard_el.ts +++ b/resources/i18n/OpenBoard_el.ts @@ -1,6 +1,6 @@ - + BlackoutWidget @@ -842,11 +842,11 @@ QObject Element ID = - ΑναγνωÏιστικό στοιχείου= + ΑναγνωÏιστικό στοιχείου= Content is not supported in destination format. - Η μοÏφή του πεÏιεχομένου δεν υποστηÏιζεται στον Ï€ÏοοÏισμό + Η μοÏφή του πεÏιεχομένου δεν υποστηÏιζεται στον Ï€ÏοοÏισμό Remove Page @@ -937,6 +937,14 @@ Ungroup Αποομαδοποίηση + + Saving document... + + + + Document has just been saved... + + UBBoardPaletteManager @@ -1223,23 +1231,23 @@ UBExportCFF Export to IWB - Εξαγωγή σε IWB + Εξαγωγή σε IWB Export as IWB File - Εξαγωγή ως αÏχείο IWB + Εξαγωγή ως αÏχείο IWB Exporting document... - Εξαγωγή εγγÏάφου... + Εξαγωγή εγγÏάφου... Export successful. - Επιτυχημένη εξαγωγή + Επιτυχημένη εξαγωγή Export failed. - Αποτυχημένη εξαγωγή + Αποτυχημένη εξαγωγή @@ -1534,23 +1542,23 @@ UBImportCFF Common File Format ( - Συνηθισμένη μοÏφή αÏχείου ( + Συνηθισμένη μοÏφή αÏχείου ( Importing file %1... - Εισαγωγή αÏχείου %1... + Εισαγωγή αÏχείου %1... Import of file %1 failed. - Η εισαγωγή του αÏχείου %1 απέτυχε + Η εισαγωγή του αÏχείου %1 απέτυχε Import successful. - Επιτυχημένη εισαγωγή + Επιτυχημένη εισαγωγή Import failed. - Αποτυχημένη εισαγωγή + Αποτυχημένη εισαγωγή @@ -1682,10 +1690,6 @@ Do you want to ignore these errors for this host? Open-Sankore Documents Detected - - 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. - - Show this panel next time @@ -1702,6 +1706,10 @@ Do you want to ignore these errors for this host? Proceed + + 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. + + UBPersistenceManager @@ -2472,7 +2480,7 @@ p, li { white-space: pre-wrap; } Marker ΜαÏκαδόÏος - + version : … έκδοση: ... @@ -2524,11 +2532,11 @@ p, li { white-space: pre-wrap; } Credits ΕÏσημα - + Open-Sankoré Importer - + Check if Open-Sankoré data could be imported at launch diff --git a/resources/i18n/OpenBoard_en.ts b/resources/i18n/OpenBoard_en.ts index 4c610433..641f7fe9 100644 --- a/resources/i18n/OpenBoard_en.ts +++ b/resources/i18n/OpenBoard_en.ts @@ -1,6 +1,6 @@ - + BlackoutWidget @@ -840,14 +840,6 @@ QObject - - Element ID = - - - - Content is not supported in destination format. - - Remove Page @@ -937,6 +929,14 @@ Ungroup + + Saving document... + + + + Document has just been saved... + + UBBoardPaletteManager @@ -1217,29 +1217,6 @@ - - UBExportCFF - - Export to IWB - - - - Export as IWB File - - - - Exporting document... - - - - Export successful. - - - - Export failed. - - - UBExportDocument @@ -1528,29 +1505,6 @@ - - UBImportCFF - - Common File Format ( - - - - Importing file %1... - - - - Import of file %1 failed. - - - - Import successful. - - - - Import failed. - - - UBImportDocument @@ -1674,10 +1628,6 @@ Do you want to ignore these errors for this host? Open-Sankore Documents Detected - - 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. - - Show this panel next time @@ -1694,6 +1644,10 @@ Do you want to ignore these errors for this host? Proceed + + 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. + + UBPersistenceManager @@ -2459,7 +2413,7 @@ p, li { white-space: pre-wrap; } Marker - + version : … @@ -2511,11 +2465,11 @@ p, li { white-space: pre-wrap; } Credits - + Open-Sankoré Importer - + Check if Open-Sankoré data could be imported at launch diff --git a/resources/i18n/OpenBoard_en_UK.ts b/resources/i18n/OpenBoard_en_UK.ts index 4e629992..8e1a33be 100644 --- a/resources/i18n/OpenBoard_en_UK.ts +++ b/resources/i18n/OpenBoard_en_UK.ts @@ -1,6 +1,6 @@ - + BlackoutWidget @@ -840,14 +840,6 @@ QObject - - Element ID = - - - - Content is not supported in destination format. - - Remove Page @@ -937,6 +929,14 @@ Ungroup + + Saving document... + + + + Document has just been saved... + + UBBoardPaletteManager @@ -1217,29 +1217,6 @@ - - UBExportCFF - - Export to IWB - - - - Export as IWB File - - - - Exporting document... - - - - Export successful. - - - - Export failed. - - - UBExportDocument @@ -1528,29 +1505,6 @@ - - UBImportCFF - - Common File Format ( - - - - Importing file %1... - - - - Import of file %1 failed. - - - - Import successful. - - - - Import failed. - - - UBImportDocument @@ -1674,10 +1628,6 @@ Do you want to ignore these errors for this host? Open-Sankore Documents Detected - - 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. - - Show this panel next time @@ -1694,6 +1644,10 @@ Do you want to ignore these errors for this host? Proceed + + 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. + + UBPersistenceManager @@ -2459,7 +2413,7 @@ p, li { white-space: pre-wrap; } Marker - + version : … @@ -2511,11 +2465,11 @@ p, li { white-space: pre-wrap; } Credits - + Open-Sankoré Importer - + Check if Open-Sankoré data could be imported at launch diff --git a/resources/i18n/OpenBoard_es.ts b/resources/i18n/OpenBoard_es.ts index 84b4fea3..2be65f6c 100644 --- a/resources/i18n/OpenBoard_es.ts +++ b/resources/i18n/OpenBoard_es.ts @@ -1,6 +1,6 @@ - + BlackoutWidget @@ -842,11 +842,11 @@ QObject Element ID = - Elemento ID = + Elemento ID = Content is not supported in destination format. - El formato de destino no permite este contenido + El formato de destino no permite este contenido Remove Page @@ -937,6 +937,14 @@ Ungroup Desagrupar + + Saving document... + + + + Document has just been saved... + + UBBoardPaletteManager @@ -1223,23 +1231,23 @@ UBExportCFF Export to IWB - Exportar a IWB + Exportar a IWB Export as IWB File - Exportar como fichero IWB + Exportar como fichero IWB Exporting document... - Exportando documento... + Exportando documento... Export successful. - Exportación satisfactoria. + Exportación satisfactoria. Export failed. - Fallo en la exportación + Fallo en la exportación @@ -1534,23 +1542,23 @@ UBImportCFF Common File Format ( - Formato de archivo común ( + Formato de archivo común ( Importing file %1... - Importando archivo %1... + Importando archivo %1... Import of file %1 failed. - Fallo en la importanción del archivo %1. + Fallo en la importanción del archivo %1. Import successful. - Importación satisfactoria. + Importación satisfactoria. Import failed. - Fallo de la importación. + Fallo de la importación. @@ -1676,10 +1684,6 @@ Do you want to ignore these errors for this host? Open-Sankore Documents Detected - - 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. - - Show this panel next time @@ -1696,6 +1700,10 @@ Do you want to ignore these errors for this host? Proceed + + 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. + + UBPersistenceManager @@ -2386,7 +2394,7 @@ p, li { white-space: pre-wrap; } Preferences Preferencias - + version : … versión : … @@ -2518,11 +2526,11 @@ p, li { white-space: pre-wrap; } Credits Créditos - + Open-Sankoré Importer - + Check if Open-Sankoré data could be imported at launch diff --git a/resources/i18n/OpenBoard_fr.ts b/resources/i18n/OpenBoard_fr.ts index ca98d0be..72fac092 100644 --- a/resources/i18n/OpenBoard_fr.ts +++ b/resources/i18n/OpenBoard_fr.ts @@ -1,6 +1,6 @@ - + BlackoutWidget @@ -843,11 +843,11 @@ QObject Element ID = - ID de l'élément = + ID de l'élément = Content is not supported in destination format. - Contenu non supporté dans le format souhaité. + Contenu non supporté dans le format souhaité. Remove Page @@ -938,6 +938,14 @@ Ungroup Dégrouper + + Saving document... + Sauvegarde du document... + + + Document has just been saved... + Le document vient d'être enregistré... + UBBoardPaletteManager @@ -1225,23 +1233,23 @@ UBExportCFF Export to IWB - Exporter au format CFF (*.iwb) + Exporter au format CFF (*.iwb) Export as IWB File - Exporter au format CFF (*.iwb) + Exporter au format CFF (*.iwb) Exporting document... - Exportation du document... + Exportation du document... Export successful. - Export réussi. + Export réussi. Export failed. - Echec de l'export. + Echec de l'export. @@ -1539,23 +1547,23 @@ UBImportCFF Common File Format ( - Format de fichier CFF ( + Format de fichier CFF ( Importing file %1... - Importation du fichier %1... + Importation du fichier %1... Import of file %1 failed. - Echec de l'import du fichier %1. + Echec de l'import du fichier %1. Import successful. - Import terminée. + Import terminée. Import failed. - Echec de l'import. + Echec de l'import. @@ -1687,10 +1695,6 @@ Voulez-vous ignorer les erreurs pour ce serveur ? Open-Sankore Documents Detected Données d’Open-Sankoré détectées - - 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. - Des documents Open-Sankoré sont présents sur votre ordinateur. Il est possible de les importer dans OpenBoard en appuyant sur le bouton “Procéder†pour lancer le processus d’importation. - Show this panel next time Afficher ce panneau à la prochaine ouverture du logiciel @@ -1707,6 +1711,10 @@ Voulez-vous ignorer les erreurs pour ce serveur ? Proceed Procéder + + 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. + Des documents Open-Sankoré sont présents sur votre ordinateur. Il est possible de les importer dans OpenBoard en appuyant sur le bouton “Procéder†pour lancer le processus d’importation. + UBPersistenceManager @@ -2450,7 +2458,7 @@ p, li { white-space: pre-wrap; } Home Page: Page d'accueil : - + version : … version :... @@ -2530,13 +2538,13 @@ p, li { white-space: pre-wrap; } Credits Crédits - + Open-Sankoré Importer Importateur de documents Open-Sankoré - + Check if Open-Sankoré data could be imported at launch - Vérifier si des données Open-Sankoré peuvent être importées au redémarrage. + Vérifier si des données Open-Sankoré peuvent être importées au redémarrage diff --git a/resources/i18n/OpenBoard_fr_CH.ts b/resources/i18n/OpenBoard_fr_CH.ts index ca98d0be..0f33e342 100644 --- a/resources/i18n/OpenBoard_fr_CH.ts +++ b/resources/i18n/OpenBoard_fr_CH.ts @@ -1,6 +1,6 @@ - + BlackoutWidget @@ -843,11 +843,11 @@ QObject Element ID = - ID de l'élément = + ID de l'élément = Content is not supported in destination format. - Contenu non supporté dans le format souhaité. + Contenu non supporté dans le format souhaité. Remove Page @@ -938,6 +938,14 @@ Ungroup Dégrouper + + Saving document... + Sauvegarde du document... + + + Document has just been saved... + Le document vient d'être sauvegardé... + UBBoardPaletteManager @@ -1225,23 +1233,23 @@ UBExportCFF Export to IWB - Exporter au format CFF (*.iwb) + Exporter au format CFF (*.iwb) Export as IWB File - Exporter au format CFF (*.iwb) + Exporter au format CFF (*.iwb) Exporting document... - Exportation du document... + Exportation du document... Export successful. - Export réussi. + Export réussi. Export failed. - Echec de l'export. + Echec de l'export. @@ -1539,23 +1547,23 @@ UBImportCFF Common File Format ( - Format de fichier CFF ( + Format de fichier CFF ( Importing file %1... - Importation du fichier %1... + Importation du fichier %1... Import of file %1 failed. - Echec de l'import du fichier %1. + Echec de l'import du fichier %1. Import successful. - Import terminée. + Import terminée. Import failed. - Echec de l'import. + Echec de l'import. @@ -1687,10 +1695,6 @@ Voulez-vous ignorer les erreurs pour ce serveur ? Open-Sankore Documents Detected Données d’Open-Sankoré détectées - - 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. - Des documents Open-Sankoré sont présents sur votre ordinateur. Il est possible de les importer dans OpenBoard en appuyant sur le bouton “Procéder†pour lancer le processus d’importation. - Show this panel next time Afficher ce panneau à la prochaine ouverture du logiciel @@ -1707,6 +1711,10 @@ Voulez-vous ignorer les erreurs pour ce serveur ? Proceed Procéder + + 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. + Des documents Open-Sankoré sont présents sur votre ordinateur. Il est possible de les importer dans OpenBoard en cliquant le bouton "Continuer" pour lancer l'application d'import. + UBPersistenceManager @@ -2450,7 +2458,7 @@ p, li { white-space: pre-wrap; } Home Page: Page d'accueil : - + version : … version :... @@ -2530,11 +2538,11 @@ p, li { white-space: pre-wrap; } Credits Crédits - + Open-Sankoré Importer Importateur de documents Open-Sankoré - + Check if Open-Sankoré data could be imported at launch Vérifier si des données Open-Sankoré peuvent être importées au redémarrage. diff --git a/resources/i18n/OpenBoard_it.ts b/resources/i18n/OpenBoard_it.ts index d9b0205c..8597f75a 100644 --- a/resources/i18n/OpenBoard_it.ts +++ b/resources/i18n/OpenBoard_it.ts @@ -1,6 +1,6 @@ - + BlackoutWidget @@ -842,11 +842,11 @@ QObject Element ID = - Elemento ID = + Elemento ID = Content is not supported in destination format. - Il contenuto non è supportato nel formato di destinazione. + Il contenuto non è supportato nel formato di destinazione. Remove Page @@ -937,6 +937,14 @@ Ungroup Separa + + Saving document... + + + + Document has just been saved... + + UBBoardPaletteManager @@ -1223,23 +1231,23 @@ UBExportCFF Export to IWB - Esporta in IWB + Esporta in IWB Export as IWB File - Esporta come file IWB + Esporta come file IWB Exporting document... - Esportazione documento in corso... + Esportazione documento in corso... Export successful. - Esportazione conclusa con successo. + Esportazione conclusa con successo. Export failed. - Esportazione fallita. + Esportazione fallita. @@ -1534,23 +1542,23 @@ UBImportCFF Common File Format ( - Common File Format ( + Common File Format ( Importing file %1... - Importazione del file %1 in corso... + Importazione del file %1 in corso... Import of file %1 failed. - L'importazione del file %1 è fallita. + L'importazione del file %1 è fallita. Import successful. - Importazione completata con successo. + Importazione completata con successo. Import failed. - Importazione fallita. + Importazione fallita. @@ -1682,10 +1690,6 @@ Vuoi ignorare gli errori per questo host? Open-Sankore Documents Detected - - 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. - - Show this panel next time @@ -1702,6 +1706,10 @@ Vuoi ignorare gli errori per questo host? Proceed + + 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. + + UBPersistenceManager @@ -2392,7 +2400,7 @@ p, li { white-space: pre-wrap; } Preferences Preferenze - + version : … versione : ... @@ -2524,11 +2532,11 @@ p, li { white-space: pre-wrap; } Credits Riconoscimenti - + Open-Sankoré Importer - + Check if Open-Sankoré data could be imported at launch diff --git a/resources/i18n/OpenBoard_iw.ts b/resources/i18n/OpenBoard_iw.ts index 035b2fe5..54c28c4d 100644 --- a/resources/i18n/OpenBoard_iw.ts +++ b/resources/i18n/OpenBoard_iw.ts @@ -1,6 +1,6 @@ - + BlackoutWidget @@ -843,11 +843,11 @@ QObject Element ID = - זהות הרכיב: + זהות הרכיב: Content is not supported in destination format. - התוכן ×ינו נתמך בפורמט היעד + התוכן ×ינו נתמך בפורמט היעד Remove Page @@ -938,6 +938,14 @@ Ungroup בטל קיבוץ + + Saving document... + + + + Document has just been saved... + + UBBoardPaletteManager @@ -1225,23 +1233,23 @@ UBExportCFF Export to IWB - ×™×™×¦× ×œ-IWB + ×™×™×¦× ×œ-IWB Export as IWB File - ×™×™×¦× ×›×§×•×‘×¥ IWB + ×™×™×¦× ×›×§×•×‘×¥ IWB Exporting document... - ×ž×™×™×¦× ×ž×¡×ž×š... + ×ž×™×™×¦× ×ž×¡×ž×š... Export successful. - ×”×™×™×¦×•× ×‘×•×¦×¢ בהצלחה. + ×”×™×™×¦×•× ×‘×•×¦×¢ בהצלחה. Export failed. - פעולת ×”×™×™×¦×•× × ×›×©×œ×” + פעולת ×”×™×™×¦×•× × ×›×©×œ×” @@ -1536,23 +1544,23 @@ UBImportCFF Common File Format ( - פורמט קובץ רגיל ) + פורמט קובץ רגיל ) Importing file %1... - ×ž×™×™×‘× ×§×•×‘×¥ %1... + ×ž×™×™×‘× ×§×•×‘×¥ %1... Import of file %1 failed. - ×™×™×‘×•× ×§×•×‘×¥ %1 נכשל. + ×™×™×‘×•× ×§×•×‘×¥ %1 נכשל. Import successful. - ×”×™×™×‘×•× ×‘×•×¦×¢ בהצלחה. + ×”×™×™×‘×•× ×‘×•×¦×¢ בהצלחה. Import failed. - ×”×™×™×‘×•× × ×›×©×œ. + ×”×™×™×‘×•× × ×›×©×œ. @@ -1679,10 +1687,6 @@ Do you want to ignore these errors for this host? Open-Sankore Documents Detected - - 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. - - Show this panel next time @@ -1699,6 +1703,10 @@ Do you want to ignore these errors for this host? Proceed + + 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. + + UBPersistenceManager @@ -2385,7 +2393,7 @@ p, li { white-space: pre-wrap; } Preferences העדפות - + version : … גרס×:... @@ -2517,11 +2525,11 @@ p, li { white-space: pre-wrap; } Credits ×שר××™ - + Open-Sankoré Importer - + Check if Open-Sankoré data could be imported at launch diff --git a/resources/i18n/OpenBoard_ja.ts b/resources/i18n/OpenBoard_ja.ts index 5acd0a76..1dbcbb29 100644 --- a/resources/i18n/OpenBoard_ja.ts +++ b/resources/i18n/OpenBoard_ja.ts @@ -1,6 +1,6 @@ - + BlackoutWidget @@ -840,14 +840,6 @@ QObject - - Element ID = - - - - Content is not supported in destination format. - - Remove Page ページ削除 @@ -937,6 +929,14 @@ Add file operation failed: file copying error + + Saving document... + + + + Document has just been saved... + + UBBoardPaletteManager @@ -1221,23 +1221,23 @@ UBExportCFF Export to IWB - IWBã¸ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ + IWBã¸ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ Export as IWB File - IWB ファイルã¨ã—ã¦ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ + IWB ファイルã¨ã—ã¦ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ Exporting document... - ドキュメントã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆä¸­... + ドキュメントã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆä¸­... Export successful. - エクスãƒãƒ¼ãƒˆã«æˆåŠŸ + エクスãƒãƒ¼ãƒˆã«æˆåŠŸ Export failed. - エクスãƒãƒ¼ãƒˆã«å¤±æ•— + エクスãƒãƒ¼ãƒˆã«å¤±æ•— @@ -1532,23 +1532,23 @@ UBImportCFF Common File Format ( - 共通ファイルフォーマット ( + 共通ファイルフォーマット ( Importing file %1... - ファイル%1ã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆä¸­... + ファイル%1ã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆä¸­... Import of file %1 failed. - ファイル%1ã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆå¤±æ•—。 + ファイル%1ã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆå¤±æ•—。 Import successful. - インãƒãƒ¼ãƒˆã«æˆåŠŸã€‚ + インãƒãƒ¼ãƒˆã«æˆåŠŸã€‚ Import failed. - インãƒãƒ¼ãƒˆå¤±æ•—。 + インãƒãƒ¼ãƒˆå¤±æ•—。 @@ -1681,10 +1681,6 @@ Do you want to ignore these errors for this host? Open-Sankore Documents Detected - - 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. - - Show this panel next time @@ -1701,6 +1697,10 @@ Do you want to ignore these errors for this host? Proceed + + 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. + + UBPersistenceManager @@ -2387,7 +2387,7 @@ p, li { white-space: pre-wrap; } Preferences 設定 - + version : … ãƒãƒ¼ã‚¸ãƒ§ãƒ³: … @@ -2519,11 +2519,11 @@ p, li { white-space: pre-wrap; } Credits - + Open-Sankoré Importer - + Check if Open-Sankoré data could be imported at launch diff --git a/resources/i18n/OpenBoard_ko.ts b/resources/i18n/OpenBoard_ko.ts index f7b4ab98..40a11e20 100644 --- a/resources/i18n/OpenBoard_ko.ts +++ b/resources/i18n/OpenBoard_ko.ts @@ -1,6 +1,6 @@ - + BlackoutWidget @@ -842,11 +842,11 @@ QObject Element ID = - 요소 ID = + 요소 ID = Content is not supported in destination format. - ëŒ€ìƒ í˜•ì‹ìœ¼ë¡œ 지ì›ë˜ì§€ 않는 콘í…츠입니다. + ëŒ€ìƒ í˜•ì‹ìœ¼ë¡œ 지ì›ë˜ì§€ 않는 콘í…츠입니다. Remove Page @@ -937,6 +937,14 @@ Ungroup 그룹 í•´ì œ + + Saving document... + + + + Document has just been saved... + + UBBoardPaletteManager @@ -1224,23 +1232,23 @@ UBExportCFF Export to IWB - IWBë¡œ 내보내기 + IWBë¡œ 내보내기 Export as IWB File - IWB 파ì¼ë¡œ 내보내기 + IWB 파ì¼ë¡œ 내보내기 Exporting document... - 문서를 내보내는 중... + 문서를 내보내는 중... Export successful. - 내보내기 완료. + 내보내기 완료. Export failed. - 내보내기 실패. + 내보내기 실패. @@ -1535,23 +1543,23 @@ UBImportCFF Common File Format ( - ì¼ë°˜ íŒŒì¼ í˜•ì‹ ( + ì¼ë°˜ íŒŒì¼ í˜•ì‹ ( Importing file %1... - %1 íŒŒì¼ ê°€ì ¸ì˜¤ëŠ” 중... + %1 íŒŒì¼ ê°€ì ¸ì˜¤ëŠ” 중... Import of file %1 failed. - %1 íŒŒì¼ ê°€ì ¸ì˜¤ê¸° 실패. + %1 íŒŒì¼ ê°€ì ¸ì˜¤ê¸° 실패. Import successful. - 가져오기 완료. + 가져오기 완료. Import failed. - 가져오기 실패. + 가져오기 실패. @@ -1683,10 +1691,6 @@ Do you want to ignore these errors for this host? Open-Sankore Documents Detected - - 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. - - Show this panel next time @@ -1703,6 +1707,10 @@ Do you want to ignore these errors for this host? Proceed + + 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. + + UBPersistenceManager @@ -2393,7 +2401,7 @@ p, li { white-space: pre-wrap; } Preferences 기본 설정 - + version : … 버전 : … @@ -2525,11 +2533,11 @@ p, li { white-space: pre-wrap; } Credits Credits - + Open-Sankoré Importer - + Check if Open-Sankoré data could be imported at launch diff --git a/resources/i18n/OpenBoard_mg.ts b/resources/i18n/OpenBoard_mg.ts index 3cbb0f55..76d97a49 100644 --- a/resources/i18n/OpenBoard_mg.ts +++ b/resources/i18n/OpenBoard_mg.ts @@ -1,6 +1,6 @@ - + BlackoutWidget @@ -842,11 +842,11 @@ QObject Element ID = - Isa famantaranaan'ilay zavatra = + Isa famantaranaan'ilay zavatra = Content is not supported in destination format. - Tsy zakan'ny andrefy tanjona ilay mpiatiny. + Tsy zakan'ny andrefy tanjona ilay mpiatiny. Remove Page @@ -937,6 +937,14 @@ Ungroup Avaho + + Saving document... + + + + Document has just been saved... + + UBBoardPaletteManager @@ -1223,23 +1231,23 @@ UBExportCFF Export to IWB - Alefa ho IWB + Alefa ho IWB Export as IWB File - Alefa ho rakitra IWB + Alefa ho rakitra IWB Exporting document... - Mandefa ny rakitra ... + Mandefa ny rakitra ... Export successful. - Fandefasana nety. + Fandefasana nety. Export failed. - Fandefasana tsy nety. + Fandefasana tsy nety. @@ -1534,23 +1542,23 @@ UBImportCFF Common File Format ( - Andrefin'ny rakitra mahazatra ( + Andrefin'ny rakitra mahazatra ( Importing file %1... - Manafatra rakitra %1 ... + Manafatra rakitra %1 ... Import of file %1 failed. - Fanafarana ny rakitra %1 tsy nety. + Fanafarana ny rakitra %1 tsy nety. Import successful. - Fanafarana nety. + Fanafarana nety. Import failed. - Fanafarana tsy nety. + Fanafarana tsy nety. @@ -1682,10 +1690,6 @@ Tena tsy te hiraharaha an'ireo tsy mety ho an'ilay milina ve ianao?Open-Sankore Documents Detected - - 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. - - Show this panel next time @@ -1702,6 +1706,10 @@ Tena tsy te hiraharaha an'ireo tsy mety ho an'ilay milina ve ianao?Proceed + + 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. + + UBPersistenceManager @@ -2472,7 +2480,7 @@ p, li { white-space: pre-wrap; } Marker Penina lehibe - + version : … kinova: ... @@ -2524,11 +2532,11 @@ p, li { white-space: pre-wrap; } Credits Voaka - + Open-Sankoré Importer - + Check if Open-Sankoré data could be imported at launch diff --git a/resources/i18n/OpenBoard_nb.ts b/resources/i18n/OpenBoard_nb.ts index 71d7af43..caa1385b 100644 --- a/resources/i18n/OpenBoard_nb.ts +++ b/resources/i18n/OpenBoard_nb.ts @@ -1,6 +1,6 @@ - + BlackoutWidget @@ -842,11 +842,11 @@ QObject Element ID = - Element-ID = + Element-ID = Content is not supported in destination format. - Innhold er ikke støttet i mottaksformat. + Innhold er ikke støttet i mottaksformat. Remove Page @@ -937,6 +937,14 @@ Ungroup Dele opp + + Saving document... + + + + Document has just been saved... + + UBBoardPaletteManager @@ -1224,23 +1232,23 @@ UBExportCFF Export to IWB - Eksporter til IWB + Eksporter til IWB Export as IWB File - Eksporter som IWB-fil + Eksporter som IWB-fil Exporting document... - Eksporterer dokument ... + Eksporterer dokument ... Export successful. - Eksport gjennomført. + Eksport gjennomført. Export failed. - Eksport mislyktes. + Eksport mislyktes. @@ -1535,23 +1543,23 @@ UBImportCFF Common File Format ( - Vanlig filformat ( + Vanlig filformat ( Importing file %1... - Importerer fil %1... + Importerer fil %1... Import of file %1 failed. - Importering av fil %1 mislyktes. + Importering av fil %1 mislyktes. Import successful. - Importering gjennomført. + Importering gjennomført. Import failed. - Importering mislyktes. + Importering mislyktes. @@ -1678,10 +1686,6 @@ Do you want to ignore these errors for this host? Open-Sankore Documents Detected - - 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. - - Show this panel next time @@ -1698,6 +1702,10 @@ Do you want to ignore these errors for this host? Proceed + + 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. + + UBPersistenceManager @@ -2387,7 +2395,7 @@ p, li { white-space: pre-wrap; } Preferences Preferanser - + version : … versjon: ... @@ -2521,11 +2529,11 @@ p, li { white-space: pre-wrap; } Translates as "thanks to" Takk til - + Open-Sankoré Importer - + Check if Open-Sankoré data could be imported at launch diff --git a/resources/i18n/OpenBoard_nl.ts b/resources/i18n/OpenBoard_nl.ts index 84a440cb..2467cd8d 100644 --- a/resources/i18n/OpenBoard_nl.ts +++ b/resources/i18n/OpenBoard_nl.ts @@ -1,6 +1,6 @@ - + BlackoutWidget @@ -840,14 +840,6 @@ QObject - - Element ID = - - - - Content is not supported in destination format. - - Remove Page Pagina verwijderen @@ -937,6 +929,14 @@ Ungroup + + Saving document... + + + + Document has just been saved... + + UBBoardPaletteManager @@ -1223,23 +1223,23 @@ UBExportCFF Export to IWB - Exporteer naar IWB + Exporteer naar IWB Export as IWB File - Exporteer als IWB bestand + Exporteer als IWB bestand Exporting document... - Document wordt geëxporteerd... + Document wordt geëxporteerd... Export successful. - Export gelukt. + Export gelukt. Export failed. - Export mislukt. + Export mislukt. @@ -1534,23 +1534,23 @@ UBImportCFF Common File Format ( - Standaard bestandformaat ( + Standaard bestandformaat ( Importing file %1... - Importering van bestand %1... + Importering van bestand %1... Import of file %1 failed. - Importering van bestand %1 is mislukt. + Importering van bestand %1 is mislukt. Import successful. - Import gelukt. + Import gelukt. Import failed. - Import mislukt. + Import mislukt. @@ -1676,10 +1676,6 @@ Do you want to ignore these errors for this host? Open-Sankore Documents Detected - - 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. - - Show this panel next time @@ -1696,6 +1692,10 @@ Do you want to ignore these errors for this host? Proceed + + 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. + + UBPersistenceManager @@ -2385,7 +2385,7 @@ p, li { white-space: pre-wrap; } Preferences Voorkeuren - + version : … versie : .... @@ -2517,11 +2517,11 @@ p, li { white-space: pre-wrap; } Credits Credits - + Open-Sankoré Importer - + Check if Open-Sankoré data could be imported at launch diff --git a/resources/i18n/OpenBoard_pl.ts b/resources/i18n/OpenBoard_pl.ts index e82c3cd1..19e36c0d 100644 --- a/resources/i18n/OpenBoard_pl.ts +++ b/resources/i18n/OpenBoard_pl.ts @@ -1,6 +1,6 @@ - + BlackoutWidget @@ -846,11 +846,11 @@ QObject Element ID = - ID elementu = + ID elementu = Content is not supported in destination format. - Zawartość nie jest obsÅ‚ugiwana w formacie docelowym. + Zawartość nie jest obsÅ‚ugiwana w formacie docelowym. Remove Page @@ -941,6 +941,14 @@ Ungroup Rozgrupuj + + Saving document... + + + + Document has just been saved... + + UBBoardPaletteManager @@ -1230,23 +1238,23 @@ UBExportCFF Export to IWB - Eksportowanie do IWB + Eksportowanie do IWB Export as IWB File - Eksportuj jako plik IWB + Eksportuj jako plik IWB Exporting 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. @@ -1541,23 +1549,23 @@ UBImportCFF Common File Format ( - Wspólny format plików ( + Wspólny format plików ( Importing file %1... - Importowanie pliku %1... + Importowanie pliku %1... Import of file %1 failed. - Importowanie pliku %1 zakoÅ„czone niepowodzeniem. + Importowanie pliku %1 zakoÅ„czone niepowodzeniem. Import successful. - Importowanie zakoÅ„czone powodzeniem. + Importowanie zakoÅ„czone powodzeniem. Import failed. - Importowanie zakoÅ„czone niepowodzeniem. + Importowanie zakoÅ„czone niepowodzeniem. @@ -1689,10 +1697,6 @@ Czy chcesz ignorować te bÅ‚Ä™dy dla tego hosta? Open-Sankore Documents Detected - - 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. - - Show this panel next time @@ -1709,6 +1713,10 @@ Czy chcesz ignorować te bÅ‚Ä™dy dla tego hosta? Proceed + + 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. + + UBPersistenceManager @@ -2403,7 +2411,7 @@ p, li { white-space: pre-wrap; } Preferences Preferencje - + version : … wersja:... @@ -2535,11 +2543,11 @@ p, li { white-space: pre-wrap; } Credits PodziÄ™kowania - + Open-Sankoré Importer - + Check if Open-Sankoré data could be imported at launch diff --git a/resources/i18n/OpenBoard_pt.ts b/resources/i18n/OpenBoard_pt.ts index a260610f..1924039e 100644 --- a/resources/i18n/OpenBoard_pt.ts +++ b/resources/i18n/OpenBoard_pt.ts @@ -1,6 +1,6 @@ - + BlackoutWidget @@ -844,11 +844,11 @@ QObject Element ID = - ID do Elemento + ID do Elemento Content 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 @@ -939,6 +939,14 @@ Ungroup Desagrupar + + Saving document... + + + + Document has just been saved... + + UBBoardPaletteManager @@ -1225,23 +1233,23 @@ UBExportCFF Export to IWB - Exportar para IWB + Exportar para IWB Export as IWB File - Exportar como ficheiro IWB + Exportar como ficheiro IWB Exporting document... - A exportar documento... + A exportar documento... Export successful. - Exportação bem sucedida. + Exportação bem sucedida. Export failed. - Falha na Exportação. + Falha na Exportação. @@ -1537,23 +1545,23 @@ UBImportCFF Common File Format ( - Formato de Ficheiro Frequente ( + Formato de Ficheiro Frequente ( Importing file %1... - A importar ficheiro %1... + A importar ficheiro %1... Import of file %1 failed. - Falha a importar ficheiro %1. + Falha a importar ficheiro %1. Import successful. - Importação bem sucedida. + Importação bem sucedida. Import failed. - Falha na importação. + Falha na importação. @@ -1685,10 +1693,6 @@ Quer ignorar estes erros, deste servidor? Open-Sankore Documents Detected - - 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. - - Show this panel next time @@ -1705,6 +1709,10 @@ Quer ignorar estes erros, deste servidor? Proceed + + 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. + + UBPersistenceManager @@ -2390,7 +2398,7 @@ p, li { white-space: pre-wrap; } Preferences Preferências - + version : … versão : ... @@ -2524,11 +2532,11 @@ p, li { white-space: pre-wrap; } Credits Créditos - + Open-Sankoré Importer - + Check if Open-Sankoré data could be imported at launch diff --git a/resources/i18n/OpenBoard_ro.ts b/resources/i18n/OpenBoard_ro.ts index ca0d82ec..4e08f09e 100644 --- a/resources/i18n/OpenBoard_ro.ts +++ b/resources/i18n/OpenBoard_ro.ts @@ -1,6 +1,6 @@ - + BlackoutWidget @@ -842,11 +842,11 @@ QObject Element ID = - ID element = + ID element = Content is not supported in destination format. - ConÈ›inutul nu este suportat în formatul de destinaÈ›ie. + ConÈ›inutul nu este suportat în formatul de destinaÈ›ie. Remove Page @@ -937,6 +937,14 @@ Ungroup Degrupare + + Saving document... + + + + Document has just been saved... + + UBBoardPaletteManager @@ -1223,23 +1231,23 @@ UBExportCFF Export to IWB - Exportare în IWB + Exportare în IWB Export as IWB File - Exportare ca fiÈ™ier IWB + Exportare ca fiÈ™ier IWB Exporting document... - Exportare document... + Exportare document... Export successful. - Exportare reuÅŸită. + Exportare reuÅŸită. Export failed. - Exportare nereuÅŸită. + Exportare nereuÅŸită. @@ -1534,23 +1542,23 @@ UBImportCFF Common File Format ( - Format de fiÅŸier comun ( + Format de fiÅŸier comun ( Importing file %1... - Importare fiÅŸier %1... + Importare fiÅŸier %1... Import of file %1 failed. - Importare fiÅŸier %1 nereuÅŸită. + Importare fiÅŸier %1 nereuÅŸită. Import successful. - Importare reuÅŸită. + Importare reuÅŸită. Import failed. - Importare nereuÅŸită. + Importare nereuÅŸită. @@ -1682,10 +1690,6 @@ DoriÅ£i să ignoraÅ£i aceste erori pentru acest host? Open-Sankore Documents Detected - - 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. - - Show this panel next time @@ -1702,6 +1706,10 @@ DoriÅ£i să ignoraÅ£i aceste erori pentru acest host? Proceed + + 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. + + UBPersistenceManager @@ -2392,7 +2400,7 @@ p, li { white-space: pre-wrap; } Preferences PreferinÅ£e - + version : … versiune : ... @@ -2524,11 +2532,11 @@ p, li { white-space: pre-wrap; } Credits Credite - + Open-Sankoré Importer - + Check if Open-Sankoré data could be imported at launch diff --git a/resources/i18n/OpenBoard_ru.ts b/resources/i18n/OpenBoard_ru.ts index 9fc99eb9..9fb30e64 100644 --- a/resources/i18n/OpenBoard_ru.ts +++ b/resources/i18n/OpenBoard_ru.ts @@ -1,6 +1,6 @@ - + BlackoutWidget @@ -842,11 +842,11 @@ QObject Element ID = - ID Ñлемента = + ID Ñлемента = Content is not supported in destination format. - Ðе поддерживаетÑÑ Ð² текущем формате. + Ðе поддерживаетÑÑ Ð² текущем формате. Remove Page @@ -937,6 +937,14 @@ Ungroup Разгруппировать + + Saving document... + + + + Document has just been saved... + + UBBoardPaletteManager @@ -1223,23 +1231,23 @@ UBExportCFF Export to IWB - ЭкÑпорт в IWB + ЭкÑпорт в IWB Export as IWB File - ЭкÑпортировать как IWB файл + ЭкÑпортировать как IWB файл Exporting document... - ЭкÑпорт документа... + ЭкÑпорт документа... Export successful. - ЭкÑпорт уÑпешно завершен. + ЭкÑпорт уÑпешно завершен. Export failed. - Ошибка ÑкÑпорта. + Ошибка ÑкÑпорта. @@ -1534,23 +1542,23 @@ UBImportCFF Common File Format ( - Стандартный формат файла ( + Стандартный формат файла ( Importing file %1... - Импорт файла %1... + Импорт файла %1... Import of file %1 failed. - Ошибка импорта файла %1. + Ошибка импорта файла %1. Import successful. - Импорт уÑпешно завершен. + Импорт уÑпешно завершен. Import failed. - Ошибка импорта. + Ошибка импорта. @@ -1682,10 +1690,6 @@ Do you want to ignore these errors for this host? Open-Sankore Documents Detected - - 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. - - Show this panel next time @@ -1702,6 +1706,10 @@ Do you want to ignore these errors for this host? Proceed + + 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. + + UBPersistenceManager @@ -2392,7 +2400,7 @@ p, li { white-space: pre-wrap; } Preferences ÐаÑтройки - + version : … верÑиÑ: … @@ -2524,11 +2532,11 @@ p, li { white-space: pre-wrap; } Credits Содержание - + Open-Sankoré Importer - + Check if Open-Sankoré data could be imported at launch diff --git a/resources/i18n/OpenBoard_sk.ts b/resources/i18n/OpenBoard_sk.ts index 8e4ca275..0db85569 100644 --- a/resources/i18n/OpenBoard_sk.ts +++ b/resources/i18n/OpenBoard_sk.ts @@ -1,6 +1,6 @@ - + BlackoutWidget @@ -844,11 +844,11 @@ QObject Element ID = - ID prvku = + ID prvku = Content is not supported in destination format. - Obsah nie je podporovaný v cieľovom formáte. + Obsah nie je podporovaný v cieľovom formáte. Remove Page @@ -939,6 +939,14 @@ Ungroup OddeliÅ¥ + + Saving document... + + + + Document has just been saved... + + UBBoardPaletteManager @@ -1227,23 +1235,23 @@ UBExportCFF Export to IWB - ExportovaÅ¥ do IWB + ExportovaÅ¥ do IWB Export as IWB File - ExportovaÅ¥ ako súbor IWB + ExportovaÅ¥ ako súbor IWB Exporting document... - Exportuje sa dokument... + Exportuje sa dokument... Export successful. - Export bol úspeÅ¡ný. + Export bol úspeÅ¡ný. Export failed. - Export sa nepodaril. + Export sa nepodaril. @@ -1538,23 +1546,23 @@ UBImportCFF Importing file %1... - Nahráva sa súbor %1... + Nahráva sa súbor %1... Import failed. - Nahrávanie sa nepodarilo. + Nahrávanie sa nepodarilo. Import of file %1 failed. - Nahrávanie súboru %1 sa nepodarilo. + Nahrávanie súboru %1 sa nepodarilo. Common File Format ( - SpoloÄný formát súboru ( + SpoloÄný formát súboru ( Import successful. - Nahrávanie bolo úspeÅ¡ne dokonÄené. + Nahrávanie bolo úspeÅ¡ne dokonÄené. @@ -1686,10 +1694,6 @@ Chcete ignorovaÅ¥ tieto chyby na tomto serveri? Open-Sankore Documents Detected - - 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. - - Show this panel next time @@ -1706,6 +1710,10 @@ Chcete ignorovaÅ¥ tieto chyby na tomto serveri? Proceed + + 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. + + UBPersistenceManager @@ -2480,7 +2488,7 @@ p, li { white-space: pre-wrap; } Preferences Predvoľby - + version : … Verzia:... @@ -2528,11 +2536,11 @@ p, li { white-space: pre-wrap; } Credits PoÄakovanie - + Open-Sankoré Importer - + Check if Open-Sankoré data could be imported at launch diff --git a/resources/i18n/OpenBoard_sv.ts b/resources/i18n/OpenBoard_sv.ts index 70beac99..9d7ba66a 100644 --- a/resources/i18n/OpenBoard_sv.ts +++ b/resources/i18n/OpenBoard_sv.ts @@ -1,6 +1,6 @@ - + BlackoutWidget @@ -842,11 +842,11 @@ QObject Element ID = - Element ID= + Element ID= Content is not supported in destination format. - InnehÃ¥llet stöds inte i destinationsformatet + InnehÃ¥llet stöds inte i destinationsformatet Remove Page @@ -938,6 +938,14 @@ Ungroup Avgruppera + + Saving document... + + + + Document has just been saved... + + UBBoardPaletteManager @@ -1224,23 +1232,23 @@ UBExportCFF Export to IWB - Exporter till IWB + Exporter till IWB Export as IWB File - Exportera som IWB-fil + Exportera som IWB-fil Exporting document... - Exporterar dokument... + Exporterar dokument... Export successful. - Export lyckades. + Export lyckades. Export failed. - Export misslyckades. + Export misslyckades. @@ -1535,23 +1543,23 @@ UBImportCFF Common File Format ( - Gemensamt filformat + Gemensamt filformat Importing file %1... - Importerar fil %1... + Importerar fil %1... Import of file %1 failed. - Import av fil %1 misslyckades. + Import av fil %1 misslyckades. Import successful. - Import lyckades. + Import lyckades. Import failed. - Import msslyckades. + Import msslyckades. @@ -1683,10 +1691,6 @@ Vill du ignorera felen för den här värden? Open-Sankore Documents Detected - - 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. - - Show this panel next time @@ -1703,6 +1707,10 @@ Vill du ignorera felen för den här värden? Proceed + + 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. + + UBPersistenceManager @@ -2393,7 +2401,7 @@ p, li { white-space: pre-wrap; } Preferences Inställningar - + version : … version : … @@ -2525,11 +2533,11 @@ p, li { white-space: pre-wrap; } Credits Poäng - + Open-Sankoré Importer - + Check if Open-Sankoré data could be imported at launch diff --git a/resources/i18n/OpenBoard_tr.ts b/resources/i18n/OpenBoard_tr.ts index 0063297b..57c841d8 100644 --- a/resources/i18n/OpenBoard_tr.ts +++ b/resources/i18n/OpenBoard_tr.ts @@ -1,6 +1,6 @@ - + BlackoutWidget @@ -842,11 +842,11 @@ QObject Element ID = - Element ID = + Element ID = Content is not supported in destination format. - İçerik hedef içerik için uygun geÄŸil. + İçerik hedef içerik için uygun geÄŸil. Remove Page @@ -937,6 +937,14 @@ Ungroup Gurubu Ayır + + Saving document... + + + + Document has just been saved... + + UBBoardPaletteManager @@ -1222,23 +1230,23 @@ UBExportCFF Export to IWB - IWB'e Aktar + IWB'e Aktar Export as IWB File - IWB Dosyası Olarak Aktar + IWB Dosyası Olarak Aktar Exporting document... - Döküman dışa aktarılıyor... + Döküman dışa aktarılıyor... Export successful. - Dışa aktarma tamamlandı. + Dışa aktarma tamamlandı. Export failed. - Dışa aktarma baÅŸarısız oldu. + Dışa aktarma baÅŸarısız oldu. @@ -1533,23 +1541,23 @@ UBImportCFF Common File Format ( - Genel Dosya Biçimi ( + Genel Dosya Biçimi ( Importing file %1... - İçe aktarılan dosya: %1... + İçe aktarılan dosya: %1... Import of file %1 failed. - %1 adlı dosya içe aktarılamadı. + %1 adlı dosya içe aktarılamadı. Import successful. - İçe aktarım tamamlandı. + İçe aktarım tamamlandı. Import failed. - İçe aktarım tamamlanmadı. + İçe aktarım tamamlanmadı. @@ -1680,10 +1688,6 @@ Bu host için yukarıdaki hatalar yok sayılsın mı? Open-Sankore Documents Detected - - 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. - - Show this panel next time @@ -1700,6 +1704,10 @@ Bu host için yukarıdaki hatalar yok sayılsın mı? Proceed + + 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. + + UBPersistenceManager @@ -2470,7 +2478,7 @@ p, li { white-space: pre-wrap; } Marker Fosforlu Kalem - + version : … Versiyon: ... @@ -2522,11 +2530,11 @@ p, li { white-space: pre-wrap; } Credits Künye - + Open-Sankoré Importer - + Check if Open-Sankoré data could be imported at launch diff --git a/resources/i18n/OpenBoard_zh.ts b/resources/i18n/OpenBoard_zh.ts index 31e28728..c602953e 100644 --- a/resources/i18n/OpenBoard_zh.ts +++ b/resources/i18n/OpenBoard_zh.ts @@ -1,6 +1,6 @@ - + BlackoutWidget @@ -842,11 +842,11 @@ QObject Element ID = - Element ID = + Element ID = Content is not supported in destination format. - 目标格å¼ä¸æ”¯æŒè¯¥å†…容。 + 目标格å¼ä¸æ”¯æŒè¯¥å†…容。 Remove Page @@ -937,6 +937,14 @@ Ungroup å–æ¶ˆç»„åˆ + + Saving document... + + + + Document has just been saved... + + UBBoardPaletteManager @@ -1221,23 +1229,23 @@ UBExportCFF Export to IWB - 导出至IWB + 导出至IWB Export as IWB File - 以 IWB文件格å¼å¯¼å‡º + 以 IWB文件格å¼å¯¼å‡º Exporting document... - 文档导出中…… + 文档导出中…… Export successful. - 导出æˆåŠŸã€‚ + 导出æˆåŠŸã€‚ Export failed. - 导出失败。 + 导出失败。 @@ -1532,23 +1540,23 @@ UBImportCFF Common File Format ( - 常è§æ–‡ä»¶æ ¼å¼ ( + 常è§æ–‡ä»¶æ ¼å¼ ( Importing file %1... - 正在导入文件 %1…… + 正在导入文件 %1…… Import of file %1 failed. - 文件%1导入失败 + 文件%1导入失败 Import successful. - 导入æˆåŠŸ + 导入æˆåŠŸ Import failed. - 导入失败 + 导入失败 @@ -1680,10 +1688,6 @@ Do you want to ignore these errors for this host? Open-Sankore Documents Detected - - 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. - - Show this panel next time @@ -1700,6 +1704,10 @@ Do you want to ignore these errors for this host? Proceed + + 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. + + UBPersistenceManager @@ -2390,7 +2398,7 @@ p, li { white-space: pre-wrap; } Preferences 自定义 - + version : … 版本:…… @@ -2522,11 +2530,11 @@ p, li { white-space: pre-wrap; } Credits ç‰ˆæƒ - + Open-Sankoré Importer - + Check if Open-Sankoré data could be imported at launch diff --git a/resources/i18n/OpenBoard_zh_CN.ts b/resources/i18n/OpenBoard_zh_CN.ts index 31e28728..c602953e 100644 --- a/resources/i18n/OpenBoard_zh_CN.ts +++ b/resources/i18n/OpenBoard_zh_CN.ts @@ -1,6 +1,6 @@ - + BlackoutWidget @@ -842,11 +842,11 @@ QObject Element ID = - Element ID = + Element ID = Content is not supported in destination format. - 目标格å¼ä¸æ”¯æŒè¯¥å†…容。 + 目标格å¼ä¸æ”¯æŒè¯¥å†…容。 Remove Page @@ -937,6 +937,14 @@ Ungroup å–æ¶ˆç»„åˆ + + Saving document... + + + + Document has just been saved... + + UBBoardPaletteManager @@ -1221,23 +1229,23 @@ UBExportCFF Export to IWB - 导出至IWB + 导出至IWB Export as IWB File - 以 IWB文件格å¼å¯¼å‡º + 以 IWB文件格å¼å¯¼å‡º Exporting document... - 文档导出中…… + 文档导出中…… Export successful. - 导出æˆåŠŸã€‚ + 导出æˆåŠŸã€‚ Export failed. - 导出失败。 + 导出失败。 @@ -1532,23 +1540,23 @@ UBImportCFF Common File Format ( - 常è§æ–‡ä»¶æ ¼å¼ ( + 常è§æ–‡ä»¶æ ¼å¼ ( Importing file %1... - 正在导入文件 %1…… + 正在导入文件 %1…… Import of file %1 failed. - 文件%1导入失败 + 文件%1导入失败 Import successful. - 导入æˆåŠŸ + 导入æˆåŠŸ Import failed. - 导入失败 + 导入失败 @@ -1680,10 +1688,6 @@ Do you want to ignore these errors for this host? Open-Sankore Documents Detected - - 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. - - Show this panel next time @@ -1700,6 +1704,10 @@ Do you want to ignore these errors for this host? Proceed + + 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. + + UBPersistenceManager @@ -2390,7 +2398,7 @@ p, li { white-space: pre-wrap; } Preferences 自定义 - + version : … 版本:…… @@ -2522,11 +2530,11 @@ p, li { white-space: pre-wrap; } Credits ç‰ˆæƒ - + Open-Sankoré Importer - + Check if Open-Sankoré data could be imported at launch diff --git a/resources/i18n/OpenBoard_zh_TW.ts b/resources/i18n/OpenBoard_zh_TW.ts index fa34f77c..adec0034 100644 --- a/resources/i18n/OpenBoard_zh_TW.ts +++ b/resources/i18n/OpenBoard_zh_TW.ts @@ -1,6 +1,6 @@ - + BlackoutWidget @@ -842,11 +842,11 @@ QObject Element ID = - 元件ID = + 元件ID = Content is not supported in destination format. - 內容格å¼ä¸æ”¯æ´ã€‚ + 內容格å¼ä¸æ”¯æ´ã€‚ Remove Page @@ -937,6 +937,14 @@ Ungroup å–消群組 + + Saving document... + + + + Document has just been saved... + + UBBoardPaletteManager @@ -1221,23 +1229,23 @@ UBExportCFF Export to IWB - 匯出至IWB + 匯出至IWB Export as IWB File - 以IWBæ ¼å¼åŒ¯å‡º + 以IWBæ ¼å¼åŒ¯å‡º Exporting document... - 匯出文件... + 匯出文件... Export successful. - æˆåŠŸåŒ¯å‡ºã€‚ + æˆåŠŸåŒ¯å‡ºã€‚ Export failed. - 匯出失敗。 + 匯出失敗。 @@ -1532,23 +1540,23 @@ UBImportCFF Common File Format ( - å¸¸è¦‹æª”æ¡ˆæ ¼å¼ ( + å¸¸è¦‹æª”æ¡ˆæ ¼å¼ ( Importing file %1... - 檔案 %1 匯入中... + 檔案 %1 匯入中... Import of file %1 failed. - 檔案 %1 匯入失敗。 + 檔案 %1 匯入失敗。 Import successful. - 匯入æˆåŠŸã€‚ + 匯入æˆåŠŸã€‚ Import failed. - 匯入失敗。 + 匯入失敗。 @@ -1674,10 +1682,6 @@ Do you want to ignore these errors for this host? Open-Sankore Documents Detected - - 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. - - Show this panel next time @@ -1694,6 +1698,10 @@ Do you want to ignore these errors for this host? Proceed + + 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. + + UBPersistenceManager @@ -2457,7 +2465,7 @@ p, li { white-space: pre-wrap; } Marker æ示筆 - + version : … 版本: … @@ -2509,11 +2517,11 @@ p, li { white-space: pre-wrap; } Credits è²¢ç» - + Open-Sankoré Importer - + Check if Open-Sankoré data could be imported at launch From 8a645607858c8d3be3a4330f52238af6240ea50a Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Tue, 15 Dec 2015 10:55:04 +0100 Subject: [PATCH 062/243] removed import of removed library --- src/frameworks/UBPlatformUtils_mac.mm | 1 - 1 file changed, 1 deletion(-) diff --git a/src/frameworks/UBPlatformUtils_mac.mm b/src/frameworks/UBPlatformUtils_mac.mm index 17b87548..cdd2d237 100644 --- a/src/frameworks/UBPlatformUtils_mac.mm +++ b/src/frameworks/UBPlatformUtils_mac.mm @@ -35,7 +35,6 @@ #import #import #import -#import NSString* bundleShortVersion(NSBundle *bundle) { From 05fc24bee03ea97c45cf89aa446675ef9fe2c7ca Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Tue, 15 Dec 2015 10:55:35 +0100 Subject: [PATCH 063/243] Updated version to 1.10alpha3 --- OpenBoard.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenBoard.pro b/OpenBoard.pro index fdde384c..a5111164 100644 --- a/OpenBoard.pro +++ b/OpenBoard.pro @@ -11,7 +11,7 @@ CONFIG += debug_and_release \ VERSION_MAJ = 1 VERSION_MIN = 1 VERSION_TYPE = a # a = alpha, b = beta, rc = release candidate, r = release, other => error -VERSION_PATCH = 1 +VERSION_PATCH = 3 VERSION = "$${VERSION_MAJ}.$${VERSION_MIN}.$${VERSION_TYPE}.$${VERSION_PATCH}" VERSION = $$replace(VERSION, "\\.r", "") From 3dc320d13a38af3e8fbadfb13bbf55a3953129e1 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Wed, 16 Dec 2015 14:08:56 +0100 Subject: [PATCH 064/243] Small correction in french translation --- resources/i18n/OpenBoard_fr.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/i18n/OpenBoard_fr.ts b/resources/i18n/OpenBoard_fr.ts index 72fac092..fab81db4 100644 --- a/resources/i18n/OpenBoard_fr.ts +++ b/resources/i18n/OpenBoard_fr.ts @@ -944,7 +944,7 @@ Document has just been saved... - Le document vient d'être enregistré... + Le document vient d'être sauvegardé... From 63b1742010f6b0764692d1f8a092949ae8876948 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Wed, 16 Dec 2015 14:16:00 +0100 Subject: [PATCH 065/243] Added a 5th pen color (yellow by default) --- resources/forms/mainWindow.ui | 9 +++++++++ src/board/UBBoardController.cpp | 1 + src/core/UBSettings.cpp | 4 ++-- src/desktop/UBDesktopPropertyPalette.cpp | 2 ++ 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/resources/forms/mainWindow.ui b/resources/forms/mainWindow.ui index 552db21e..a56f509d 100644 --- a/resources/forms/mainWindow.ui +++ b/resources/forms/mainWindow.ui @@ -445,6 +445,15 @@ Color + + + + :/images/toolbar/color.png:/images/toolbar/color.png + + + Color + + diff --git a/src/board/UBBoardController.cpp b/src/board/UBBoardController.cpp index ceb85256..99af72b7 100644 --- a/src/board/UBBoardController.cpp +++ b/src/board/UBBoardController.cpp @@ -291,6 +291,7 @@ void UBBoardController::setupToolbar() colorActions.append(mMainWindow->actionColor1); colorActions.append(mMainWindow->actionColor2); colorActions.append(mMainWindow->actionColor3); + colorActions.append(mMainWindow->actionColor4); UBToolbarButtonGroup *colorChoice = new UBToolbarButtonGroup(mMainWindow->boardToolBar, colorActions); diff --git a/src/core/UBSettings.cpp b/src/core/UBSettings.cpp index 64595ce1..a076d664 100644 --- a/src/core/UBSettings.cpp +++ b/src/core/UBSettings.cpp @@ -45,7 +45,7 @@ QPointer UBSettings::sSingleton = 0; int UBSettings::pointerDiameter = 40; int UBSettings::crossSize = 32; -int UBSettings::colorPaletteSize = 4; +int UBSettings::colorPaletteSize = 5; int UBSettings::objectFrameWidth = 20; int UBSettings::boardMargin = 10; @@ -265,7 +265,7 @@ void UBSettings::init() pageDpi = new UBSetting(this, "Board", "pageDpi", 0); QStringList penLightBackgroundColors; - penLightBackgroundColors << "#000000" << "#FF0000" <<"#004080" << "#008000" << "#C87400" << "#800040" << "#008080" << "#5F2D0A"; + penLightBackgroundColors << "#000000" << "#FF0000" <<"#004080" << "#008000" << "#FFFF00" << "#C87400" << "#800040" << "#008080" << "#5F2D0A"; boardPenLightBackgroundColors = new UBColorListSetting(this, "Board", "PenLightBackgroundColors", penLightBackgroundColors, 1.0); QStringList penDarkBackgroundColors; diff --git a/src/desktop/UBDesktopPropertyPalette.cpp b/src/desktop/UBDesktopPropertyPalette.cpp index d44b6bb6..6a65c43c 100644 --- a/src/desktop/UBDesktopPropertyPalette.cpp +++ b/src/desktop/UBDesktopPropertyPalette.cpp @@ -55,6 +55,7 @@ UBDesktopPenPalette::UBDesktopPenPalette(QWidget *parent, UBRightPalette* rightP colorActions.append(UBApplication::mainWindow->actionColor1); colorActions.append(UBApplication::mainWindow->actionColor2); colorActions.append(UBApplication::mainWindow->actionColor3); + colorActions.append(UBApplication::mainWindow->actionColor4); UBToolbarButtonGroup *colorChoice = new UBToolbarButtonGroup(UBApplication::mainWindow->boardToolBar, colorActions); @@ -151,6 +152,7 @@ UBDesktopMarkerPalette::UBDesktopMarkerPalette(QWidget *parent, UBRightPalette* colorActions.append(UBApplication::mainWindow->actionColor1); colorActions.append(UBApplication::mainWindow->actionColor2); colorActions.append(UBApplication::mainWindow->actionColor3); + colorActions.append(UBApplication::mainWindow->actionColor4); UBToolbarButtonGroup *colorChoice = new UBToolbarButtonGroup(UBApplication::mainWindow->boardToolBar, colorActions); colorChoice->displayText(false); From 125d8a4f847713e8fd92ecf961afafc6b8d7dcfa Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Thu, 17 Dec 2015 14:26:59 +0100 Subject: [PATCH 066/243] Made yellow slightly redder for pen on white background --- src/core/UBSettings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/UBSettings.cpp b/src/core/UBSettings.cpp index a076d664..fe07f280 100644 --- a/src/core/UBSettings.cpp +++ b/src/core/UBSettings.cpp @@ -265,7 +265,7 @@ void UBSettings::init() pageDpi = new UBSetting(this, "Board", "pageDpi", 0); QStringList penLightBackgroundColors; - penLightBackgroundColors << "#000000" << "#FF0000" <<"#004080" << "#008000" << "#FFFF00" << "#C87400" << "#800040" << "#008080" << "#5F2D0A"; + penLightBackgroundColors << "#000000" << "#FF0000" <<"#004080" << "#008000" << "#FFDD00" << "#C87400" << "#800040" << "#008080" << "#5F2D0A"; boardPenLightBackgroundColors = new UBColorListSetting(this, "Board", "PenLightBackgroundColors", penLightBackgroundColors, 1.0); QStringList penDarkBackgroundColors; From 665945f5900713373bbaf9baf3603e7cb31d8b15 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Thu, 17 Dec 2015 14:35:45 +0100 Subject: [PATCH 067/243] Re-enabled podcasts on Win32 - Linked necessary Windows SDK libraries - Solved compilation errors upon including `wmsdk.h` or other Windows SDK headers (`interface` keyword wasn't recognized) --- OpenBoard.pro | 13 +++++++++++-- src/podcast/UBPodcastController.cpp | 6 +++--- src/podcast/podcast.pri | 14 +++++++------- src/podcast/windowsmedia/UBWindowsMediaFile.h | 5 +++-- .../windowsmedia/UBWindowsMediaVideoEncoder.cpp | 1 - 5 files changed, 24 insertions(+), 15 deletions(-) diff --git a/OpenBoard.pro b/OpenBoard.pro index a5111164..c442a008 100644 --- a/OpenBoard.pro +++ b/OpenBoard.pro @@ -109,12 +109,20 @@ RCC_DIR = $$BUILD_DIR/rcc UI_DIR = $$BUILD_DIR/ui win32 { + + + LIBS += -lUser32 + LIBS += -lGdi32 + LIBS += -lAdvApi32 + LIBS += -lOle32 + RC_FILE = resources/win/OpenBoard.rc - CONFIG += qaxcontainer + CONFIG += axcontainer exists(console):CONFIG += console QMAKE_CXXFLAGS += /MP + QMAKE_CXXFLAGS += /MD QMAKE_CXXFLAGS_RELEASE += /Od /Zi - QMAKE_LFLAGS_RELEASE += /DEBUG + QMAKE_LFLAGS += /VERBOSE:LIB UB_LIBRARY.path = $$DESTDIR UB_I18N.path = $$DESTDIR/i18n UB_ETC.path = $$DESTDIR @@ -126,6 +134,7 @@ win32 { DEFINES += NOMINMAX # avoids compilation error in qdatetime.h + } macx { diff --git a/src/podcast/UBPodcastController.cpp b/src/podcast/UBPodcastController.cpp index 98a5c79f..7dbb3644 100644 --- a/src/podcast/UBPodcastController.cpp +++ b/src/podcast/UBPodcastController.cpp @@ -57,8 +57,8 @@ #ifdef Q_OS_WIN - // #include "windowsmedia/UBWindowsMediaVideoEncoder.h" - // #include "windowsmedia/UBWaveRecorder.h" + #include "windowsmedia/UBWindowsMediaVideoEncoder.h" + #include "windowsmedia/UBWaveRecorder.h" #elif defined(Q_OS_OSX) #include "quicktime/UBQuickTimeVideoEncoder.h" #include "quicktime/UBAudioQueueRecorder.h" @@ -304,7 +304,7 @@ void UBPodcastController::start() applicationMainModeChanged(UBApplication::applicationController->displayMode()); #ifdef Q_OS_WIN - //mVideoEncoder = new UBWindowsMediaVideoEncoder(this); //deleted on stop + mVideoEncoder = new UBWindowsMediaVideoEncoder(this); //deleted on stop #elif defined(Q_OS_OSX) mVideoEncoder = new UBQuickTimeVideoEncoder(this); //deleted on stop #endif diff --git a/src/podcast/podcast.pri b/src/podcast/podcast.pri index a9ced647..af441814 100644 --- a/src/podcast/podcast.pri +++ b/src/podcast/podcast.pri @@ -13,13 +13,13 @@ SOURCES += src/podcast/UBPodcastController.cpp \ win32 { -# SOURCES += src/podcast/windowsmedia/UBWindowsMediaVideoEncoder.cpp \ -# src/podcast/windowsmedia/UBWindowsMediaFile.cpp \ -# src/podcast/windowsmedia/UBWaveRecorder.cpp -# -# HEADERS += src/podcast/windowsmedia/UBWindowsMediaVideoEncoder.h \ -# src/podcast/windowsmedia/UBWindowsMediaFile.h \ -# src/podcast/windowsmedia/UBWaveRecorder.h + SOURCES += src/podcast/windowsmedia/UBWindowsMediaVideoEncoder.cpp \ + src/podcast/windowsmedia/UBWindowsMediaFile.cpp \ + src/podcast/windowsmedia/UBWaveRecorder.cpp + + HEADERS += src/podcast/windowsmedia/UBWindowsMediaVideoEncoder.h \ + src/podcast/windowsmedia/UBWindowsMediaFile.h \ + src/podcast/windowsmedia/UBWaveRecorder.h } macx { diff --git a/src/podcast/windowsmedia/UBWindowsMediaFile.h b/src/podcast/windowsmedia/UBWindowsMediaFile.h index 703e027a..0f3d869c 100644 --- a/src/podcast/windowsmedia/UBWindowsMediaFile.h +++ b/src/podcast/windowsmedia/UBWindowsMediaFile.h @@ -30,8 +30,9 @@ #include -#include - +#ifndef inteface +#define interface struct +#endif #include class UBWindowsMediaFile : public QObject diff --git a/src/podcast/windowsmedia/UBWindowsMediaVideoEncoder.cpp b/src/podcast/windowsmedia/UBWindowsMediaVideoEncoder.cpp index 6645279c..d474cb0f 100644 --- a/src/podcast/windowsmedia/UBWindowsMediaVideoEncoder.cpp +++ b/src/podcast/windowsmedia/UBWindowsMediaVideoEncoder.cpp @@ -33,7 +33,6 @@ #include "core/UBApplication.h" -#include "UBWindowsMediaFile.h" #include "core/memcheck.h" From 9adc8991cd11d30d1fb095b64b21bbb219bff30e Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Fri, 18 Dec 2015 17:11:44 +0100 Subject: [PATCH 068/243] Fixed UBPlatformUtils::showFullScreen not maximizing to full screen on OS X 10.9 --- src/frameworks/UBPlatformUtils_mac.mm | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/frameworks/UBPlatformUtils_mac.mm b/src/frameworks/UBPlatformUtils_mac.mm index cdd2d237..36bfca8a 100644 --- a/src/frameworks/UBPlatformUtils_mac.mm +++ b/src/frameworks/UBPlatformUtils_mac.mm @@ -588,12 +588,24 @@ void UBPlatformUtils::setFrontProcess() */ void UBPlatformUtils::showFullScreen(QWidget *pWidget) { - pWidget->showMaximized(); - - /* On OS X, we want to hide the Dock and menu bar (aka "kiosk mode"). Qt's default behaviour - * when full-screening a QWidget is to set the dock and menu bar to auto-hide. + /* OpenBoard is designed to be run in "kiosk mode", i.e full screen. + * On OS X, we want to maximize the application while hiding the dock and menu bar, + * rather than use OS X's native full screen mode (which places the window on a new desktop). + * However, Qt's default behaviour when full-screening a QWidget is to set the dock and menu bar to auto-hide. * Since it is impossible to later set different presentation options (i.e Hide dock & menu bar) * to NSApplication, we have to avoid calling QWidget::showFullScreen on OSX. */ + + pWidget->showMaximized(); + + /* Hack. On OS X 10.10, showMaximize() resizes the widget to full screen; + but on 10.9, it is placed in the "available" screen area (i.e the screen area minus + the menu bar and dock area). So we have to manually resize it to the total screen height, + and move it up to the top of the screen (0,0 position) */ + + QDesktopWidget * desktop = QApplication::desktop(); + pWidget->resize(pWidget->width(), desktop->screenGeometry().height()); + pWidget->move(0, 0); + } From 024322c8d101b5bb9223eff6ca05d387bf1bbce8 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Mon, 21 Dec 2015 10:03:42 +0100 Subject: [PATCH 069/243] Fixed full-screen widgets all being moved to primary screen on OSX (due to commit 9adc899). Fullscreening should now work as expected in OSX 10.9 and 10.10, with one or multiple monitors. --- src/frameworks/UBPlatformUtils_mac.mm | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/frameworks/UBPlatformUtils_mac.mm b/src/frameworks/UBPlatformUtils_mac.mm index 36bfca8a..1ec487aa 100644 --- a/src/frameworks/UBPlatformUtils_mac.mm +++ b/src/frameworks/UBPlatformUtils_mac.mm @@ -598,14 +598,14 @@ void UBPlatformUtils::showFullScreen(QWidget *pWidget) pWidget->showMaximized(); - /* Hack. On OS X 10.10, showMaximize() resizes the widget to full screen; - but on 10.9, it is placed in the "available" screen area (i.e the screen area minus - the menu bar and dock area). So we have to manually resize it to the total screen height, - and move it up to the top of the screen (0,0 position) */ + /* Bit of a hack. On OS X 10.10, showMaximized() resizes the widget to full screen (if the dock and + * menu bar are hidden); but on 10.9, it is placed in the "available" screen area (i.e the + * screen area minus the menu bar and dock area). So we have to manually resize it to the + * total screen height, and move it up to the top of the screen (y=0 position). */ QDesktopWidget * desktop = QApplication::desktop(); pWidget->resize(pWidget->width(), desktop->screenGeometry().height()); - pWidget->move(0, 0); + pWidget->move(pWidget->pos().x(), 0); } From 6faeea9ddbaa86d1171aa9ee8072b55618926322 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Mon, 21 Dec 2015 10:06:51 +0100 Subject: [PATCH 070/243] Corrected pen stroke duplication issue (see below) Presumably due to the change in how pen strokes were saved to file (commit 8ed2e24), pen strokes with pressure levels were badly saved. They were converted to lines instead of polygons, meaning that every time a page was saved or duplicated, the lines would look worse and worse -- and artefacts would appear. This should now be fixed. --- src/adaptors/UBSvgSubsetAdaptor.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/adaptors/UBSvgSubsetAdaptor.cpp b/src/adaptors/UBSvgSubsetAdaptor.cpp index 5a38311e..21c57dfe 100644 --- a/src/adaptors/UBSvgSubsetAdaptor.cpp +++ b/src/adaptors/UBSvgSubsetAdaptor.cpp @@ -1145,11 +1145,15 @@ bool UBSvgSubsetAdaptor::UBSvgSubsetWriter::persistScene(int pageIndex) } } - if (polygonItem->isNominalLine()) - polygonItemToSvgLine(polygonItem, groupHoldsInfo); - else + UBGraphicsStroke* stroke = dynamic_cast(currentStroke); + + if (stroke && stroke->hasPressure()) polygonItemToSvgPolygon(polygonItem, groupHoldsInfo); + else if (polygonItem->isNominalLine()) + polygonItemToSvgLine(polygonItem, groupHoldsInfo); + + continue; } @@ -2100,7 +2104,6 @@ UBGraphicsMediaItem* UBSvgSubsetAdaptor::UBSvgSubsetReader::videoItemFromSvg() void UBSvgSubsetAdaptor::UBSvgSubsetReader::graphicsItemFromSvg(QGraphicsItem* gItem) { - // TODO: check position QStringRef svgTransform = mXmlReader.attributes().value("transform"); QMatrix itemMatrix; From f26f3d1c6a628c25af64844e1152cd6f2025a87d Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Mon, 21 Dec 2015 12:13:40 +0100 Subject: [PATCH 071/243] Enabled cross-origin requests to allow W3C widgets to load remote content --- src/domain/UBGraphicsWidgetItem.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/domain/UBGraphicsWidgetItem.cpp b/src/domain/UBGraphicsWidgetItem.cpp index cfa974da..0f7edbf6 100644 --- a/src/domain/UBGraphicsWidgetItem.cpp +++ b/src/domain/UBGraphicsWidgetItem.cpp @@ -81,6 +81,7 @@ UBGraphicsWidgetItem::UBGraphicsWidgetItem(const QUrl &pWidgetUrl, QGraphicsItem QGraphicsWebView::settings()->setAttribute(QWebSettings::OfflineStorageDatabaseEnabled, true); QGraphicsWebView::settings()->setAttribute(QWebSettings::JavascriptCanAccessClipboard, true); QGraphicsWebView::settings()->setAttribute(QWebSettings::DnsPrefetchEnabled, true); + QGraphicsWebView::settings()->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls, true); page()->setNetworkAccessManager(UBNetworkAccessManager::defaultAccessManager()); From 82c349468ec62d91b5ebeb6c043826ce661bb83d Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Mon, 21 Dec 2015 12:23:08 +0100 Subject: [PATCH 072/243] Updated (/corrected) version number --- OpenBoard.pro | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenBoard.pro b/OpenBoard.pro index c442a008..6e9553dc 100644 --- a/OpenBoard.pro +++ b/OpenBoard.pro @@ -9,9 +9,9 @@ CONFIG += debug_and_release \ VERSION_MAJ = 1 -VERSION_MIN = 1 +VERSION_MIN = 10 VERSION_TYPE = a # a = alpha, b = beta, rc = release candidate, r = release, other => error -VERSION_PATCH = 3 +VERSION_PATCH = 4 VERSION = "$${VERSION_MAJ}.$${VERSION_MIN}.$${VERSION_TYPE}.$${VERSION_PATCH}" VERSION = $$replace(VERSION, "\\.r", "") From 7e2b463853e30db548fb720d0bad622e388503fe Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Tue, 22 Dec 2015 17:07:06 +0100 Subject: [PATCH 073/243] Fixed screenshot taking pixmap of entire desktop in multiscreen environment --- src/desktop/UBDesktopAnnotationController.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/desktop/UBDesktopAnnotationController.cpp b/src/desktop/UBDesktopAnnotationController.cpp index cc15b94a..4f7a0a76 100644 --- a/src/desktop/UBDesktopAnnotationController.cpp +++ b/src/desktop/UBDesktopAnnotationController.cpp @@ -500,11 +500,12 @@ void UBDesktopAnnotationController::screenCapture() QPixmap UBDesktopAnnotationController::getScreenPixmap() { QDesktopWidget *desktop = QApplication::desktop(); - - QScreen * screen = QApplication::primaryScreen(); - return screen->grabWindow(desktop->effectiveWinId()); + QRect rect = desktop->screenGeometry(QCursor::pos()); + + return screen->grabWindow(desktop->effectiveWinId(), + rect.x(), rect.y(), rect.width(), rect.height()); } From 51bfde681ef7baf03c13a0138a6a88e76ed6b255 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Tue, 22 Dec 2015 17:57:38 +0100 Subject: [PATCH 074/243] Replace deprecated QPixmap::grabWindow function --- src/gui/UBScreenMirror.cpp | 5 +++-- src/podcast/UBPodcastController.cpp | 7 ++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/gui/UBScreenMirror.cpp b/src/gui/UBScreenMirror.cpp index a4cda1be..c97ecef8 100644 --- a/src/gui/UBScreenMirror.cpp +++ b/src/gui/UBScreenMirror.cpp @@ -98,8 +98,9 @@ void UBScreenMirror::grabPixmap() // WHY HERE? // this is the case we are showing the desktop but the is no widget and we use the last widget rectagle to know // what we have to grab. Not very good way of doing - WId windowID = qApp->desktop()->screen(mScreenIndex)->winId(); - mLastPixmap = QPixmap::grabWindow(windowID, mRect.x(), mRect.y(), mRect.width(), mRect.height()); + QDesktopWidget * desktop = QApplication::desktop(); + QScreen * screen = QApplication::primaryScreen(); + mLastPixmap = screen->grabWindow(desktop->effectiveWinId(), mRect.x(), mRect.y(), mRect.width(), mRect.height()); } mLastPixmap = mLastPixmap.scaled(width(), height(), Qt::KeepAspectRatio, Qt::SmoothTransformation); diff --git a/src/podcast/UBPodcastController.cpp b/src/podcast/UBPodcastController.cpp index 7dbb3644..1a680c78 100644 --- a/src/podcast/UBPodcastController.cpp +++ b/src/podcast/UBPodcastController.cpp @@ -761,7 +761,12 @@ void UBPodcastController::timerEvent(QTimerEvent *event) && event->timerId() == mScreenGrabingTimerEventID && mSourceWidget == qApp->desktop()) { - QPixmap desktop = QPixmap::grabWindow(qApp->desktop()->screen(UBApplication::applicationController->displayManager()->controleScreenIndex())->winId()); + QDesktopWidget * dtop = QApplication::desktop(); + QRect dtopRect = dtop->screenGeometry(); + QScreen * screen = QApplication::primaryScreen(); + + QPixmap desktop = screen->grabWindow(dtop->effectiveWinId(), + dtopRect.x(), dtopRect.y(), dtopRect.width(), dtopRect.height()); { QPainter p(&mLatestCapture); From 13a236d53b3ed50da59657a92c8f8a491aa9f535 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Wed, 23 Dec 2015 11:45:07 +0100 Subject: [PATCH 075/243] Fixed video not appearing on secondary screen --- src/domain/UBGraphicsMediaItem.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/domain/UBGraphicsMediaItem.cpp b/src/domain/UBGraphicsMediaItem.cpp index c3cf8ec6..22f99c51 100644 --- a/src/domain/UBGraphicsMediaItem.cpp +++ b/src/domain/UBGraphicsMediaItem.cpp @@ -72,6 +72,9 @@ UBGraphicsMediaItem::UBGraphicsMediaItem(const QUrl& pMediaFileUrl, QGraphicsIte mVideoItem = new QGraphicsVideoItem(); + // Necessary to allow the video to be displayed on secondary screen + mVideoItem->setData(UBGraphicsItemData::ItemLayerType, UBItemLayerType::Object); + mMediaObject->setVideoOutput(mVideoItem); mVideoItem->setSize(QSize(320,240)); From 1b525728abded27d3b977e50748354aa29c0da93 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Mon, 11 Jan 2016 09:38:41 +0100 Subject: [PATCH 076/243] Fixed media playback on linux --- src/core/main.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/main.cpp b/src/core/main.cpp index 090a206a..5aba64e2 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -91,6 +91,10 @@ int main(int argc, char *argv[]) #endif */ + // QT_NO_GLIB=1 is set by default on Linux, and prevents media playback + if (qEnvironmentVariableIsSet("QT_NO_GLIB")) + qunsetenv("QT_NO_GLIB"); + Q_INIT_RESOURCE(OpenBoard); qInstallMessageHandler(ub_message_output); From 8e864c6e114e88336cafd5b28dbe5523259d33ec Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Mon, 11 Jan 2016 14:52:49 +0100 Subject: [PATCH 077/243] updated version number (1.10a5) --- OpenBoard.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenBoard.pro b/OpenBoard.pro index 6e9553dc..b1401c70 100644 --- a/OpenBoard.pro +++ b/OpenBoard.pro @@ -11,7 +11,7 @@ CONFIG += debug_and_release \ VERSION_MAJ = 1 VERSION_MIN = 10 VERSION_TYPE = a # a = alpha, b = beta, rc = release candidate, r = release, other => error -VERSION_PATCH = 4 +VERSION_PATCH = 5 VERSION = "$${VERSION_MAJ}.$${VERSION_MIN}.$${VERSION_TYPE}.$${VERSION_PATCH}" VERSION = $$replace(VERSION, "\\.r", "") From 7e105fa59053ce126958b2fc642454a33d0b9292 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Mon, 11 Jan 2016 17:02:14 +0100 Subject: [PATCH 078/243] Post-install script on Linux: delete OpenBoardUser.config file (avoids a crash if the config file comes from a version <= 1.10a3) --- buildDebianPackage.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/buildDebianPackage.sh b/buildDebianPackage.sh index b35927c6..2ae25d43 100755 --- a/buildDebianPackage.sh +++ b/buildDebianPackage.sh @@ -300,7 +300,7 @@ exit 0 #DEBHELPER# EOF -cat > "$BASE_WORKING_DIR/DEBIAN/postint" << EOF +cat > "$BASE_WORKING_DIR/DEBIAN/postinst" << EOF #!/bin/bash # -------------------------------------------------------------------- # This program is free software: you can redistribute it and/or modify @@ -318,6 +318,7 @@ cat > "$BASE_WORKING_DIR/DEBIAN/postint" << EOF # --------------------------------------------------------------------- xdg-desktop-menu install --novendor /usr/share/applications/${APPLICATION_NAME}.desktop +rm -f "\$HOME/.local/share/OpenBoard/OpenBoardUser.config" exit 0 #DEBHELPER# EOF @@ -410,7 +411,7 @@ echo "Categories=Education" >> $APPLICATION_SHORTCUT cp "resources/images/${APPLICATION_NAME}.png" "$PACKAGE_DIRECTORY/${APPLICATION_NAME}.png" chmod 755 "$BASE_WORKING_DIR/DEBIAN" chmod 755 "$BASE_WORKING_DIR/DEBIAN/prerm" -chmod 755 "$BASE_WORKING_DIR/DEBIAN/postint" +chmod 755 "$BASE_WORKING_DIR/DEBIAN/postinst" mkdir -p "install/linux" DEBIAN_PACKAGE_NAME="${APPLICATION_NAME}_`lsb_release -is`_`lsb_release -rs`_${VERSION}_$ARCHITECTURE.deb" @@ -419,7 +420,7 @@ chown -R root:root $BASE_WORKING_DIR dpkg -b "$BASE_WORKING_DIR" "install/linux/$DEBIAN_PACKAGE_NAME" #clean up mess -rm -rf $BASE_WORKING_DIR +#rm -rf $BASE_WORKING_DIR notifyProgress "${APPLICATION_NAME}" "Package built" From 4cb7a15ceb7ce2aa1eb35152dbf06564324fee5f Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Tue, 12 Jan 2016 10:08:01 +0100 Subject: [PATCH 079/243] Fixed mediaservice plugins not being included in Windows installer --- OpenBoard.iss | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/OpenBoard.iss b/OpenBoard.iss index bc55ba00..31f670e6 100644 --- a/OpenBoard.iss +++ b/OpenBoard.iss @@ -109,15 +109,15 @@ Source: "{#QtDir}\plugins\imageformats\qtiff.dll"; DestDir: "{app}\imageformats" Source: "{#QtDir}\plugins\iconengines\qsvgicon.dll"; DestDir: "{app}\iconengines"; Flags: ignoreversion ;qt multimedia plugins -Source: "{#QtDir}\plugins\mediaservice\dsengine.dll"; DestDir: "\plugins\mediaservice"; Flags: ignoreversion -Source: "{#QtDir}\plugins\mediaservice\dsengined.dll"; DestDir: "\plugins\mediaservice"; Flags: ignoreversion -Source: "{#QtDir}\plugins\mediaservice\qtmedia_audioengine.dll"; DestDir: "\plugins\mediaservice"; Flags: ignoreversion -Source: "{#QtDir}\plugins\mediaservice\qtmedia_audioengined.dll"; DestDir: "\plugins\mediaservice"; Flags: ignoreversion -Source: "{#QtDir}\plugins\mediaservice\wmfengine.dll"; DestDir: "\plugins\mediaservice"; Flags: ignoreversion -Source: "{#QtDir}\plugins\mediaservice\wmfengined.dll"; DestDir: "\plugins\mediaservice"; Flags: ignoreversion +Source: "{#QtDir}\plugins\mediaservice\dsengine.dll"; DestDir: "{app}\mediaservice"; Flags: ignoreversion +Source: "{#QtDir}\plugins\mediaservice\dsengined.dll"; DestDir: "{app}\mediaservice"; Flags: ignoreversion +Source: "{#QtDir}\plugins\mediaservice\qtmedia_audioengine.dll"; DestDir: "{app}\mediaservice"; Flags: ignoreversion +Source: "{#QtDir}\plugins\mediaservice\qtmedia_audioengined.dll"; DestDir: "{app}\mediaservice"; Flags: ignoreversion +Source: "{#QtDir}\plugins\mediaservice\wmfengine.dll"; DestDir: "{app}\mediaservice"; Flags: ignoreversion +Source: "{#QtDir}\plugins\mediaservice\wmfengined.dll"; DestDir: "{app}\mediaservice"; Flags: ignoreversion ;OpenBoardImporter -Source: "..\OpenBoard-Importer\release\OpenBoardImporter.exe"; DestDir: "c:\OpenBoard\Importer"; Flags: ignoreversion +Source: "..\OpenBoard-Importer\release\OpenBoardImporter.exe"; DestDir: "{app}\Importer"; Flags: ignoreversion Source: "{#QtLibs}\Qt5Core.dll"; DestDir: "{app}" Source: "{#QtLibs}\Qt5Gui.dll"; DestDir: "{app}" From b2fc32913e3294e18f0167602110be89c1c409d9 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Tue, 12 Jan 2016 11:21:56 +0100 Subject: [PATCH 080/243] Tutorial link now points to openboard.ch --- src/core/UBSettings.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/UBSettings.cpp b/src/core/UBSettings.cpp index fe07f280..c1298933 100644 --- a/src/core/UBSettings.cpp +++ b/src/core/UBSettings.cpp @@ -206,11 +206,11 @@ void UBSettings::ValidateKeyboardPaletteKeyBtnSize() void UBSettings::init() { - productWebUrl = new UBSetting(this, "App", "ProductWebAddress", "http://www.openboard.org"); + productWebUrl = new UBSetting(this, "App", "ProductWebAddress", "http://www.openboard.ch"); softwareHomeUrl = productWebUrl->get().toString(); - tutorialUrl = new UBSetting(this,"App","TutorialUrl","http://www.youtube.com/channel/UCM_moFB68dqpSLPZ-jV40Ow"); + tutorialUrl = new UBSetting(this,"App","TutorialUrl","http://www.openboard.ch"); documentSizes.insert(DocumentSizeRatio::Ratio4_3, QSize(1280, 960)); // 1.33 documentSizes.insert(DocumentSizeRatio::Ratio16_9, QSize((960 / 9 * 16), 960)); // 1.77 From 93dc25385fa70295ad8f59309b0b65ad2f6aa6d2 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Tue, 12 Jan 2016 11:23:21 +0100 Subject: [PATCH 081/243] Updated About text in preferences menu --- resources/forms/preferences.ui | 35 +++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/resources/forms/preferences.ui b/resources/forms/preferences.ui index eda73013..1331814c 100644 --- a/resources/forms/preferences.ui +++ b/resources/forms/preferences.ui @@ -24,7 +24,7 @@ - 5 + 6 @@ -2650,7 +2650,7 @@ Public License instead of this License. But first, please read <!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:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'.Helvetica Neue DeskInterface'; font-size:13pt; font-weight:400; font-style:normal;"> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Cantarell'; font-size:12pt; font-weight:600;">Translations</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Cantarell'; font-size:10pt;"><br /></span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Cantarell'; font-size:10pt;">A special thanks to:</span></p> @@ -2697,12 +2697,12 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://creativecommons.org/licenses/by/3.0/"><span style=" font-family:'Cantarell'; font-size:10pt; text-decoration: underline; color:#0000ff;">Creative Commons BY-ND</span></a></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://douteau.ecolier.perso.sfr.fr/page_ecolier.htm"><span style=" font-family:'Cantarell'; font-size:10pt; text-decoration: underline; color:#000000;">DGESCO (</span></a><a href="mailto:degre.numerique@education.gouv.fr"><span style=" font-family:'Cantarell'; font-size:10pt; text-decoration: underline; color:#0000ff;">degre.numerique@education.gouv.fr</span></a><a href="http://douteau.ecolier.perso.sfr.fr/page_ecolier.htm"><span style=" font-family:'Cantarell'; font-size:10pt; text-decoration: underline; color:#000000;">)</span></a></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://douteau.ecolier.perso.sfr.fr/page_ecolier.htm"><span style=" font-family:'Cantarell'; font-size:10pt; text-decoration: underline; color:#000000;">Source: </span></a><a href="http://eduscol.education.fr/cid72979/polices-de-caracteres-cursives-pour-l-enseignement-de-l-ecriture.html"><span style=" font-family:'Cantarell'; font-size:10pt; text-decoration: underline; color:#0000ff;">http://eduscol.education.fr/cid72979/polices-de-caracteres-cursives-pour-l-enseignement-de-l-ecriture.html</span></a></p> -<p style="-qt-paragraph-type:empty; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Lucida Grande';"><br /></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Cantarell'; font-size:10pt;">GeTypo Libre</span></p> <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:'Cantarell'; font-size:10pt;">Creative Commons BY-NC-ND</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.ge.ch/sem/cc/by-nc-nd/"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">http://www.ge.ch/sem/cc/by-nc-nd/</span></a></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.ge.ch/sem/cc/by-nc-nd/"><span style=" font-family:'Lucida Grande'; font-size:10pt; text-decoration: underline; color:#0000ff;">http://www.ge.ch/sem/cc/by-nc-nd/</span></a></p> <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:'Cantarell'; font-size:10pt;">© 2005-2015, Vista Multimedia SA, Droit de diffusion Etat de Genève - DIP</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://edu.ge.ch/sem/node/1294"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">http://edu.ge.ch/sem/node/1294</span></a><span style=" font-family:'Cantarell'; font-size:10pt;"><br /></span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://edu.ge.ch/sem/node/1294"><span style=" font-family:'Lucida Grande'; font-size:10pt; text-decoration: underline; color:#0000ff;">http://edu.ge.ch/sem/node/1294</span></a><span style=" font-family:'Cantarell'; font-size:10pt;"><br /></span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Cantarell'; font-size:10pt; color:#000000;">Sonata para piano (.mp3)</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Cantarell'; font-size:10pt; color:#000000;">Óscar G. Villegas</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://creativecommons.org/licenses/by-nc-sa/3.0/es"><span style=" font-family:'Cantarell'; font-size:10pt; text-decoration: underline; color:#0000ff;">Creative Commons Attribution-NonCommercial-Share Alike 3.0 Unported</span></a></p> @@ -2744,27 +2744,28 @@ p, li { white-space: pre-wrap; } <!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:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'.Helvetica Neue DeskInterface'; font-size:13pt; font-weight:400; font-style:normal;"> <table border="0" style="-qt-table-type: root; margin-top:4px; margin-bottom:4px; margin-left:4px; margin-right:4px;"> <tr> <td style="border: none;"> -<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:'Cantarell'; font-size:10pt;">OpenBoard 1.00.00</span></p> +<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:'Cantarell'; font-size:10pt;">OpenBoard 1.10.0</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Cantarell'; font-size:10pt;"><br /></p> -<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:'Cantarell'; font-size:10pt;">OpenBoard is copyright © 2013 . All rights reserved.</span></p> +<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:'Cantarell'; font-size:10pt;">OpenBoard is copyright © 2015. All rights reserved.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Cantarell'; font-size:10pt;"><br /></p> -<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:'Cantarell'; font-size:10pt;">OpenBoard is derived from Open-Sankoré. Open-Sankoré is copyright © 2010-2013 Groupement d'Intérêt Public pour l'Education Numérique en Afrique (GIP ENA). All right reserved.</span></p> +<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:'Cantarell'; font-size:10pt;">OpenBoard is derived from Open-Sankoré. Open-Sankoré is copyright © 2010-2015 Groupement d'Intérêt Public pour l'Education Numérique en Afrique (GIP ENA). All right reserved.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Cantarell'; font-size:10pt;"><br /></p> -<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:'Cantarell'; font-size:10pt;">OpenBoard is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License, with a specific linking exception for the OpenSSL project's &quot;OpenSSL&quot; library (or with modified versions of it that use the same license as the &quot;OpenSSL&quot; library). You can find the source code of this software at &lt;https://github.com/OpenEducationFoundation&gt;</span></p> +<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:'Cantarell'; font-size:10pt;">OpenBoard is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License, with a specific linking exception for the OpenSSL project's &quot;OpenSSL&quot; library (or with modified versions of it that use the same license as the &quot;OpenSSL&quot; library). You can find the source code of this software at </span><a href="https://github.com/DIP-SEM/OpenBoard"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">github.com/DIP-SEM/OpenBoard</span></a><span style=" font-family:'Cantarell'; font-size:10pt;">, </span><a href="https://github.com/DIP-SEM/OpenBoard-ThirdParty"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">github.com/DIP-SEM/OpenBoard-ThirdParty</span></a><span style=" font-family:'Cantarell'; font-size:10pt;">, and </span><a href="https://github.com/DIP-SEM/OpenBoard-Importer"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">github.com/DIP-SEM/OpenBoard-Importer.</span></a><span style=" font-family:'Cantarell'; font-size:10pt;"> </span></p> <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:'Cantarell'; font-size:10pt;">OpenBoard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License below for more details.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Cantarell'; font-size:10pt;"><br /></p> <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:'Cantarell'; font-size:10pt;">Contact :</span></p> -<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:'Cantarell'; font-size:10pt;">Open Education Foundation</span></p> -<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:'Cantarell'; font-size:10pt;">c/o FBT Avocats SA</span></p> -<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:'Cantarell'; font-size:10pt;">Rue du 31-Décembre 47</span></p> -<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:'Cantarell'; font-size:10pt;">1207 Genève</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.oe-f.org"><span style=" font-family:'Cantarell'; font-size:10pt; text-decoration: underline; color:#0000ff;">oe-f.org</span></a></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Cantarell'; font-size:10pt;"><br /></p> -<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:'Cantarell'; font-size:10pt;">email: </span><a href="mailto:contact@oe-f.org"><span style=" font-family:'Cantarell'; font-size:10pt; text-decoration: underline; color:#0000ff;">contact@oe-f.org</span></a></p></td></tr></table></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:'Cantarell'; font-size:10pt;">Service écoles-médias</span></p> +<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:'Cantarell'; font-size:10pt;">Rue des Gazomètres 5</span></p> +<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:'Cantarell'; font-size:10pt;">Case Postale 241</span></p> +<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:'Cantarell'; font-size:10pt;">1211 Genève 8</span></p> +<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:'Cantarell'; font-size:10pt;">Switzerland</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.openboard.ch"><span style=" font-size:11pt; text-decoration: underline; color:#0000ff;">openboard.ch</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt; text-decoration: underline; color:#0000ff;"><br /></p> +<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:'Cantarell'; font-size:10pt;">email: </span><a href="mailto:sem.logistique@edu.ge.ch"><span style=" font-family:'Cantarell'; font-size:10pt; text-decoration: underline; color:#0000ff;">sem.logistique@edu.ge.ch</span></a></p></td></tr></table></body></html> true From 54214f93f00a1a6040b383eb71f1fd4f7d45c0f9 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Tue, 12 Jan 2016 12:07:27 +0100 Subject: [PATCH 082/243] Add videos at their native size (not 320x240) --- src/domain/UBGraphicsMediaItem.cpp | 3 +++ src/domain/UBGraphicsMediaItem.h | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/domain/UBGraphicsMediaItem.cpp b/src/domain/UBGraphicsMediaItem.cpp index 22f99c51..4bc036af 100644 --- a/src/domain/UBGraphicsMediaItem.cpp +++ b/src/domain/UBGraphicsMediaItem.cpp @@ -121,6 +121,9 @@ UBGraphicsMediaItem::UBGraphicsMediaItem(const QUrl& pMediaFileUrl, QGraphicsIte connect(Delegate(), SIGNAL(showOnDisplayChanged(bool)), this, SLOT(showOnDisplayChanged(bool))); connect(mMediaObject, SIGNAL(videoAvailableChanged(bool)), this, SLOT(hasMediaChanged(bool))); + + // Resize the widget as soon as the video's native size is known (it isn't at this stage) + connect(mVideoItem, SIGNAL(nativeSizeChanged(QSizeF)), this, SLOT(resize(QSizeF))); } diff --git a/src/domain/UBGraphicsMediaItem.h b/src/domain/UBGraphicsMediaItem.h index e83facef..d05c1871 100644 --- a/src/domain/UBGraphicsMediaItem.h +++ b/src/domain/UBGraphicsMediaItem.h @@ -112,8 +112,6 @@ public: virtual void setPos(qreal x, qreal y); virtual void setMatrix(const QMatrix &matrix, bool combine = false); virtual void setTransform(const QTransform &matrix, bool combine = false); - virtual void resize(qreal w, qreal h); - virtual void resize(const QSizeF & pSize); public slots: @@ -123,6 +121,8 @@ public slots: void activeSceneChanged(); void hasMediaChanged(bool hasMedia); void showOnDisplayChanged(bool shown); + virtual void resize(qreal w, qreal h); + virtual void resize(const QSizeF & pSize); protected: From 6f044afc49e324d30d84163eafe125f79bb07db8 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Tue, 12 Jan 2016 17:37:00 +0100 Subject: [PATCH 083/243] Added support for OSX on-screen keyboard --- src/board/UBBoardController.cpp | 9 +++++++++ src/frameworks/UBPlatformUtils.h | 1 + src/frameworks/UBPlatformUtils_mac.mm | 13 +++++++++++++ 3 files changed, 23 insertions(+) diff --git a/src/board/UBBoardController.cpp b/src/board/UBBoardController.cpp index 99af72b7..b11114cf 100644 --- a/src/board/UBBoardController.cpp +++ b/src/board/UBBoardController.cpp @@ -94,6 +94,10 @@ bool onboardIsAlreadyRunning = true; #endif +#ifdef Q_OS_OSX +#include +#endif + UBBoardController::UBBoardController(UBMainWindow* mainWindow) : UBDocumentContainer(mainWindow->centralWidget()) , mMainWindow(mainWindow) @@ -853,6 +857,11 @@ void UBBoardController::showKeyboard(bool show) } else mPaletteManager->showVirtualKeyboard(show); + +#elif defined(Q_OS_OSX) + if(UBSettings::settings()->useSystemOnScreenKeybard->get().toBool()) + UBPlatformUtils::showOSK(); + #else mPaletteManager->showVirtualKeyboard(show); #endif diff --git a/src/frameworks/UBPlatformUtils.h b/src/frameworks/UBPlatformUtils.h index 0b28c7dd..368ae84a 100644 --- a/src/frameworks/UBPlatformUtils.h +++ b/src/frameworks/UBPlatformUtils.h @@ -208,6 +208,7 @@ public: #ifdef Q_OS_OSX static void SetMacLocaleByIdentifier(const QString& id); + static void showOSK(); #endif }; diff --git a/src/frameworks/UBPlatformUtils_mac.mm b/src/frameworks/UBPlatformUtils_mac.mm index 1ec487aa..a9bbbe57 100644 --- a/src/frameworks/UBPlatformUtils_mac.mm +++ b/src/frameworks/UBPlatformUtils_mac.mm @@ -609,3 +609,16 @@ void UBPlatformUtils::showFullScreen(QWidget *pWidget) } + +void UBPlatformUtils::showOSK() +{ + [[NSAutoreleasePool alloc] init]; + + CFDictionaryRef properties = + (CFDictionaryRef)[NSDictionary + dictionaryWithObject: @"com.apple.KeyboardViewer" + forKey: (NSString *)kTISPropertyInputSourceID]; + NSArray *sources = (NSArray *)TISCreateInputSourceList(properties, false); + + TISSelectInputSource((TISInputSourceRef)[sources objectAtIndex: 0]); +} From 435c559b865a42b92047b3691db7cde3c9cae499 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Thu, 14 Jan 2016 10:00:03 +0100 Subject: [PATCH 084/243] Enable cross-origin requests for UBFeaturesWidgets --- src/gui/UBFeaturesWidget.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/UBFeaturesWidget.cpp b/src/gui/UBFeaturesWidget.cpp index 23c5f162..d702b656 100644 --- a/src/gui/UBFeaturesWidget.cpp +++ b/src/gui/UBFeaturesWidget.cpp @@ -780,6 +780,7 @@ UBFeaturesWebView::UBFeaturesWebView(QWidget* parent, const char* name):QWidget( mpWebSettings->setAttribute(QWebSettings::OfflineStorageDatabaseEnabled, true); mpWebSettings->setAttribute(QWebSettings::JavascriptCanAccessClipboard, true); mpWebSettings->setAttribute(QWebSettings::DnsPrefetchEnabled, true); + mpWebSettings->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls, true); mpLayout->addWidget(mpView); mpLayout->setMargin(0); From 5b7cf175e9ea854c8deb6a8edbad471ba993bc5e Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Thu, 14 Jan 2016 11:39:04 +0100 Subject: [PATCH 085/243] Clean-up of on-screen keyboard code - Moved all platform-specific code to UBPlatformUtils - For now, removed support (on Linux) for checking whether onboard is running when OpenBoard is started (it wasn't working anyway, but it needs a cleaner solution for all 3 platforms) --- src/board/UBBoardController.cpp | 44 ++---------------------- src/frameworks/UBPlatformUtils.h | 3 +- src/frameworks/UBPlatformUtils_linux.cpp | 7 ++++ src/frameworks/UBPlatformUtils_mac.mm | 20 ++++++----- src/frameworks/UBPlatformUtils_win.cpp | 6 ++++ 5 files changed, 29 insertions(+), 51 deletions(-) diff --git a/src/board/UBBoardController.cpp b/src/board/UBBoardController.cpp index b11114cf..0354e254 100644 --- a/src/board/UBBoardController.cpp +++ b/src/board/UBBoardController.cpp @@ -89,15 +89,6 @@ #include "core/memcheck.h" -#ifdef Q_OS_LINUX -#include -bool onboardIsAlreadyRunning = true; -#endif - -#ifdef Q_OS_OSX -#include -#endif - UBBoardController::UBBoardController(UBMainWindow* mainWindow) : UBDocumentContainer(mainWindow->centralWidget()) , mMainWindow(mainWindow) @@ -172,12 +163,6 @@ void UBBoardController::init() UBBoardController::~UBBoardController() { -#ifdef Q_OS_LINUX - if(!onboardIsAlreadyRunning){ - QProcess newProcess; - newProcess.startDetached("killall onboard"); - } -#endif delete mDisplayView; } @@ -836,36 +821,11 @@ void UBBoardController::showKeyboard(bool show) if(show) UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); -#ifdef Q_OS_LINUX - static bool isFirstTime = true; - if(isFirstTime){ - QProcess isAlreadyRunningProcess; - QString psAuxGrepC = "ps aux"; - isAlreadyRunningProcess.start(psAuxGrepC); - isAlreadyRunningProcess.waitForFinished(); - QString output(isAlreadyRunningProcess.readAll()); - if(output.count("onboard") != 0) - onboardIsAlreadyRunning = true; - else - onboardIsAlreadyRunning = false; - - isFirstTime = false; - } - if(UBSettings::settings()->useSystemOnScreenKeybard->get().toBool()){ - QProcess newProcess; - newProcess.startDetached("/usr/bin/onboard"); - } + if(UBSettings::settings()->useSystemOnScreenKeybard->get().toBool()) + UBPlatformUtils::showOSK(show); else mPaletteManager->showVirtualKeyboard(show); -#elif defined(Q_OS_OSX) - if(UBSettings::settings()->useSystemOnScreenKeybard->get().toBool()) - UBPlatformUtils::showOSK(); - -#else - mPaletteManager->showVirtualKeyboard(show); -#endif - } diff --git a/src/frameworks/UBPlatformUtils.h b/src/frameworks/UBPlatformUtils.h index 368ae84a..af5578de 100644 --- a/src/frameworks/UBPlatformUtils.h +++ b/src/frameworks/UBPlatformUtils.h @@ -30,6 +30,7 @@ #include #include +#include class QMainWindow; @@ -205,10 +206,10 @@ public: static QStringList availableTranslations(); static void setFrontProcess(); static void showFullScreen(QWidget * pWidget); + static void showOSK(bool show); #ifdef Q_OS_OSX static void SetMacLocaleByIdentifier(const QString& id); - static void showOSK(); #endif }; diff --git a/src/frameworks/UBPlatformUtils_linux.cpp b/src/frameworks/UBPlatformUtils_linux.cpp index d4b4f690..e74bc76f 100644 --- a/src/frameworks/UBPlatformUtils_linux.cpp +++ b/src/frameworks/UBPlatformUtils_linux.cpp @@ -440,3 +440,10 @@ void UBPlatformUtils::showFullScreen(QWidget *pWidget) pWidget->showFullScreen(); } +void UBPlatformUtils::showOSK(bool show) +{ + if (show) { + QProcess newProcess; + newProcess.startDetached("/usr/bin/env onboard"); + } +} diff --git a/src/frameworks/UBPlatformUtils_mac.mm b/src/frameworks/UBPlatformUtils_mac.mm index a9bbbe57..ef946428 100644 --- a/src/frameworks/UBPlatformUtils_mac.mm +++ b/src/frameworks/UBPlatformUtils_mac.mm @@ -610,15 +610,19 @@ void UBPlatformUtils::showFullScreen(QWidget *pWidget) } -void UBPlatformUtils::showOSK() +void UBPlatformUtils::showOSK(bool show) { - [[NSAutoreleasePool alloc] init]; + // TODO: enable hiding OSK - CFDictionaryRef properties = - (CFDictionaryRef)[NSDictionary - dictionaryWithObject: @"com.apple.KeyboardViewer" - forKey: (NSString *)kTISPropertyInputSourceID]; - NSArray *sources = (NSArray *)TISCreateInputSourceList(properties, false); + if (show) { + [[NSAutoreleasePool alloc] init]; - TISSelectInputSource((TISInputSourceRef)[sources objectAtIndex: 0]); + CFDictionaryRef properties = + (CFDictionaryRef)[NSDictionary + dictionaryWithObject: @"com.apple.KeyboardViewer" + forKey: (NSString *)kTISPropertyInputSourceID]; + NSArray *sources = (NSArray *)TISCreateInputSourceList(properties, false); + + TISSelectInputSource((TISInputSourceRef)[sources objectAtIndex: 0]); + } } diff --git a/src/frameworks/UBPlatformUtils_win.cpp b/src/frameworks/UBPlatformUtils_win.cpp index b4f25c67..07dfc348 100644 --- a/src/frameworks/UBPlatformUtils_win.cpp +++ b/src/frameworks/UBPlatformUtils_win.cpp @@ -436,3 +436,9 @@ void UBPlatformUtils::showFullScreen(QWidget *pWidget) { pWidget->showFullScreen(); } + +void UBPlatformUtils::showOSK(bool show) +{ + Q_UNUSED(show); + // No system OSK support yet +} From 138553bb306ba46cf6863a84999e8fd00e13c865 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Thu, 14 Jan 2016 11:55:00 +0100 Subject: [PATCH 086/243] Added system OSK support for Windows --- src/frameworks/UBPlatformUtils_win.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/frameworks/UBPlatformUtils_win.cpp b/src/frameworks/UBPlatformUtils_win.cpp index 07dfc348..eac3ae45 100644 --- a/src/frameworks/UBPlatformUtils_win.cpp +++ b/src/frameworks/UBPlatformUtils_win.cpp @@ -440,5 +440,10 @@ void UBPlatformUtils::showFullScreen(QWidget *pWidget) void UBPlatformUtils::showOSK(bool show) { Q_UNUSED(show); - // No system OSK support yet + + QString windir = qgetenv("WINDIR"); + QString osk_path = windir+"\\System32\\osk.exe"; + + QProcess newProcess; + newProcess.startDetached("explorer.exe", QStringList() << osk_path); } From 631b070e82dc02673dce7f27d05ef4848c7c006d Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Thu, 14 Jan 2016 13:03:57 +0100 Subject: [PATCH 087/243] Updated version number (1.10a6) --- OpenBoard.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenBoard.pro b/OpenBoard.pro index b1401c70..c21f1934 100644 --- a/OpenBoard.pro +++ b/OpenBoard.pro @@ -11,7 +11,7 @@ CONFIG += debug_and_release \ VERSION_MAJ = 1 VERSION_MIN = 10 VERSION_TYPE = a # a = alpha, b = beta, rc = release candidate, r = release, other => error -VERSION_PATCH = 5 +VERSION_PATCH = 6 VERSION = "$${VERSION_MAJ}.$${VERSION_MIN}.$${VERSION_TYPE}.$${VERSION_PATCH}" VERSION = $$replace(VERSION, "\\.r", "") From da5378a68c55e28b032ca15c59df019e25b63f84 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Thu, 14 Jan 2016 17:29:56 +0100 Subject: [PATCH 088/243] Code clean-up Mostly, removal of old code that had been commented out instead of removed --- src/board/UBBoardController.cpp | 7 ------- src/board/UBFeaturesController.cpp | 4 ---- src/core/UB.h | 2 -- src/core/UBApplication.cpp | 6 ++---- src/core/UBApplicationController.h | 5 ----- src/domain/UBGraphicsMediaItem.cpp | 8 ++++---- src/frameworks/UBPlatformUtils_mac.mm | 11 ----------- src/gui/UBFloatingPalette.cpp | 1 - src/gui/UBMagnifer.cpp | 1 - src/tools/UBGraphicsTriangle.cpp | 4 ---- src/tools/UBGraphicsTriangle.h | 1 - src/tools/UBToolsManager.cpp | 7 ------- 12 files changed, 6 insertions(+), 51 deletions(-) diff --git a/src/board/UBBoardController.cpp b/src/board/UBBoardController.cpp index 0354e254..b6cd4f65 100644 --- a/src/board/UBBoardController.cpp +++ b/src/board/UBBoardController.cpp @@ -27,10 +27,7 @@ #include "UBBoardController.h" -//#include #include - -//#include #include #include "frameworks/UBFileSystemUtils.h" @@ -992,8 +989,6 @@ void UBBoardController::downloadURL(const QUrl& url, QString contentSourceUrl, c if (isBackground) oldBackgroundObject = mActiveScene->backgroundObject(); - //if(sUrl.startsWith("uniboardTool://")) - //if(sUrl.startsWith("openboardTool://",Qt::CaseInsensitive)) if(sUrl.startsWith("openboardtool://")) { @@ -1094,7 +1089,6 @@ UBItem *UBBoardController::downloadFinished(bool pSuccess, QUrl sourceUrl, QUrl mActiveScene->deselectAllItems(); - //if (!sourceUrl.toString().startsWith("file://") && !sourceUrl.toString().startsWith("uniboardTool://")) if (!sourceUrl.toString().startsWith("file://") && !sourceUrl.toString().startsWith("openboardtool://")) showMessage(tr("Download finished")); @@ -1375,7 +1369,6 @@ UBItem *UBBoardController::downloadFinished(bool pSuccess, QUrl sourceUrl, QUrl selectedDocument()->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); } } - //else if (UBMimeType::UniboardTool == itemMimeType) else if (UBMimeType::OpenboardTool == itemMimeType) { qDebug() << "accepting mime type" << mimeType << "OpenBoard Tool"; diff --git a/src/board/UBFeaturesController.cpp b/src/board/UBFeaturesController.cpp index 51178d2c..fff8a2ee 100644 --- a/src/board/UBFeaturesController.cpp +++ b/src/board/UBFeaturesController.cpp @@ -347,7 +347,6 @@ UBFeaturesController::UBFeaturesController(QWidget *pParentWidget) : featuresModel = new UBFeaturesModel(featuresList, this); //featuresModel->setSupportedDragActions(Qt::CopyAction | Qt::MoveAction); - //featuresModel->setSupportedDragActions(Qt::CopyAction | Qt::MoveAction); featuresProxyModel = new UBFeaturesProxyModel(this); featuresProxyModel->setFilterFixedString(rootPath); @@ -607,7 +606,6 @@ void UBFeaturesController::addToFavorite( const QUrl &path ) void UBFeaturesController::removeFromFavorite( const QUrl &path, bool deleteManualy) { -// QString filePath = fileNameFromUrl( path ); if ( favoriteSet->find( path ) != favoriteSet->end() ) { favoriteSet->erase( favoriteSet->find( path ) ); @@ -622,7 +620,6 @@ void UBFeaturesController::removeFromFavorite( const QUrl &path, bool deleteManu QString UBFeaturesController::fileNameFromUrl( const QUrl &url ) { QString fileName = url.toString(); - //if ( fileName.contains( "uniboardTool://")) if ( fileName.contains( "OpenboardTool://")) return fileName; return url.toLocalFile(); @@ -633,7 +630,6 @@ UBFeatureElementType UBFeaturesController::fileTypeFromUrl(const QString &path) { QFileInfo fileInfo(path); - //if ( path.contains("uniboardTool://")) if ( path.contains("OpenboardTool://")) return FEATURE_INTERNAL; diff --git a/src/core/UB.h b/src/core/UB.h index f2dd6685..d4bc8db6 100644 --- a/src/core/UB.h +++ b/src/core/UB.h @@ -28,7 +28,6 @@ #ifndef UB_H_ #define UB_H_ -//#include #include @@ -46,7 +45,6 @@ struct UBMimeType Audio, Flash, PDF, - //UniboardTool, OpenboardTool, Group, UNKNOWN diff --git a/src/core/UBApplication.cpp b/src/core/UBApplication.cpp index b518e491..12a47311 100644 --- a/src/core/UBApplication.cpp +++ b/src/core/UBApplication.cpp @@ -183,20 +183,18 @@ UBApplication::~UBApplication() QString UBApplication::checkLanguageAvailabilityForSankore(QString &language) { QStringList availableTranslations = UBPlatformUtils::availableTranslations(); - //QStringList availableTranslations ;availableTranslations<< "OpenBoard_fr"; + if(availableTranslations.contains(language,Qt::CaseInsensitive)) return language; else{ if(language.length() > 2){ QString shortLanguageCode = language.left(2); - //if(availableTranslations.contains(shortLanguageCode,Qt::CaseInsensitive)) + foreach (const QString &str, availableTranslations) { if (str.contains(shortLanguageCode)) return shortLanguageCode; } - //if(availableTranslations.contains(shortLanguageCode)) - //return shortLanguageCode; } } return QString(""); diff --git a/src/core/UBApplicationController.h b/src/core/UBApplicationController.h index 9db9a130..4774e033 100644 --- a/src/core/UBApplicationController.h +++ b/src/core/UBApplicationController.h @@ -28,13 +28,10 @@ #ifndef UBAPPLICATIONCONTROLLER_H_ #define UBAPPLICATIONCONTROLLER_H_ -//#include #include #include -//#include -//#include #include @@ -55,7 +52,6 @@ class UBSoftwareUpdate; class QNetworkAccessManager; class QNetworkReply; class QHttpPart; -//class QHttp; class UBRightPalette; class UBOpenSankoreImporter; class QScriptValue; @@ -161,7 +157,6 @@ class UBApplicationController : public QObject private slots: void updateRequestFinished(int id, bool error); - //void updateHeaderReceived(QHttpResponseHeader header); void updateHeaderReceived(QNetworkRequest header ); protected: diff --git a/src/domain/UBGraphicsMediaItem.cpp b/src/domain/UBGraphicsMediaItem.cpp index 4bc036af..08bd25f0 100644 --- a/src/domain/UBGraphicsMediaItem.cpp +++ b/src/domain/UBGraphicsMediaItem.cpp @@ -114,16 +114,16 @@ UBGraphicsMediaItem::UBGraphicsMediaItem(const QUrl& pMediaFileUrl, QGraphicsIte Delegate()->createControls(); if (mediaType_Audio == mMediaType) Delegate()->frame()->setOperationMode(UBGraphicsDelegateFrame::ResizingHorizontally); - else + else { Delegate()->frame()->setOperationMode(UBGraphicsDelegateFrame::Resizing); + // Resize the widget as soon as the video's native size is known (it isn't at this stage) + connect(mVideoItem, SIGNAL(nativeSizeChanged(QSizeF)), this, SLOT(resize(QSizeF))); + } setData(UBGraphicsItemData::itemLayerType, QVariant(itemLayerType::ObjectItem)); //Necessary to set if we want z value to be assigned correctly connect(Delegate(), SIGNAL(showOnDisplayChanged(bool)), this, SLOT(showOnDisplayChanged(bool))); connect(mMediaObject, SIGNAL(videoAvailableChanged(bool)), this, SLOT(hasMediaChanged(bool))); - - // Resize the widget as soon as the video's native size is known (it isn't at this stage) - connect(mVideoItem, SIGNAL(nativeSizeChanged(QSizeF)), this, SLOT(resize(QSizeF))); } diff --git a/src/frameworks/UBPlatformUtils_mac.mm b/src/frameworks/UBPlatformUtils_mac.mm index ef946428..a0440537 100644 --- a/src/frameworks/UBPlatformUtils_mac.mm +++ b/src/frameworks/UBPlatformUtils_mac.mm @@ -57,15 +57,6 @@ void UBPlatformUtils::init() { initializeKeyboardLayouts(); - // qwidget_mac.mm qt_mac_set_fullscreen_mode uses kUIModeAllSuppressed which is unfortunate in our case - // - // http://developer.apple.com/mac/library/documentation/Carbon/Reference/Dock_Manager/Reference/reference.html#//apple_ref/c/func/SetSystemUIMode - // - - //originalSetSystemUIMode = APEPatchCreate((const void *)SetSystemUIMode, (const void *)emptySetSystemUIMode); - - //setDesktopMode(false); - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSString *currentPath = [[NSBundle mainBundle] pathForResource:@"Save PDF to OpenBoard" ofType:@"workflow"]; @@ -94,8 +85,6 @@ void UBPlatformUtils::init() void UBPlatformUtils::setDesktopMode(bool desktop) { - //qDebug() << "setDesktopMode called. desktop = " << desktop; - @try { // temporarily disabled due to bug: when switching to desktop mode (and calling this), // openboard switches right back to the board mode. clicking again on desktop mode works. diff --git a/src/gui/UBFloatingPalette.cpp b/src/gui/UBFloatingPalette.cpp index 0aa19233..2ed4eb31 100644 --- a/src/gui/UBFloatingPalette.cpp +++ b/src/gui/UBFloatingPalette.cpp @@ -60,7 +60,6 @@ UBFloatingPalette::UBFloatingPalette(Qt::Corner position, QWidget *parent) #endif #ifdef Q_OS_OSX setAttribute(Qt::WA_MacAlwaysShowToolWindow); - //setAttribute(Qt::WA_MacNonActivatingToolWindow); // no longer exists setAttribute(Qt::WA_MacNoShadow); #endif } diff --git a/src/gui/UBMagnifer.cpp b/src/gui/UBMagnifer.cpp index 0d492655..20d4a101 100644 --- a/src/gui/UBMagnifer.cpp +++ b/src/gui/UBMagnifer.cpp @@ -85,7 +85,6 @@ UBMagnifier::UBMagnifier(QWidget *parent, bool isInteractive) #endif #ifdef Q_OS_OSX setAttribute(Qt::WA_MacAlwaysShowToolWindow); - //setAttribute(Qt::WA_MacNonActivatingToolWindow); setAttribute(Qt::WA_MacNoShadow); #endif } diff --git a/src/tools/UBGraphicsTriangle.cpp b/src/tools/UBGraphicsTriangle.cpp index 8c2e80c8..86f2cd30 100644 --- a/src/tools/UBGraphicsTriangle.cpp +++ b/src/tools/UBGraphicsTriangle.cpp @@ -25,8 +25,6 @@ -//#include - #include #include @@ -143,7 +141,6 @@ void UBGraphicsTriangle::setOrientation(UBGraphicsTriangleOrientation orientatio { mOrientation = orientation; - //calculatePoints(boundingRect()); calculatePoints(bounds_rect); QPolygonF polygon; @@ -172,7 +169,6 @@ UBGraphicsScene* UBGraphicsTriangle::scene() const void UBGraphicsTriangle::calculatePoints(const QRectF& r) { - //qDebug() << "UBGraphicsTriangle calculatePoints()"<<"r ="< #include #include diff --git a/src/tools/UBToolsManager.cpp b/src/tools/UBToolsManager.cpp index d9c756f2..878b5f44 100644 --- a/src/tools/UBToolsManager.cpp +++ b/src/tools/UBToolsManager.cpp @@ -49,7 +49,6 @@ void UBToolsManager::destroy() UBToolsManager::UBToolsManager(QObject *parent) : QObject(parent) { - //mask.id = "uniboardTool://uniboard.mnemis.com/mask"; mask.id = "openboardtool://openboard/mask"; mask.icon = QPixmap(":/images/toolPalette/maskTool.png"); @@ -58,7 +57,6 @@ UBToolsManager::UBToolsManager(QObject *parent) mToolsIcon.insert(mask.id, ":/images/toolPalette/maskTool.png"); mDescriptors << mask; - //ruler.id = "uniboardTool://uniboard.mnemis.com/ruler"; ruler.id = "openboardtool://ruler"; ruler.icon = QPixmap(":/images/toolPalette/rulerTool.png"); @@ -67,7 +65,6 @@ UBToolsManager::UBToolsManager(QObject *parent) mToolsIcon.insert(ruler.id, ":/images/toolPalette/rulerTool.png"); mDescriptors << ruler; - //compass.id = "uniboardTool://uniboard.mnemis.com/compass"; compass.id = "openboardtool://compass"; compass.icon = QPixmap(":/images/toolPalette/compassTool.png"); @@ -76,7 +73,6 @@ UBToolsManager::UBToolsManager(QObject *parent) mToolsIcon.insert(compass.id, ":/images/toolPalette/compassTool.png"); mDescriptors << compass; - //protractor.id = "uniboardTool://uniboard.mnemis.com/protractor"; protractor.id = "openboardtool://protractor"; protractor.icon = QPixmap(":/images/toolPalette/protractorTool.png"); @@ -85,7 +81,6 @@ UBToolsManager::UBToolsManager(QObject *parent) mToolsIcon.insert(protractor.id,":/images/toolPalette/protractorTool.png"); mDescriptors << protractor; - //triangle.id = "uniboardTool://uniboard.mnemis.com/triangle"; triangle.id = "openboardtool://triangle"; triangle.icon = QPixmap(":/images/toolPalette/triangleTool.png"); @@ -94,7 +89,6 @@ UBToolsManager::UBToolsManager(QObject *parent) mToolsIcon.insert(triangle.id,":/images/toolPalette/triangleTool.png"); mDescriptors << triangle; - //magnifier.id = "uniboardTool://uniboard.mnemis.com/magnifier"; magnifier.id = "openboardtool://magnifier"; magnifier.icon = QPixmap(":/images/toolPalette/magnifierTool.png"); @@ -103,7 +97,6 @@ UBToolsManager::UBToolsManager(QObject *parent) mToolsIcon.insert(magnifier.id,":/images/toolPalette/magnifierTool.png"); mDescriptors << magnifier; - //cache.id = "uniboardTool://uniboard.mnemis.com/cache"; cache.id = "openboardtool://cache"; cache.icon = QPixmap(":/images/toolPalette/cacheTool.png"); From 972e078a812440c63d78276a0b9c0102efcb46ab Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Tue, 19 Jan 2016 16:27:41 +0100 Subject: [PATCH 089/243] Fixed SWF transparency issue on Linux --- .../etc/npapi-wrapper.application.x-shockwave-flash.swf.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/etc/npapi-wrapper.application.x-shockwave-flash.swf.htm b/resources/etc/npapi-wrapper.application.x-shockwave-flash.swf.htm index 7d99bf8c..f5902672 100644 --- a/resources/etc/npapi-wrapper.application.x-shockwave-flash.swf.htm +++ b/resources/etc/npapi-wrapper.application.x-shockwave-flash.swf.htm @@ -22,7 +22,7 @@ - + From 4f61ce89754c47c7e8a4002700281717b58d51f4 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Thu, 21 Jan 2016 09:38:20 +0100 Subject: [PATCH 090/243] Clean-up / commenting --- src/core/main.cpp | 10 ---------- src/domain/UBGraphicsMediaItem.cpp | 8 +++++++- src/podcast/UBPodcastController.cpp | 2 +- src/tools/UBGraphicsTriangle.cpp | 10 +++++----- 4 files changed, 13 insertions(+), 17 deletions(-) diff --git a/src/core/main.cpp b/src/core/main.cpp index 5aba64e2..ab2aa08e 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -99,15 +99,6 @@ int main(int argc, char *argv[]) qInstallMessageHandler(ub_message_output); - - /* - * setGraphicsSystem is obsolete in Qt5, made redundant by the QPA framework. - * TODO: check if this works ok, if not, explore how to use QPA framework -#if defined(Q_OS_LINUX) - qDebug() << "Setting GraphicsSystem to raster"; - QApplication::setGraphicsSystem("raster"); -#endif - */ UBApplication app("OpenBoard", argc, argv); QStringList args = app.arguments(); @@ -136,7 +127,6 @@ int main(int argc, char *argv[]) } } - //app.initialize(false); // should not be needed anymore QObject::connect(&app, SIGNAL(messageReceived(const QString&, QObject*)), &app, SLOT(handleOpenMessage(const QString&))); diff --git a/src/domain/UBGraphicsMediaItem.cpp b/src/domain/UBGraphicsMediaItem.cpp index 08bd25f0..f0f7f598 100644 --- a/src/domain/UBGraphicsMediaItem.cpp +++ b/src/domain/UBGraphicsMediaItem.cpp @@ -65,7 +65,13 @@ UBGraphicsMediaItem::UBGraphicsMediaItem(const QUrl& pMediaFileUrl, QGraphicsIte mMediaObject->setNotifyInterval(50); - mDummyVideoWidget = new QWidget(); // owned and destructed by the scene ... + /* A dummy widget is used to keep the old functionality (when a Phonon video widget + * was used) with the current implementation, such as maintaining a clickable area + * above the video to move it around, etc. + * The whole class could be cleaned up, and the inheritance of QGraphicsProxyWidget + * abandoned, to make for a cleaner solution; for now, this works ok. + */ + mDummyVideoWidget = new QWidget(); mDummyVideoWidget->resize(320,240); mDummyVideoWidget->setMinimumSize(320, 240); mDummyVideoWidget->setWindowOpacity(0.0); diff --git a/src/podcast/UBPodcastController.cpp b/src/podcast/UBPodcastController.cpp index 1a680c78..b588ca96 100644 --- a/src/podcast/UBPodcastController.cpp +++ b/src/podcast/UBPodcastController.cpp @@ -799,7 +799,7 @@ QStringList UBPodcastController::audioRecordingDevices() QStringList devices; #ifdef Q_OS_WIN - //devices = UBWaveRecorder::waveInDevices(); + devices = UBWaveRecorder::waveInDevices(); #elif defined(Q_OS_OSX) devices = UBAudioQueueRecorder::waveInDevices(); #endif diff --git a/src/tools/UBGraphicsTriangle.cpp b/src/tools/UBGraphicsTriangle.cpp index 86f2cd30..0613628c 100644 --- a/src/tools/UBGraphicsTriangle.cpp +++ b/src/tools/UBGraphicsTriangle.cpp @@ -297,8 +297,8 @@ void UBGraphicsTriangle::paint(QPainter *painter, const QStyleOptionGraphicsItem mCloseSvgItem->setPos(closeButtonRect().topLeft()); - qDebug() << "UBGraphicsTriangle Paint"<<"closeButtonRect().topLeft()=" - <0 0 759 - 692 + 718 @@ -24,42 +24,13 @@ - 6 + 0 Display - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Qt::Vertical - - - QSizePolicy::Expanding - - - - 20 - 40 - - - - @@ -112,19 +83,6 @@ - - - - Qt::Vertical - - - - 20 - 40 - - - - @@ -213,19 +171,6 @@ - - - - Qt::Vertical - - - - 20 - 40 - - - - @@ -328,8 +273,8 @@ - - + + 0 @@ -337,11 +282,11 @@ - Virtual Keyboard + Mode - + - + Qt::Horizontal @@ -357,19 +302,30 @@ - + - + - Keyboard button size: + Mode to start in: - + + + + Board + + + + + Desktop + + + - + Qt::Horizontal @@ -386,8 +342,76 @@ + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 40 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + - + 0 @@ -395,11 +419,18 @@ - Mode + Virtual Keyboard - + + + + + Use system keyboard (recommended) + + + - + Qt::Horizontal @@ -414,31 +445,13 @@ - - - - - - Mode to start in: - - - - - - - - Board - - - - - Desktop - - - + + + + - - + + Qt::Horizontal @@ -450,24 +463,31 @@ + + + + Keyboard button size: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + - - - - Qt::Vertical - - - - 20 - 40 - - - - diff --git a/src/board/UBBoardController.cpp b/src/board/UBBoardController.cpp index b6cd4f65..18f69bf2 100644 --- a/src/board/UBBoardController.cpp +++ b/src/board/UBBoardController.cpp @@ -818,7 +818,7 @@ void UBBoardController::showKeyboard(bool show) if(show) UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); - if(UBSettings::settings()->useSystemOnScreenKeybard->get().toBool()) + if(UBSettings::settings()->useSystemOnScreenKeyboard->get().toBool()) UBPlatformUtils::showOSK(show); else mPaletteManager->showVirtualKeyboard(show); diff --git a/src/core/UBPreferencesController.cpp b/src/core/UBPreferencesController.cpp index f8d2ab90..2ca34217 100644 --- a/src/core/UBPreferencesController.cpp +++ b/src/core/UBPreferencesController.cpp @@ -129,6 +129,7 @@ void UBPreferencesController::wire() mPreferencesUI->keyboardPaletteKeyButtonSize->addItem(settings->supportedKeyboardSizes->at(i)); + connect(mPreferencesUI->useSystemOSKCheckBox, SIGNAL(clicked(bool)), settings->useSystemOnScreenKeyboard, SLOT(setBool(bool))); connect(mPreferencesUI->keyboardPaletteKeyButtonSize, SIGNAL(currentIndexChanged(const QString &)), settings->boardKeyboardPaletteKeyBtnSize, SLOT(setString(const QString &))); connect(mPreferencesUI->startModeComboBox, SIGNAL(currentIndexChanged(int)), settings->appStartMode, SLOT(setInt(int))); @@ -199,6 +200,8 @@ void UBPreferencesController::init() break; } + mPreferencesUI->useSystemOSKCheckBox->setChecked(settings->useSystemOnScreenKeyboard->get().toBool()); + mPreferencesUI->startModeComboBox->setCurrentIndex(settings->appStartMode->get().toInt()); mPreferencesUI->useExternalBrowserCheckBox->setChecked(settings->webUseExternalBrowser->get().toBool()); @@ -259,6 +262,8 @@ void UBPreferencesController::defaultSettings() mPreferencesUI->verticalChoice->setChecked(settings->appToolBarOrientationVertical->reset().toBool()); mPreferencesUI->horizontalChoice->setChecked(!settings->appToolBarOrientationVertical->reset().toBool()); mPreferencesUI->startModeComboBox->setCurrentIndex(0); + + mPreferencesUI->useSystemOSKCheckBox->setChecked(settings->useSystemOnScreenKeyboard->reset().toBool()); } else if (mPreferencesUI->mainTabWidget->currentWidget() == mPreferencesUI->penTab) { diff --git a/src/core/UBSettings.cpp b/src/core/UBSettings.cpp index c1298933..3e439dcd 100644 --- a/src/core/UBSettings.cpp +++ b/src/core/UBSettings.cpp @@ -415,7 +415,7 @@ void UBSettings::init() libIconSize = new UBSetting(this, "Library", "LibIconSize", defaultLibraryIconSize); - useSystemOnScreenKeybard = new UBSetting(this, "App", "UseSystemOnScreenKeybard", false); + useSystemOnScreenKeyboard = new UBSetting(this, "App", "UseSystemOnScreenKeyboard", true); cleanNonPersistentSettings(); } diff --git a/src/core/UBSettings.h b/src/core/UBSettings.h index 89fa3927..adf3d996 100644 --- a/src/core/UBSettings.h +++ b/src/core/UBSettings.h @@ -374,7 +374,7 @@ class UBSettings : public QObject UBSetting* libIconSize; - UBSetting* useSystemOnScreenKeybard; + UBSetting* useSystemOnScreenKeyboard; UBSetting* magnifierDrawingMode; UBSetting* autoSaveInterval; From 16bacf1bc9bdf3fa934434caaed34bd7b6f11004 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Thu, 21 Jan 2016 10:49:49 +0100 Subject: [PATCH 092/243] Added Data AbulEdu web search --- .../search/Data AbulEdu.wgs/config.xml | 16 + .../search/Data AbulEdu.wgs/css/basic.css | 314 ++++++++++++++++++ .../library/search/Data AbulEdu.wgs/icon.png | Bin 0 -> 9620 bytes .../Data AbulEdu.wgs/icon.thumbnail.png | Bin 0 -> 9620 bytes .../search/Data AbulEdu.wgs/images/down.png | Bin 0 -> 1192 bytes .../Data AbulEdu.wgs/images/greySquare.png | Bin 0 -> 214 bytes .../Data AbulEdu.wgs/images/icon-close.png | Bin 0 -> 1507 bytes .../Data AbulEdu.wgs/images/popupBack.png | Bin 0 -> 931 bytes .../search/Data AbulEdu.wgs/images/search.png | Bin 0 -> 1797 bytes .../Data AbulEdu.wgs/images/search_app.png | Bin 0 -> 1104 bytes .../Data AbulEdu.wgs/images/trgDown.png | Bin 0 -> 475 bytes .../search/Data AbulEdu.wgs/images/trgUp.png | Bin 0 -> 448 bytes .../search/Data AbulEdu.wgs/images/up.png | Bin 0 -> 1196 bytes .../search/Data AbulEdu.wgs/index.html | 268 +++++++++++++++ .../scripts/jquery-1.6.2.min.js | 18 + 15 files changed, 616 insertions(+) create mode 100644 resources/library/search/Data AbulEdu.wgs/config.xml create mode 100644 resources/library/search/Data AbulEdu.wgs/css/basic.css create mode 100644 resources/library/search/Data AbulEdu.wgs/icon.png create mode 100644 resources/library/search/Data AbulEdu.wgs/icon.thumbnail.png create mode 100644 resources/library/search/Data AbulEdu.wgs/images/down.png create mode 100644 resources/library/search/Data AbulEdu.wgs/images/greySquare.png create mode 100644 resources/library/search/Data AbulEdu.wgs/images/icon-close.png create mode 100644 resources/library/search/Data AbulEdu.wgs/images/popupBack.png create mode 100644 resources/library/search/Data AbulEdu.wgs/images/search.png create mode 100644 resources/library/search/Data AbulEdu.wgs/images/search_app.png create mode 100644 resources/library/search/Data AbulEdu.wgs/images/trgDown.png create mode 100644 resources/library/search/Data AbulEdu.wgs/images/trgUp.png create mode 100644 resources/library/search/Data AbulEdu.wgs/images/up.png create mode 100644 resources/library/search/Data AbulEdu.wgs/index.html create mode 100644 resources/library/search/Data AbulEdu.wgs/scripts/jquery-1.6.2.min.js diff --git a/resources/library/search/Data AbulEdu.wgs/config.xml b/resources/library/search/Data AbulEdu.wgs/config.xml new file mode 100644 index 00000000..9b51976e --- /dev/null +++ b/resources/library/search/Data AbulEdu.wgs/config.xml @@ -0,0 +1,16 @@ + + + + Choisir + RyXéo SARL + Choisir widget + + + diff --git a/resources/library/search/Data AbulEdu.wgs/css/basic.css b/resources/library/search/Data AbulEdu.wgs/css/basic.css new file mode 100644 index 00000000..8807a3e3 --- /dev/null +++ b/resources/library/search/Data AbulEdu.wgs/css/basic.css @@ -0,0 +1,314 @@ +html, body{ + width: 100%; + padding: 0; + height: auto; + background-color: white; + margin: 0; +} + +::-webkit-scrollbar { + width: 14px; + background-color:white; +} + + +::-webkit-scrollbar-thumb { + border-radius: 10px; + background-color:lightgray; + border: 2px solid gray; +} + +::-webkit-scrollbar-button:vertical:start{ + border-radius: 10px; + background-color:lightgray; + background-image: url(../images/trgUp.png); + background-size: 8px auto; + background-position: center; + background-repeat: no-repeat; + border: 2px solid gray; +} + +::-webkit-scrollbar-button:vertical:end{ + border-radius: 10px; + background-color:lightgray; + background-image: url(../images/trgDown.png); + background-size: 8px auto; + background-position: center; + background-repeat: no-repeat; + border: 2px solid gray; +} + +a { + text-decoration: underline; +} + +#disc_nav_cont{ + height: auto; + position: fixed; + left: 0; + bottom: 0; + width: 100%; +} + +.disclaimer{ + padding: 5px; + text-align: center; + background-color: #BBBBBB; + border-top: solid 4px #EEEEEE; + border-bottom: none; + font-size: 12px; +} + +.resultFooter{ + width: 100%; + padding: 3px; + font-family: Verdana,Arial,Helvetica,sans-serif; + font-weight: bold; + font-size: x-large; + text-align: center; + background-color: white; +} + +#searchResult { + overflow: hidden; + text-align: center; + margin-top: 50px; + margin-bottom: 85px; +} + +.search{ + position: fixed; + top: 0; + left: 0; + padding: 5px; + background-color: #BBBBBB; + border-bottom: solid 4px #EEEEEE; +} + +.search, +.disclaimer { + width: 100%; + box-sizing: border-box; + -webkit-box-sizing: border-box; +} + +.searchInput{ + padding: 3px; + float: left; + width: 100%; + border-radius: 3px; + border-style: none; + height: 22px; + line-height: 18px; + vertical-align: middle; + box-sizing: border-box; + -webkit-box-sizing: border-box; +} + +.searchButton{ + background: url("../images/search_app.png") -38px -38px no-repeat; + width: 24px; + height: 24px; + overflow: hidden; + position: absolute; + right: 30px; + top: 9px; + margin-left: -2px; + cursor: pointer; +} + +.subSearch{ + margin: 0; + float: left; +} + +#subSearchInput{ + width: 100%; + float: left; + box-sizing: border-box; + -webkit-box-sizing: border-box; + padding: 5px; + padding-right: 26px; +} + +#subSearchFilter{ + width: 100%; + float: left; + display: none; +} + +.searchResult{ + width: 98%; + padding: 3px; + background-color:#123456; +} + +.imgContainer{ + display: inline-block; + padding: 3px; + margin: 3px; + text-align: center; + overflow: hidden; + font-size: small; + font-family: Verdana,Arial,Helvetica,sans-serif; + vertical-align: top; +} + +.imgContainer img{ + max-width: 150px; + max-height:150px; +} + +.filterContainer{ + float: left; + margin: 2px; + padding: 2px; + font-size: 14px; + +} + +.filterSelect{ + border-style:none; + -webkit-border-top-right-radius: 15px; + -webkit-border-bottom-right-radius: 15px; + -moz-border-radius-topright: 15px; + -moz-border-radius-bottomright: 15px; + border-top-right-radius: 15px; + margin-top: 2px; + width: 100%; +} + +span{ + font-family: Verdana,Arial,Helvetica,sans-serif; + color: #666; +} + +[draggable] { + -webkit-user-select: none; + user-select: none; +} + +.toggleFilters{ + margin: 0; + padding: 0; + background-position: center; + background-image: url(../images/down.png); + position: absolute; + top: 11px; + right: 6px; + width: 20px; + height: 20px; + cursor: pointer; +} + +.colors_line { + float: left; + margin: 4px; + margin-right: 0; + clear: left; +} + +.custom { + opacity: 0; + position: absolute; + left: -10000px; +} + +.filter_button.button.color { + display: inline-block; + width: 15px; + height: 15px; + border: 1px solid #EBEBEB; + padding: 0; + margin: 0; + box-sizing: border-box; + -webkit-box-sizing: border-box; +} + +.filter_button.button.color:hover { + border: 1px solid rgb(128,128,128); + cursor: pointer; +} + +input[type="radio"]:checked + .filter_button.button.color { + border: 1px solid rgb(255,255,255); + box-shadow: 0 0 0px 1px #000; + -webkit-box-shadow: 0 0 0px 1px #000; +} + +#allcolor { + background: white url('../images/search_app.png') -43px -144px no-repeat; +} + +#colored { + background: white url('../images/search_app.png') -43px -244px no-repeat; +} + +#grayed { + background: white url('../images/search_app.png') -45px -343px no-repeat; +} + +#black{ + background-color:#ffffff; +} +#blue{ + background-color:#0000FF; +} +#brown{ + background-color:rgba(139, 82, 16, 1); +} + +#gray{ + background-color:#999999; +} + +#green{ + background-color:#00CC00; +} + +#orange{ + background-color:#FB940B; +} + +#pink{ + background-color:#FF98BF; +} + +#purple{ + background-color:#762CA7; +} + +#red{ + background-color:#CC0000; +} + +#teal{ + background-color:#03C0C6; +} + +#white{ + background-color:#000000; +} + +#yellow{ + background-color:#FFFF00; +} + +.selectBox-dropdown, .selectBox-options li a { + line-height: 1.3 !important; + font-size: 13px; +} + +.pager_button { + padding: 3px 5px; + font-size: 16px; + color: black; + display: inline-block; +} + +.pager_button.active { + border-radius: 3px; + -webkit-border-radius: 3px; + background-color: gray; + color: white; +} diff --git a/resources/library/search/Data AbulEdu.wgs/icon.png b/resources/library/search/Data AbulEdu.wgs/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3e3eb085a8a9e844c6fef499eb5c808566726045 GIT binary patch literal 9620 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 KMNUMnLSTXgi@G%c literal 0 HcmV?d00001 diff --git a/resources/library/search/Data AbulEdu.wgs/icon.thumbnail.png b/resources/library/search/Data AbulEdu.wgs/icon.thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..3e3eb085a8a9e844c6fef499eb5c808566726045 GIT binary patch literal 9620 zcmV;FC2QJ=P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01m_e01m_fl`9S#00007bV*G`2i*(< z7911LQzZWY03ZNKL_t(|+U=cpv|U$y=Rfow`ATg_d@HnwrW-~Y2Fr>~R8OVf8n3m8&C&3gOFg7p-OO`CzR&P(z)9dZ_dr#YY{y68h z*YuubgJZGRdP`ULo_o%@zwdAV%J=u%`v|3!;^*UMHng9Mz#p<`;Z5gJQvOu0Yh1}f zSGJ2coyQxS!`X8hS*VcswR<2P`#Av5pQ=mbR37KZ1>B)YoRbqchlhQ0kci=)pTRCd$8pb0Ad41_4p8Px*ay#HUcL5` zulb|XGyLNd7kI_?E?$4_8iWv6E&xIZoa3X|2hZUi8^IgT;*HIr;Ko249%2Qe8w;AALaMIeslo{ zS4JkR2_kpzT=9=pK;;KV@n#AOKKstGDL(ME!%XDu)dt0U;zwus>&J#@WPh$0Dk6Nt zdellCLC8RBkK>)2TJX{KHE~|Ky_1M}38GW*xxE)SHC?*$GGSw&9iz7mcVrI5LR%~h z9X%OEbS4O0JBYcd2Xkxhg5&zrQU2%`wvx9zzIt$URrk=73iFnm`sj*>t~>xlYmD$M zTkyWTr%C*JM-rpI4P&qqb4w3ee=Ejd*RtnYlMM6WS8XL%aroY`>4wmA$*XhyK#JeG zb3L!Sx(7qAPepMh(b3MKVX}YtC6wo3Zt2C`*^hZuAI4w@A{j-*!mB#p$;kr0@r6VD zWN3B?5PU)3x4nx$xNi&B^(Pk|aU}tuN;Z}6Jqto$?ixVvX+?xD&j=hD&-3R0`xK|9 z3X1~pu9vRkckkIqe>$@G+_>TjGPaA-HH7}$#UJ~Jv)uKu9|s|(0tC^J#vk6dg?HY( zmPBM}kj2j{VizC9Y?-;qJVS>@+4Idqq`MM4@SZzq@Adg2rQrJ~r+Mus_o5_pCBl5< z{;PPybv>9D0s6A$-$>r!|DBm-u3)3Y3MurulK6Mt_*w`YSF*h$%57UZ2#54by04#1 z9ALaO%_|3PBW6Tb{5{W;I2D(2!Q$-UQI0)%j**j-Opj$LX3I#ake(vd*23IGj<%j8 zLI{L_J2tlQ(bsL~Foa;PP~o)l_|R9LMF@dZvf+Ewj}KBR;X5-%%qMuf@>Qhr5J8fEaQXVEkr4j-*T{FPYp;4R_(a?g?(^J?LrwM>dN)RtOu^}j6T#VKVwAXVb zu9S#Cc&c#*sNi*Q>~z*)Dx)}dVXg*D)no}2T3~lY?YjaiIz*=DE67M5L8!^+xXR^k zpZyF+W>4~4*SwuOdTt`5n@xAR`T7AKfADFti-wa6f7kfg8LWy!EE)OP0B}+JUKMa4 z?0DE99yRbh>DOwj4jI*~(Gn2#8Bu*t1nMuPBvY_(9k=GwrJ1GB^B^)hfso-Ph4$#k z6C9a4$#3rZCEm960XibB_3U1n=4THm>X3?vr(~5UI`=eZtUdDGb6Z;w<0q%J)UK~>_yWqy@y4+bRVDvmO=zlYvwyAs=z{=cq=?KJ*Ltl&M%^>AF5itUoO9B$k=KryTYVDnMQqIum>Tg9iR_;`fKY6x3U4PmDxSoS&+eo{D=Twl6g>-C` zTm5sub5O2>tQ2sp0uq5ICDH>=`d~EvE2YBo6jDh%De*jsCl#J2k-=-J6eY`{Ga02V z9Y&NTq9_nW&HpQCh^&UN#FEj&9lg8x$V+~kRJhrGw{|Dcbiqoyvi5!NDAH5UtqH1l zkh5K+RD^UvNYgNMfhOt+Ye*MNjgR5ZoWXTHP`;2n&%=`vC1uSNDWwP*IvuHPR9uOa zO-855+*BhPwTS&!il)%BC2Z3bxs{3WN3mlgD9uGE6Ho|Opq7Xx`{LdFr<>kKZ%g-r z&(fUstdxpz%(?JlxRXA zJxMHV67A^Z{=09$bv-|YcU&yXrefJtDmJ$3n;F;j*wEj}+P)sjC2K+Wsc4?Xsv7wO zzpQ#p-LLpBJ?Syn-@%DJcVWa2Q)xYk7nw%5ksvf$M0iGo-@Eo*yrk=zMTHS>jS){r znVZbj-fLTvqJMK2o&9Or*Cc6OlccjRP1o8sgf1|Q=O_MZ=C<}gfWF3iQX-|#sYvOY45bv&h=~`3kd0AJRmrQ`UVpn0q#$K$Ou~SC zMRDVXHoh88(Ux70Ug@CHb_geV9y}9d;LQUK)ilA|uX=!A-S&nhg%M9j8Qk7OIA(I~ z%eJy+u#I$Af^=7cmPF*TwS8Ft1Yn3j@kZ7bD>5(X3oL}@K~Fu0nQ%yh_Nc*Fu@V4K7lvvu0W}_| z(LpxM0@c9pC?RUnlxneTw;8NjG!*0(in>!)s(Cg#t|SpL>FVji9-T$gH2+xL#+>U$ zKi-QM&tlFE;%&L~tkpU?MDekGJ{A4>hsk~ZVM1Hi5xZ+Q(HpkWa@TImjRVh37}^=u zFf_28DgdG;B+)3OTB2IjVo~RAg4d1asY#=2Go>B{)lE`0`jO3_(F`!sLrF#1Q(U{b zm%V3?l8Dp|nx_}hDqU!$Hf&wuO7oHgB=bdbpZgZd^_qN?b^ILG@pEK=mV0j|eBD;! z_q>GAw)N;8X|!nM(g0`+3({eoqOF3cr6E*ow9$cN>NS-HlcTCpQ&o%QLXM|q=bM~M z0E%ds4b3yb_uB&H1x%|_ba$kYx`~orFyjPx9#Xkj%HtQeK8>SoAQFnM8UXv)Su+3d z;Iak2!grsb@ZBfKf9+8s+t!o*)dz^b>UPky)dQdj!McROg{+NKRZSFi6C)Y~DQPwx zu)vfwY5Y8(f*`2j|7xD&1*Nr1pp|CQqYxd!APW0`3cZWlmbn-WQt*4cijR0 z__bf)RBjm0?E<#0oaVA@vS0enijQ|ro=45)NWK036$u}}m@e3K#G4ye2U-jgrp9c= z!w=nM-Gqob*;SqJQuz!rsD{r~Ef=Z*Csl(dBR#h)IzCeZ?Xs zda@lgI}9NMAtaenh^q$9^Zu8AgZ1eN22u|q3ge)?8xn6_833Ln`>AiNoF6lEVz*yM z?3Qa*?gP@%g;9YapsPh^s_Zs7^=r1d!J??f79=2R3+*4jD9c-T@CUdP zvnwu8iIylW_q`Oor(@-0oURE5~X$I+B*RB3Q$Ao~dzxf!gdmXW_=@`Hb~@{Vdv5Z=Cl=pEOujtvz;5H+=?mT3XB zhBab_&t7^;1|Z-IRe}sOPd~PzdDefR3zgu5*=++DzJUc2zP8gionH_VlmqS)*cwU9dduas9*~J@)*vA30BH= zYKBhahHZqeTEBWaS_rXV;ee@W?Cgrx1TO>aRVom?s%v*u!=F`Hp2RRTcC7Ekj1+mrwx?O&IgMrOivv(|Bqf-BH%$LJxaVup z8^G)*zUX(+t;GBY(9#KFw_SJXd4N8zs-p>5mkJRv1%--4h)30$R9wl!pRN~>k!$lNEv zIgIG~0_c6na)s!P+fjuQl|!eHmIKc6-4daV10-H|*JY4#i!3OP>4J@|VGfKIYaI)X zA!n1|=O;?FB+grq`BtMS*~CKx{#!1js2jsm&-ML_l#QXTFX4f1*x8mt$H9^&mMigA zv?@b@u?g^bAT1i9>(AbYb8eK}*B-@s>L}&?M{y@+@Mg0M!88q$Z+HbF9J+J>7DZJT z3?@Sy8ZS|CGo0P5JSIRGvLa^($j?;($zv}sGOEEMUNQH?Q8o7#tE=1krs0Q2JKrJstP1h2+1~au# z=*`Jm)layt#BscOt$7hMr5S>(+`#{N;+0f(eV3PP8LmZO3tgN6@i(I4??8yvmlcI+ zVhpSyF|g+O?~3S&oAf6`C`FKr1+jcJ6!cWB(?M2~HB}EyRggP)UXWxdg&TyKDk#v% z#(W^?h;V~zIiAF}-JpBI|9&+Y^nyIZ@%((FyDh=A9OR=9-O2xc^kzzyjxZKUTO(T_ z^*aa==4UxpWVqrXje%5{lhb8Nwp(ixREs#}W)q~E`lM7-8Lb+cHq?FR`HgD$YFm!q zebI1br52KVng`Kn2s4?ac){SC2exr$W{@xb_7~~z%+&3fXoa?qfw_^N^;ppi5I}z_ zOfsVR2~~sUd#bM8GME*9_Udc6+tAlj%baChgWcLpp+H2qlF^K za*>d3p$w0|c=A8L0#kWCHp1T7pP9FJ4Z&Y+}+jz`q6NVorTHP?E< zj1>c*30U76B@xO|wA_YRoCWkkW45cr{7hLj7wSc0lq7IH58HBaU9T?WdF4#mSe&WN z9{+{yxL|~cC6km#1t_=Hk5nj^35TQqIspLaPJ~$78f7eJ)msc3DTNyU(_E@-=J^}j z5gV#%fakeXDlXFV7Ssq7Y92>4uhy)5GbcQS7KvcS6MmxTd5BtdNAN-$s{$aR3pTe$ zcxF^1U-A1#nXloBW&ta;2p81UY~t4r91q)Z>wE7snU*Ea*HCqslkUMNP6nwM;E&%9^L8)dKq>KEpQ|evI#VG6+irG;~BX3tiMRV70JG ztO_QcgPv?fMPiVjsZX;P0|4D|lfG1#Gc(0n4Pjx~u(6#m5N34^fdYxoXgYQfVg^f) z>KXN7{YVYeLv03$X1XJIoh@3VQz_yd9b~6QFq9Y6tX~8G0IY9|u;-kH9kixP<`vb2 zT2L=g_>q(2NL3LmpwfIOu+4AUWS429x$Y=(5&I{4} zUpfHS_a}Mi=oFcv9k7ZGCP&r(F+rjg{E-^$*YeXIG7 z+P}6`kS|n7baXHkiJ&U(i^l}{Ie}nDcMDIS%V6lj-<`H$?XQx)*_Be_Dt!LFku8;V zTizVyhL-ObK21 z4PA9Ezo93nu>rRs36s?pMA-;JLy{HLo0}3eC7Y5w0X1fJevaX|F1l`_$CEHI4Tu+{ z6}n^q+G7UqxMhHUJ}|~`w#;P4Lf`|TY0U|eTC7|-FR`i@z7{UVkc-h44W?**$F>R< z2+n3pB-X6KI(w#0YQ0zh0JvjQ8@Fy~<=A+Ey=Uhbo-K2By2ND8!uC9$Sc6)}L)D=+ z&WgomNK+y=uOD?mRy?mfS_NE6pGDQ%*7ywt(&dG?G0$bM6E-x#&fWw&gZ+_b3N~kF zN({}EIXadjQ*s&2l$p+1I8tFbKF{CCwW`LJbgBjSMXG64?nu>(Kut}&RUZ@(cBQgK zs=I^nSQ5{1UR*w4Nz)V$(H;+R!@4xkgDc_mWPxL2d1gvBN5}FEO_j)3TykXxx1qo; zgT^kuf>mEJSu6ZEltdeMG?2j_5_P8?tRr(=)|(P{%{ruGEmjtL@c{rZS918LCr3Cv zUE)nQ^s;*}&DJ$>0CHuA;kgRqIg3*h1t#+q#xfPgvKB?lB~!AoUBANR1p6_Iz=1ZK zu0|gaEE%a4_p6gjP$-mXUALZ!eFXuqXDGv;K6HwaoW)$pVX!?$XTtB9Nk&a}L``<| zCb;LS4hojbOu=TRXp^5S#Ciw&t1Gew)}l3SY%6?f_8oOswE9yVCl?mxHXCF|1^Esuiba%!T$ zg-n^@*)pdm3(OWBGDVxRBgvK>@)Z{?5VUECMV+kWNN*aN zV_=#WUnbNNHfRYObP;B-J%%F{W!ocHamkb%MrKQ7DlR9-^E@-0C0lkF%~(w2DwvwU z&;`1t1tBqn4V{ytSq8dONLO7MCaCEGx{g)M<0i}%0nj)!O%T=uVM8MwGZ|=&u)Qaa zREo0G&2-+PV0oMz&$D-EmZ6ynqjP1lC7Yt{QFJ_ziq2G&Si~gNVqAFu0HhN!!r{xW z1qvZ*+x~_Oon){d=Z@YauiVwmY_`DDBL)8Z4@YQ==|nV`ExW8=ljN<}^$-eOfdELQ zFimsCMQ|ylzfW9{3}~9RNWp{>Phlal_gaFVt~S z0Blz>S8~Xd9LkP|?I}!65HU595rg)4h={p#XPN7H2qUy204lai(Qsr~_msqf{uztShPx|L( z$~<*G!+{GqPEHn?$lK&A4i!fdHg)1*jqXI4&0TS>A4qa-f0Febv1OHS0RWkz&3BGX z^OXam>_4C9LbihC%4MhsjozfmuD&F%+11T`JGuzz%_}0jCHDP1G?L?M2Pb&==oH5% z3&B%}7Q5MCKW0;7ur0>!wJHAn?p|KDrG3HdbG+uIRw4cJga7etg>N02;=yMpIB+4y zNVbBz%wDFtz<+#IUxL?O-Oa0acGI)O=G{#I92+n2$se8L%Lm68&NMIWPlR+*F_WmF zVYwc8OOh!&xKeUHV{tw+#s2d-zJFqd&iL{sM@q?q&rI^M$Ii0ve1?4W2}4R?YS7kV zl8l&W0?Mvrw&YN-BxOf(bfUlWBW4C`8qh9<>QYI@z9ZJ#_|@8%Wc}C2C1k?#MH4|UmkNM2T#Fp#$q^A zVeh#tKRz?ZZ`?k}P3zN31Muufjz9VKNxuH-v-Qw?>JFbu=NcT**|y=ID5V$4}4luA;xny|M3+YYl&Rr ztQnrG@K=uv5i$ge?NP1?!IrKTKK_QCHL9d3qdzmphre}_?;e}R3BKN!4DqtfZQL}N zW9 z>X9M7a&R11K}Zw);?6F9>83tz+0aTVVh|1KOAk~z z|HLeripQs)93dXo`SAT)=b0lPys?XHEjf~@aDJ}50Dv=7MgHsePV?;}Qz!xPkk0+P zy7=W=2DrK}Nh)d(HWo%`702UEH@ZAClIJsfFYvXeC&*bY-#Io-#MJ3eZ(~DeOEUnU z-8;fR?Hk2a&|>Pm`}VcG=gvXawnmrSl2Hgj*wpDVbvoiqmw-HC+S+Tf1U>@RghRx7YX3vdn`NG))kX7{nt6Z@sCP-RqM4=|iXa-2O2N zmd8Ilae*7wrg`Iyy-nARni@UHFi}%qbpL6?(0J*FR&H3^Y#Qr596rBqgjetCLT?bxrp^}r zN(zcy9dK8+?9t!RyzB%|g6?SJTqZ;A~ec6P#A>`BG`;T+G5`j0Z)wx)$w?d&3IYRr}F1%#gv5DWR{Xt9xs zn!NG)9v(S1#oqH-j!zbO{7i;zJqbUve|98~6YSf+dtI7aH?&?>$kvqzbNi+?9zHhH z0DxeoU^6^d3c@$R-g6o5|GT}5o>%S*1@mcwvOH<1bD~BcDD5-*gu@3U^$$c zEV85T@^-K)J054Iij-^#0!A_xzw_mzgbYzzP{O=(lAg0B*MIEE`k+92zgMxihvT0N^(^hcvK&;W(fzFBcv^Tp8%~flTBSM%PXd#1yAwtDA`_ZHW^oS#{qw5lS89<&Q6yY?6~xY z+UF`RPo2*;JX&E9UlBF=z`Yw--yUPB=Wj(!ja_|7Hmu@agwSY>nXGM%aCD-;M9$*K zSe`q#v|rN9HZ;NOuj}Ey?Vae_;<JIm_XbKOW}u`$n-GZO z{P}lIac-`{as^l=C60XVt5Yh7!|&bJ$@Vn~K=6~Z8UE(cAr6n`FVUpd7oBQnX1I4-2iNo^=}ARMMhr|{;7TZ14wD6kV`F(9J~G7*PtP$PJY!cA^EUAKDUX)0 z!8>m5XDnCYANPz>3r_VQATnWC#FiAm@4tL zgX8q3BXlRiq+@0+i4sBW;;9Rn=gsENzh|SK;tL+Qb`8C$FrV8u%C`?saca6q!SXmZ zS>o7aX<4P{ONP07YX@)H-OJESnJ0$kYL^m15Ne*`q7 z9^?04v5B3%3BLH$7*7mkm?=3-7HlSq4v=3lxRjZK|# zUbCy4$4<=hz%{TV( z(v59AF_hs4CuTS@USMd}Z;!0l^LteZw&8(|9Wl0awOrOSVya_%Pn>~tgmZIcZW?T@ zJ!5j&hk52JF4F~@(X7Q(-Xa^6-y)_?%+%;ggy~6z>5PYHZK;)K=7G?-rYX{ak5Ma$*!({p6X4!3V=rzhp}ZT}yj%6?A5pUUk30000< KMNUMnLSTXgi@G%c literal 0 HcmV?d00001 diff --git a/resources/library/search/Data AbulEdu.wgs/images/down.png b/resources/library/search/Data AbulEdu.wgs/images/down.png new file mode 100644 index 0000000000000000000000000000000000000000..1de37e16ff7500ef6f776158baf7fdd9ded21190 GIT binary patch literal 1192 zcmaJ>Z)h839KJ3jYh#0{Yn`b&UT)BBu-v~ijX8R2(p-h2P> zJkRg>{oWt%Vs7MUDA*k&2qKg{Cg$5bL^{-0ZXK7^+T8Y-eOa{^Ul8xm>NEJ2Xf z@n6tCtOjcLj1wm&a@Gm?ps%1WgO% zBU42w2QsD&L7ZZu3e(4cK9*u*y@^EPFyI)Lp&5>5xhR|9V;s*gVEZF+G+UkE^WyM! zEW8uQDTFMZrYn^SRf$oiJxR04WYW{%xF|+MojC)^Zq#u0HxxwZD7I!H%`||gD3{Dx zB#_wYqZD*&N7it*%Y+L?yRt>I6yv4T07}yTLv?)z?Vvn-?Ds!~ox+?2={$7ISzEyu zH?iLfW$_ss%E+_}rde)OF*ju*)0r|YkQs}ElbWHL6=w@ANqp9DkZdS0D+(m$Q<|po zY@ZlUr_(XEH^#B-5SxtmC6Z!>Ne;&23?2=xXezThG*E-9KIZl|<$8^vTR5@^ZS6Iv z4%?;zu2rH2Leul^p77s8ck2r`Q%f!H%-=iP zGVp@GHj{he{(PG>+7bTfzzrsF>B57YPz-IpSsDra&~o7Xkxt+G9i8mxOn*&0TMyKJ zX@AeR6e*wBc)#$;nbROPm zPe0WgKL3ZG`^|r-yY1><{`%VOTJ_w*#jEXK-Tr)I<#;H(+y1@^PQB<~Pfc9e9eLl@9oGAjfkHOj-UAl+aH4^ literal 0 HcmV?d00001 diff --git a/resources/library/search/Data AbulEdu.wgs/images/greySquare.png b/resources/library/search/Data AbulEdu.wgs/images/greySquare.png new file mode 100644 index 0000000000000000000000000000000000000000..c0a7f14e8cc02340252ef48d9b5893d72b72239a GIT binary patch literal 214 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 literal 0 HcmV?d00001 diff --git a/resources/library/search/Data AbulEdu.wgs/images/search_app.png b/resources/library/search/Data AbulEdu.wgs/images/search_app.png new file mode 100644 index 0000000000000000000000000000000000000000..efd8ea4a12012eb26b752d8e34010722dab5e9d5 GIT binary patch literal 1104 zcmeAS@N?(olHy`uVBq!ia0vp^DGUsZ6FAs_tcYnx-vcSh64!{5;QX|b^2DN42FH~A zq*MjZ+{E~)xnb|6oG5YNp?TuQg4S4*GzV_wjJ4_p z)1oTcO7l0E2LN#d^R3&rDp|R6MNFplwsIbHGx^=?qr#Ht7;fGckWx0n?A|wW?c1rtk5eT9UX1% za8E4R+;`v7i+;)5XY8Hjwz(nFPh)y2%g>NY#>&Stmd@R0xk=~$zts*=y2>6~TVBt3 z|K*#8TimSa&Raeit3K3WuAKd>O)vPoX$>dyr@mc`pUg`C6@1~>3w3w6x2*Y*+{T}0 zc>Uyo(->(+%zCRdX?as?z9XT4cFth3yyj zjZ-w1)|CduEDGzE{t;L=Q|i~{2(KypKlQRjR2xI?T=}1PRPv(MzPj?0LeQXKU{q2- z1O`pn6IN_F_d9s`+ZA(Tj=i}Vx~Ama;+wS{M|bBPdEWiPKjz4dOQk*QzbDnK6>r}@ zdE@*Op~Zyt;WsdSptZ-CF+Ib8^$4?w8D2 zZVZfC4h{jvk2ka-@eJYs{RfV7DzhCBsR?8J9lKs_xbIr`;oB!~bP0l+XkKKzMR? literal 0 HcmV?d00001 diff --git a/resources/library/search/Data AbulEdu.wgs/images/trgDown.png b/resources/library/search/Data AbulEdu.wgs/images/trgDown.png new file mode 100644 index 0000000000000000000000000000000000000000..632be5fb5560dde4c9a5c76430e7878d817381b7 GIT binary patch literal 475 zcmV<10VMv3P)g(&fl=1oV=d#Yu&ZkvXRmDX`MZpSKSy>s_*w|1o z4-XH++qZ8ScJAEybnDiwrc4qN5|7*3+S1OPIm5ur%*?>T!UD%217L=L+LB44j;tU>bx41qB&)?AXEJ>gw9(?d`o2 zq=)hU|NkJG;memV+)hqT$F;Pybk)_>!D1jk@$&LA+`4s(;lzm(XMxVN;o{=@0g?mT z2m(MqeC_Y=Pd#?**iTSkaC37r02ML({ri_;`}XbMdwYA+V46@gf`GNP^~w17_y(Xt zu#@@t_!w5NUd;d$t1>e)JBO?m?o=26+Q8)H<+aDaz`zj{J=d>a-?4e~W>1hSPyk3H zI=*q^hO&l+#usgE?e}-@-j&CuhJ^tO00z$8l9G~qU{w58Qc`+|O$|VR0RRFkn+8)O RIpF{R002ovPDHLkV1k0cdU|>azJLGjVQ6T`prxh7@Z-l1$BvGUGIVt)8c&@%WwdbN!nV-R zP=-&RJ~4d!_>sZW(~|)x)^PObQFCOqaHoFz_Km~c-TjD#g@v)2ni|9B&z~87{`?7+ zyLs~_!?kPIF7Mm7&yt6S=PQbhH8nLYe0+RhO&>mdU;sK7)wQc_YNCAt+A6`d$f z-MV$F`|jPli#$9$7~a2s57q#}$eN9ej2Jd-*pR((<3>NQQ(wJ$CF$+$eH!RYX<=bu zhA&^fF#P)U3k3t?li}aLe+;i*zh=07`}WJdd-s~MZ)h837{BCbwX=at>swxn<+Kaw#pMB1QmO(3?voc!2st5+eCM7Ko zK|&FVFbxH%x^NASV;BzPY|hFhr#VqmNWsC7wxT08hK*0yx*(RJ1@f>ct6}1gFD?^6 zmcqnbAW0|nC@jfGYX;2JX0l?fERIRU#1SxVb4WmemH=#JUNt#8Ozh}#D0Yr10_;Gn za+r8fR4$nUQO$rLK+-;u4$>gVkc@vM6bc;%EX~jq%~A~OV?vyt0J~$cdaATUds6f@~aHWS_wky{$f}*3$ zF=)sqp)_S^3fO6wle^WzPfc~z+vQ5#YoWVxDO3#QjP+k*?i?ZSIN_dY(Pq!~P(@xh zkg0$B$pUL->I!{q56{XWi|)k$LRN%UBzD%60n*@BR4C-z|R= zX}MPFH_o{xMtj-|smE^C`;xQ!z2}Fo(!C$8-b;mZFW*=p6Ye|st-OS9HtZf80{8M< zvtPnl6}v>d*}L^f-gBrloqp{ge*K)c)!2F?TPPM^XZBxt=GWW9kuxJlHd|j`|2VTf z_}74Rb1Cl``Zm@2VCkLwLD%Oe0Dhu{f&dkHWs9F~d;30ZzVz9OnhpCv&zbL=tBv%j+wN^Q+kYJUX=V2L=8q!b-N3fXM1Rfm z;`!yZ_XiiUuJz@&n#b_ + + + + AbulÉdu Data Search + + + + + + +
+ + diff --git a/resources/library/search/Data AbulEdu.wgs/scripts/jquery-1.6.2.min.js b/resources/library/search/Data AbulEdu.wgs/scripts/jquery-1.6.2.min.js new file mode 100644 index 00000000..48590ecb --- /dev/null +++ b/resources/library/search/Data AbulEdu.wgs/scripts/jquery-1.6.2.min.js @@ -0,0 +1,18 @@ +/*! + * jQuery JavaScript Library v1.6.2 + * http://jquery.com/ + * + * Copyright 2011, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Thu Jun 30 14:16:56 2011 -0400 + */ +(function(a,b){function cv(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cs(a){if(!cg[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ch||(ch=c.createElement("iframe"),ch.frameBorder=ch.width=ch.height=0),b.appendChild(ch);if(!ci||!ch.createElement)ci=(ch.contentWindow||ch.contentDocument).document,ci.write((c.compatMode==="CSS1Compat"?"":"")+""),ci.close();d=ci.createElement(a),ci.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ch)}cg[a]=e}return cg[a]}function cr(a,b){var c={};f.each(cm.concat.apply([],cm.slice(0,b)),function(){c[this]=a});return c}function cq(){cn=b}function cp(){setTimeout(cq,0);return cn=f.now()}function cf(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ce(){try{return new a.XMLHttpRequest}catch(b){}}function b$(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g0){c!=="border"&&f.each(e,function(){c||(d-=parseFloat(f.css(a,"padding"+this))||0),c==="margin"?d+=parseFloat(f.css(a,c+this))||0:d-=parseFloat(f.css(a,"border"+this+"Width"))||0});return d+"px"}d=bx(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0,c&&f.each(e,function(){d+=parseFloat(f.css(a,"padding"+this))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+this+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+this))||0)});return d+"px"}function bm(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(be,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bl(a){f.nodeName(a,"input")?bk(a):"getElementsByTagName"in a&&f.grep(a.getElementsByTagName("input"),bk)}function bk(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bj(a){return"getElementsByTagName"in a?a.getElementsByTagName("*"):"querySelectorAll"in a?a.querySelectorAll("*"):[]}function bi(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bh(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c=f.expando,d=f.data(a),e=f.data(b,d);if(d=d[c]){var g=d.events;e=e[c]=f.extend({},d);if(g){delete e.handle,e.events={};for(var h in g)for(var i=0,j=g[h].length;i=0===c})}function V(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function N(a,b){return(a&&a!=="*"?a+".":"")+b.replace(z,"`").replace(A,"&")}function M(a){var b,c,d,e,g,h,i,j,k,l,m,n,o,p=[],q=[],r=f._data(this,"events");if(!(a.liveFired===this||!r||!r.live||a.target.disabled||a.button&&a.type==="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var s=r.live.slice(0);for(i=0;ic)break;a.currentTarget=e.elem,a.data=e.handleObj.data,a.handleObj=e.handleObj,o=e.handleObj.origHandler.apply(e.elem,arguments);if(o===!1||a.isPropagationStopped()){c=e.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function K(a,c,d){var e=f.extend({},d[0]);e.type=a,e.originalEvent={},e.liveFired=b,f.event.handle.call(c,e),e.isDefaultPrevented()&&d[0].preventDefault()}function E(){return!0}function D(){return!1}function m(a,c,d){var e=c+"defer",g=c+"queue",h=c+"mark",i=f.data(a,e,b,!0);i&&(d==="queue"||!f.data(a,g,b,!0))&&(d==="mark"||!f.data(a,h,b,!0))&&setTimeout(function(){!f.data(a,g,b,!0)&&!f.data(a,h,b,!0)&&(f.removeData(a,e,!0),i.resolve())},0)}function l(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function k(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(j,"$1-$2").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNaN(d)?i.test(d)?f.parseJSON(d):d:parseFloat(d)}catch(g){}f.data(a,c,d)}else d=b}return d}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/\d/,n=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,o=/^[\],:{}\s]*$/,p=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,q=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,r=/(?:^|:|,)(?:\s*\[)+/g,s=/(webkit)[ \/]([\w.]+)/,t=/(opera)(?:.*version)?[ \/]([\w.]+)/,u=/(msie) ([\w.]+)/,v=/(mozilla)(?:.*? rv:([\w.]+))?/,w=/-([a-z])/ig,x=function(a,b){return b.toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=n.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.6.2",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;A.resolveWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!A){A=e._Deferred();if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNaN:function(a){return a==null||!m.test(a)||isNaN(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1;var c;for(c in a);return c===b||D.call(a,c)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(o.test(b.replace(p,"@").replace(q,"]").replace(r,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(b,c,d){a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b)),d=c.documentElement,(!d||!d.nodeName||d.nodeName==="parsererror")&&e.error("Invalid XML: "+b);return c},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i1?h.call(arguments,0):c,--e||g.resolveWith(g,h.call(b,0))}}var b=arguments,c=0,d=b.length,e=d,g=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred();if(d>1){for(;c
a",d=a.getElementsByTagName("*"),e=a.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=a.getElementsByTagName("input")[0],k={leadingWhitespace:a.firstChild.nodeType===3,tbody:!a.getElementsByTagName("tbody").length,htmlSerialize:!!a.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55$/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:a.className!=="t",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,k.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,k.optDisabled=!h.disabled;try{delete a.test}catch(v){k.deleteExpando=!1}!a.addEventListener&&a.attachEvent&&a.fireEvent&&(a.attachEvent("onclick",function(){k.noCloneEvent=!1}),a.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),k.radioValue=i.value==="t",i.setAttribute("checked","checked"),a.appendChild(i),l=c.createDocumentFragment(),l.appendChild(a.firstChild),k.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,a.innerHTML="",a.style.width=a.style.paddingLeft="1px",m=c.getElementsByTagName("body")[0],o=c.createElement(m?"div":"body"),p={visibility:"hidden",width:0,height:0,border:0,margin:0},m&&f.extend(p,{position:"absolute",left:-1e3,top:-1e3});for(t in p)o.style[t]=p[t];o.appendChild(a),n=m||b,n.insertBefore(o,n.firstChild),k.appendChecked=i.checked,k.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,k.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="
",k.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="
t
",q=a.getElementsByTagName("td"),u=q[0].offsetHeight===0,q[0].style.display="",q[1].style.display="none",k.reliableHiddenOffsets=u&&q[0].offsetHeight===0,a.innerHTML="",c.defaultView&&c.defaultView.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",a.appendChild(j),k.reliableMarginRight=(parseInt((c.defaultView.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0),o.innerHTML="",n.removeChild(o);if(a.attachEvent)for(t in{submit:1,change:1,focusin:1})s="on"+t,u=s in a,u||(a.setAttribute(s,"return;"),u=typeof a[s]=="function"),k[t+"Bubbles"]=u;o=l=g=h=m=j=a=i=null;return k}(),f.boxModel=f.support.boxModel;var i=/^(?:\{.*\}|\[.*\])$/,j=/([a-z])([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!l(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g=f.expando,h=typeof c=="string",i,j=a.nodeType,k=j?f.cache:a,l=j?a[f.expando]:a[f.expando]&&f.expando;if((!l||e&&l&&!k[l][g])&&h&&d===b)return;l||(j?a[f.expando]=l=++f.uuid:l=f.expando),k[l]||(k[l]={},j||(k[l].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?k[l][g]=f.extend(k[l][g],c):k[l]=f.extend(k[l],c);i=k[l],e&&(i[g]||(i[g]={}),i=i[g]),d!==b&&(i[f.camelCase(c)]=d);if(c==="events"&&!i[c])return i[g]&&i[g].events;return h?i[f.camelCase(c)]||i[c]:i}},removeData:function(b,c,d){if(!!f.acceptData(b)){var e=f.expando,g=b.nodeType,h=g?f.cache:b,i=g?b[f.expando]:f.expando;if(!h[i])return;if(c){var j=d?h[i][e]:h[i];if(j){delete j[c];if(!l(j))return}}if(d){delete h[i][e];if(!l(h[i]))return}var k=h[i][e];f.support.deleteExpando||h!=a?delete h[i]:h[i]=null,k?(h[i]={},g||(h[i].toJSON=f.noop),h[i][e]=k):g&&(f.support.deleteExpando?delete b[f.expando]:b.removeAttribute?b.removeAttribute(f.expando):b[f.expando]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d=null;if(typeof a=="undefined"){if(this.length){d=f.data(this[0]);if(this[0].nodeType===1){var e=this[0].attributes,g;for(var h=0,i=e.length;h-1)return!0;return!1},val:function(a){var c,d,e=this[0];if(!arguments.length){if(e){c=f.valHooks[e.nodeName.toLowerCase()]||f.valHooks[e.type];if(c&&"get"in c&&(d=c.get(e,"value"))!==b)return d;d=e.value;return typeof d=="string"?d.replace(p,""):d==null?"":d}return b}var g=f.isFunction(a);return this.each(function(d){var e=f(this),h;if(this.nodeType===1){g?h=a.call(this,d,e.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c=a.selectedIndex,d=[],e=a.options,g=a.type==="select-one";if(c<0)return null;for(var h=g?c:0,i=g?c+1:e.length;h=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attrFix:{tabindex:"tabIndex"},attr:function(a,c,d,e){var g=a.nodeType;if(!a||g===3||g===8||g===2)return b;if(e&&c in f.attrFn)return f(a)[c](d);if(!("getAttribute"in a))return f.prop(a,c,d);var h,i,j=g!==1||!f.isXMLDoc(a);j&&(c=f.attrFix[c]||c,i=f.attrHooks[c],i||(t.test(c)?i=w:v&&c!=="className"&&(f.nodeName(a,"form")||u.test(c))&&(i=v)));if(d!==b){if(d===null){f.removeAttr(a,c);return b}if(i&&"set"in i&&j&&(h=i.set(a,d,c))!==b)return h;a.setAttribute(c,""+d);return d}if(i&&"get"in i&&j&&(h=i.get(a,c))!==null)return h;h=a.getAttribute(c);return h===null?b:h},removeAttr:function(a,b){var c;a.nodeType===1&&(b=f.attrFix[b]||b,f.support.getSetAttribute?a.removeAttribute(b):(f.attr(a,b,""),a.removeAttributeNode(a.getAttributeNode(b))),t.test(b)&&(c=f.propFix[b]||b)in a&&(a[c]=!1))},attrHooks:{type:{set:function(a,b){if(q.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},tabIndex:{get:function(a){var c=a.getAttributeNode("tabIndex");return c&&c.specified?parseInt(c.value,10):r.test(a.nodeName)||s.test(a.nodeName)&&a.href?0:b}},value:{get:function(a,b){if(v&&f.nodeName(a,"button"))return v.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(v&&f.nodeName(a,"button"))return v.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e=a.nodeType;if(!a||e===3||e===8||e===2)return b;var g,h,i=e!==1||!f.isXMLDoc(a);i&&(c=f.propFix[c]||c,h=f.propHooks[c]);return d!==b?h&&"set"in h&&(g=h.set(a,d,c))!==b?g:a[c]=d:h&&"get"in h&&(g=h.get(a,c))!==b?g:a[c]},propHooks:{}}),w={get:function(a,c){return f.prop(a,c)?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},f.support.getSetAttribute||(f.attrFix=f.propFix,v=f.attrHooks.name=f.attrHooks.title=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&d.nodeValue!==""?d.nodeValue:b},set:function(a,b,c){var d=a.getAttributeNode(c);if(d){d.nodeValue=b;return b}}},f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})})),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}})),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var x=/\.(.*)$/,y=/^(?:textarea|input|select)$/i,z=/\./g,A=/ /g,B=/[^\w\s.|`]/g,C=function(a){return a.replace(B,"\\$&")};f.event={add:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){if(d===!1)d=D;else if(!d)return;var g,h;d.handler&&(g=d,d=g.handler),d.guid||(d.guid=f.guid++);var i=f._data(a);if(!i)return;var j=i.events,k=i.handle;j||(i.events=j={}),k||(i.handle=k=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.handle.apply(k.elem,arguments):b}),k.elem=a,c=c.split(" ");var l,m=0,n;while(l=c[m++]){h=g?f.extend({},g):{handler:d,data:e},l.indexOf(".")>-1?(n=l.split("."),l=n.shift(),h.namespace=n.slice(0).sort().join(".")):(n=[],h.namespace=""),h.type=l,h.guid||(h.guid=d.guid);var o=j[l],p=f.event.special[l]||{};if(!o){o=j[l]=[];if(!p.setup||p.setup.call(a,e,n,k)===!1)a.addEventListener?a.addEventListener(l,k,!1):a.attachEvent&&a.attachEvent("on"+l,k)}p.add&&(p.add.call(a,h),h.handler.guid||(h.handler.guid=d.guid)),o.push(h),f.event.global[l]=!0}a=null}},global:{},remove:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){d===!1&&(d=D);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=f.hasData(a)&&f._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(d=c.handler,c=c.type);if(!c||typeof c=="string"&&c.charAt(0)==="."){c=c||"";for(h in t)f.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+f.map(m.slice(0).sort(),C).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!d){for(j=0;j=0&&(h=h.slice(0,-1),j=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i. +shift(),i.sort());if(!!e&&!f.event.customEvent[h]||!!f.event.global[h]){c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.exclusive=j,c.namespace=i.join("."),c.namespace_re=new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)");if(g||!e)c.preventDefault(),c.stopPropagation();if(!e){f.each(f.cache,function(){var a=f.expando,b=this[a];b&&b.events&&b.events[h]&&f.event.trigger(c,d,b.handle.elem)});return}if(e.nodeType===3||e.nodeType===8)return;c.result=b,c.target=e,d=d!=null?f.makeArray(d):[],d.unshift(c);var k=e,l=h.indexOf(":")<0?"on"+h:"";do{var m=f._data(k,"handle");c.currentTarget=k,m&&m.apply(k,d),l&&f.acceptData(k)&&k[l]&&k[l].apply(k,d)===!1&&(c.result=!1,c.preventDefault()),k=k.parentNode||k.ownerDocument||k===c.target.ownerDocument&&a}while(k&&!c.isPropagationStopped());if(!c.isDefaultPrevented()){var n,o=f.event.special[h]||{};if((!o._default||o._default.call(e.ownerDocument,c)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)){try{l&&e[h]&&(n=e[l],n&&(e[l]=null),f.event.triggered=h,e[h]())}catch(p){}n&&(e[l]=n),f.event.triggered=b}}return c.result}},handle:function(c){c=f.event.fix(c||a.event);var d=((f._data(this,"events")||{})[c.type]||[]).slice(0),e=!c.exclusive&&!c.namespace,g=Array.prototype.slice.call(arguments,0);g[0]=c,c.currentTarget=this;for(var h=0,i=d.length;h-1?f.map(a.options,function(a){return a.selected}).join("-"):"":f.nodeName(a,"select")&&(c=a.selectedIndex);return c},J=function(c){var d=c.target,e,g;if(!!y.test(d.nodeName)&&!d.readOnly){e=f._data(d,"_change_data"),g=I(d),(c.type!=="focusout"||d.type!=="radio")&&f._data(d,"_change_data",g);if(e===b||g===e)return;if(e!=null||g)c.type="change",c.liveFired=b,f.event.trigger(c,arguments[1],d)}};f.event.special.change={filters:{focusout:J,beforedeactivate:J,click:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(c==="radio"||c==="checkbox"||f.nodeName(b,"select"))&&J.call(this,a)},keydown:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(a.keyCode===13&&!f.nodeName(b,"textarea")||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&J.call(this,a)},beforeactivate:function(a){var b=a.target;f._data(b,"_change_data",I(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in H)f.event.add(this,c+".specialChange",H[c]);return y.test(this.nodeName)},teardown:function(a){f.event.remove(this,".specialChange");return y.test(this.nodeName)}},H=f.event.special.change.filters,H.focus=H.beforeactivate}f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){function e(a){var c=f.event.fix(a);c.type=b,c.originalEvent={},f.event.trigger(c,null,c.target),c.isDefaultPrevented()&&a.preventDefault()}var d=0;f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.each(["bind","one"],function(a,c){f.fn[c]=function(a,d,e){var g;if(typeof a=="object"){for(var h in a)this[c](h,d,a[h],e);return this}if(arguments.length===2||d===!1)e=d,d=b;c==="one"?(g=function(a){f(this).unbind(a,g);return e.apply(this,arguments)},g.guid=e.guid||f.guid++):g=e;if(a==="unload"&&c!=="one")this.one(a,d,e);else for(var i=0,j=this.length;i0?this.bind(b,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d=0,e=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,f,g){f=f||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return f;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(e.call(n)==="[object Array]")if(!u)f.push.apply(f,n);else if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&f.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&f.push(j[t]);else p(n,f);o&&(k(o,h,f,g),k.uniqueSort(f));return f};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=d++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(e.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var f=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(e||!l.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return k(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="
";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g0)for(h=g;h0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(d=0,e=a.length;d-1:f(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=T.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a||typeof a=="string")return f.inArray(this[0],a?f(a):this.parent().children());return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(V(c[0])||V(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c),g=S.call(arguments);O.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!U[a]?f.unique(e):e,(this.length>1||Q.test(d))&&P.test(a)&&(e=e.reverse());return this.pushStack(e,a,g.join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var X=/ jQuery\d+="(?:\d+|null)"/g,Y=/^\s+/,Z=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,$=/<([\w:]+)/,_=/",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]};bf.optgroup=bf.option,bf.tbody=bf.tfoot=bf.colgroup=bf.caption=bf.thead,bf.th=bf.td,f.support.htmlSerialize||(bf._default=[1,"div
","
"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){f(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(X,""):null;if(typeof a=="string"&&!bb.test(a)&&(f.support.leadingWhitespace||!Y.test(a))&&!bf[($.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Z,"<$1>");try{for(var c=0,d=this.length;c1&&l0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j +)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d=a.cloneNode(!0),e,g,h;if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bi(a,d),e=bj(a),g=bj(d);for(h=0;e[h];++h)bi(e[h],g[h])}if(b){bh(a,d);if(c){e=bj(a),g=bj(d);for(h=0;e[h];++h)bh(e[h],g[h])}}e=g=null;return d},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!ba.test(k))k=b.createTextNode(k);else{k=k.replace(Z,"<$1>");var l=($.exec(k)||["",""])[1].toLowerCase(),m=bf[l]||bf._default,n=m[0],o=b.createElement("div");o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=_.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]===""&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&Y.test(k)&&o.insertBefore(b.createTextNode(Y.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bo.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle;c.zoom=1;var e=f.isNaN(b)?"":"alpha(opacity="+b*100+")",g=d&&d.filter||c.filter||"";c.filter=bn.test(g)?g.replace(bn,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bx(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(by=function(a,c){var d,e,g;c=c.replace(bp,"-$1").toLowerCase();if(!(e=a.ownerDocument.defaultView))return b;if(g=e.getComputedStyle(a,null))d=g.getPropertyValue(c),d===""&&!f.contains(a.ownerDocument.documentElement,a)&&(d=f.style(a,c));return d}),c.documentElement.currentStyle&&(bz=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bq.test(d)&&br.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bx=by||bz,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bB=/%20/g,bC=/\[\]$/,bD=/\r?\n/g,bE=/#.*$/,bF=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bG=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bH=/^(?:about|app|app\-storage|.+\-extension|file|widget):$/,bI=/^(?:GET|HEAD)$/,bJ=/^\/\//,bK=/\?/,bL=/)<[^<]*)*<\/script>/gi,bM=/^(?:select|textarea)/i,bN=/\s+/,bO=/([?&])_=[^&]*/,bP=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bQ=f.fn.load,bR={},bS={},bT,bU;try{bT=e.href}catch(bV){bT=c.createElement("a"),bT.href="",bT=bT.href}bU=bP.exec(bT.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bQ)return bQ.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("
").append(c.replace(bL,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bM.test(this.nodeName)||bG.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bD,"\r\n")}}):{name:b.name,value:c.replace(bD,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.bind(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?f.extend(!0,a,f.ajaxSettings,b):(b=a,a=f.extend(!0,f.ajaxSettings,b));for(var c in{context:1,url:1})c in b?a[c]=b[c]:c in f.ajaxSettings&&(a[c]=f.ajaxSettings[c]);return a},ajaxSettings:{url:bT,isLocal:bH.test(bU[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":"*/*"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML}},ajaxPrefilter:bW(bR),ajaxTransport:bW(bS),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a?4:0;var o,r,u,w=l?bZ(d,v,l):b,x,y;if(a>=200&&a<300||a===304){if(d.ifModified){if(x=v.getResponseHeader("Last-Modified"))f.lastModified[k]=x;if(y=v.getResponseHeader("Etag"))f.etag[k]=y}if(a===304)c="notmodified",o=!0;else try{r=b$(d,w),c="success",o=!0}catch(z){c="parsererror",u=z}}else{u=c;if(!c||a)c="error",a<0&&(a=0)}v.status=a,v.statusText=c,o?h.resolveWith(e,[r,c,v]):h.rejectWith(e,[v,c,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.resolveWith(e,[v,c]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f._Deferred(),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bF.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.done,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bE,"").replace(bJ,bU[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bN),d.crossDomain==null&&(r=bP.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bU[1]&&r[2]==bU[2]&&(r[3]||(r[1]==="http:"?80:443))==(bU[3]||(bU[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bX(bR,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bI.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bK.test(d.url)?"&":"?")+d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bO,"$1_="+x);d.url=y+(y===d.url?(bK.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", */*; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bX(bS,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){status<2?w(-1,z):f.error(z)}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)bY(g,a[g],c,e);return d.join("&").replace(bB,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var b_=f.now(),ca=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+b_++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ca.test(b.url)||e&&ca.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ca,l),b.url===j&&(e&&(k=k.replace(ca,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cb=a.ActiveXObject?function(){for(var a in cd)cd[a](0,1)}:!1,cc=0,cd;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ce()||cf()}:ce,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cb&&delete cd[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cc,cb&&(cd||(cd={},f(a).unload(cb)),cd[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cg={},ch,ci,cj=/^(?:toggle|show|hide)$/,ck=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cl,cm=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cn,co=a.webkitRequestAnimationFrame||a.mozRequestAnimationFrame||a.oRequestAnimationFrame;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cr("show",3),a,b,c);for(var g=0,h=this.length;g=e.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),e.animatedProperties[this.prop]=!0;for(g in e.animatedProperties)e.animatedProperties[g]!==!0&&(c=!1);if(c){e.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){d.style["overflow"+b]=e.overflow[a]}),e.hide&&f(d).hide();if(e.hide||e.show)for(var i in e.animatedProperties)f.style(d,i,e.orig[i]);e.complete.call(d)}return!1}e.duration==Infinity?this.now=b:(h=b-this.startTime,this.state=h/e.duration,this.pos=f.easing[e.animatedProperties[this.prop]](this.state,h,0,1,e.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){for(var a=f.timers,b=0;b
";f.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),d=b.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,this.doesNotAddBorder=e.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,e.style.position="fixed",e.style.top="20px",this.supportsFixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",this.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),f.offset.initialize=f.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.offset.initialize(),f.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cu.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cu.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cv(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cv(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a&&a.style?parseFloat(f.css(a,d,"padding")):null},f.fn["outer"+c]=function(a){var b=this[0];return b&&b.style?parseFloat(f.css(b,d,a?"margin":"border")):null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c];return e.document.compatMode==="CSS1Compat"&&g||e.document.body["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var h=f.css(e,d),i=parseFloat(h);return f.isNaN(i)?h:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f})(window); \ No newline at end of file From cb44c2b6b0b102b4adeabd00c2dc25432b97da70 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Thu, 21 Jan 2016 11:45:25 +0100 Subject: [PATCH 093/243] Basic readme --- README | 3 --- README.md | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 3 deletions(-) delete mode 100644 README create mode 100644 README.md diff --git a/README b/README deleted file mode 100644 index ad854867..00000000 --- a/README +++ /dev/null @@ -1,3 +0,0 @@ -[Ubuntu Linux] -Fonts - - If you want to use the web compatible fonts, you need to install the package ttf-mscorefonts-installer. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 00000000..aa068de7 --- /dev/null +++ b/README.md @@ -0,0 +1,33 @@ +# OpenBoard +OpenBoard is an open source cross-platform interactive white board application designed for use in schools. It is a fork of Open-Sankoré, which was itself based on Uniboard. + +Supported platforms are Windows (7+), OS X (10.9+) and Linux (tested on Ubuntu 14.04, but should work with other distributions too). + +# Dependencies + +The latest version (1.10) requires Qt 5.5. See below for Linux-specific instructions. + +OpenBoard makes use of several third-party libraries, which are available in the OpenBoard-ThirdParty repository. These should be built first; instructions are provided for each library. + +## Linux + +### Qt +Due to a shared library conflict within Qt5 on Linux (the Qt Multimedia and Qt Webkit modules are built against different versions of gstreamer by default), a specific installation of Qt5.5 is 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: + + sudo add-apt-repository ppa:beineri/opt-qt551-trusty + sudo apt-get update + sudo apt-get install qt-latest + +### Onboard +OpenBoard has a built-in virtual keyboard, but also allows the use of an external OSK (which is now the default, as the built-in keyboard will likely be removed in a future release). +On Linux, Onboard is currently used as the external OSK. In case you can't or won't install it, you can simply use the built-in OSK instead. + +# Installation & Deployment + +Deployment scripts 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. + + From 2606c696c7f53f949dd529d683ce4dd354cf185c Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Thu, 21 Jan 2016 11:52:54 +0100 Subject: [PATCH 094/243] Added onboard as dependency in .deb package --- buildDebianPackage.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/buildDebianPackage.sh b/buildDebianPackage.sh index 2ae25d43..5251cf17 100755 --- a/buildDebianPackage.sh +++ b/buildDebianPackage.sh @@ -391,6 +391,7 @@ for ((i=0;i<${#tab[@]};i++)); do fi echo -n "${tab[$i]} (>= "`dpkg -p ${tab[$i]} | grep "Version: " | awk '{ print $2 }' | sed -e 's/\([:. 0-9?]*\).*/\1/g' | sed -e 's/\.$//'`") " >> "$CONTROL_FILE" done +echo -n ", onboard" >> "$CONTROL_FILE" echo "" >> "$CONTROL_FILE" echo "Description: This a interactive white board that uses a free standard format." >> "$CONTROL_FILE" @@ -420,7 +421,7 @@ chown -R root:root $BASE_WORKING_DIR dpkg -b "$BASE_WORKING_DIR" "install/linux/$DEBIAN_PACKAGE_NAME" #clean up mess -#rm -rf $BASE_WORKING_DIR +rm -rf $BASE_WORKING_DIR notifyProgress "${APPLICATION_NAME}" "Package built" From 03564f05570273b756c2a5c14e16757f177d0c53 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Thu, 21 Jan 2016 12:25:05 +0100 Subject: [PATCH 095/243] Fixed error displayed when podcast recorded successfully, on OSX --- src/podcast/quicktime/UBQuickTimeVideoEncoder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/podcast/quicktime/UBQuickTimeVideoEncoder.cpp b/src/podcast/quicktime/UBQuickTimeVideoEncoder.cpp index cd03d8ed..5c8839fb 100644 --- a/src/podcast/quicktime/UBQuickTimeVideoEncoder.cpp +++ b/src/podcast/quicktime/UBQuickTimeVideoEncoder.cpp @@ -91,7 +91,7 @@ void UBQuickTimeVideoEncoder::compressionFinished() { mLastErrorMessage = mQuickTimeCompressionSession.lastErrorMessage(); - emit encodingFinished(mLastErrorMessage.length() > 0); + emit encodingFinished(mLastErrorMessage.length() == 0); } From 3bbf341e85cde2e4d100819d9191b999cba6d4b4 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Thu, 21 Jan 2016 14:59:45 +0100 Subject: [PATCH 096/243] Updated version number (1.10a7) --- OpenBoard.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenBoard.pro b/OpenBoard.pro index c21f1934..cd13a96d 100644 --- a/OpenBoard.pro +++ b/OpenBoard.pro @@ -11,7 +11,7 @@ CONFIG += debug_and_release \ VERSION_MAJ = 1 VERSION_MIN = 10 VERSION_TYPE = a # a = alpha, b = beta, rc = release candidate, r = release, other => error -VERSION_PATCH = 6 +VERSION_PATCH = 7 VERSION = "$${VERSION_MAJ}.$${VERSION_MIN}.$${VERSION_TYPE}.$${VERSION_PATCH}" VERSION = $$replace(VERSION, "\\.r", "") From 6a388505da5ec397b49172aabde1afb3dee02052 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 23 Jan 2016 20:39:54 +0100 Subject: [PATCH 097/243] New previous page / next page icons --- resources/images/toolbar/nextPage.png | Bin 1802 -> 2311 bytes resources/images/toolbar/nextPageOn.png | Bin 1803 -> 2245 bytes resources/images/toolbar/previousPage.png | Bin 1801 -> 2260 bytes resources/images/toolbar/previousPageOn.png | Bin 1813 -> 2199 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/resources/images/toolbar/nextPage.png b/resources/images/toolbar/nextPage.png index d0c3665c8b4aae2566f6fc7a143883a41fd7917b..8a5b027819a9c0e4d6ccbf3a05afb31e5774fdb8 100644 GIT binary patch delta 2279 zcmV004Rm004lS009MJ004i_002>w009Dx0027=000>u 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 IM6N<$f`2ScfdBvi diff --git a/resources/images/toolbar/nextPageOn.png b/resources/images/toolbar/nextPageOn.png index 0c7989e5cd3c380cb2788ee36edad1da879aa5bc..a8f29d253e10685eea21aa6937bf2e8c74fb7286 100644 GIT binary patch delta 2213 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 delta 1767 zcmV z$3Jg6p->W`xV9mnJUpbKBw=g?w+J=aB;Cd=>oQH6KNMs$`*wHC%k21Oc56!!2}qA^ zJ&Kq9p?E0bNpkSu$sR-k*6Jk)9;*n&LN8L*!|b04ZE1fn@PB!~-|u~Ye+C{5d|M7f zZAsV+V&mp>a%FW*?*D}Wh8P4Wdr>%DDir|AVW`<_0v`W{0Jt~tjQERe$gHfcfsjC^ zmhjs^Wi+P-<8!hnY0-%z{%HP-%owtS_F4)!{O1sZ)_M|TZZl9 zecvM&0f<98QT6z-WNU*t82F>zel!aEzkny#+U@^twA)W^!oFSjL3>Tp>h4(l3`xJ; zoo~BcdLAb;0g#33r(yX3EPM`M{s~9EfmgqS(hw}3z<>IT?iZ_1Vt|=Oc)|F!dMuAQ z&O35C47HN;fj2oW%UVn0*XnU3jf#|Msmdgqy6JW59Rvnduyh6(1?y84&2?C8Rm!sq zz$A#jDr$BP7zgon)ju^4i~+kPM|J zb6x*O<$w1}zz7I;qp{!uhrpV;SYKRDSm=xOnPP{3HBEO3coVE!p)M7Y-mD*4MWgTu zPy|R^^5mEx#L%FMkB`PDk0L-}@QK)XW~Qc;Vo9C{1U$gt^D#{n5|^{&ifoPd6r}UJ z^N(}ix$fL@{=PcW9P3B6%!j_WbLAl=6sD)!iGOx_O7uM%Orz1%P;B;Qic+1Xx~m3P zNBTP@xx+|NtjSN0qBTlT!2wND`J_v|VAq&;hA?RV`$@5T}VKIc&wBFbn2E+F^( zzkhBn$=d=zCa(fzd{4UhoGh6})z>QZ%)KD|lJ-Bia1GyYDSE~L001CkNK#Dz0Bx86 z0CSE20P;=%0EHd^0B()|0OdUZ05dKC02tA|5{Q2Q00VGIL_t(|+QgPiZyQwR8Ll6S71eEfqil`zaAd2Gz+KN)qA5ekR zKwAm1iHfbNB#xs}$4%QLp2VKVy_ba@j8I7Dm3JPaD;6BviG(Ks%YTtN zKxas2_{~RlB;iRwNTmU&vcOP^;Wr*`T0(C{Co8FtC6^8%8GgOLDTytCmx0rOY9^u~ z-#maU3#2U&n+{Q1Ff`In_pVSw68`FYWazC&_wVTmpoDB9b&$41tlKE3vQ9XXXh@QH zbsx#E7shU^SO5p_Ca}M++mDqqL4SHbn1myVx{Ac`K9UpLOVoNm*`gAz^d62xm^Km9 zA~Cdg+uxzrH&RRB^%6y!@LHL{MEs5t|LlTR3)D-jmKjX!*^+qwzo|gI#JWXjrNn{3 zINiHKAJ$9g^&PE*YEQTdQM3tM-QYl?Ch^Se6%ew0;Z_xwcxl_RrgetPnJVH{W)9f-T_6{y0Cu_!aCMKW3Q z&=2PdM}WfUK-|7<8)^X^&3~u0=%%URyC;Cz6D2jZ$RG3O=O@lCe{n0k)`YH5KP{Dc zw(p5pZK^dk4HaU;#l2QWmfV}*rTaQaC3B<~%p)hxE*}P#M+f58zfQv&8_v}D$C*we z?0c%&WV>QPUVEt*yX4m3Rmk-?uUK2?DeB~4{2Y>VezDD8w4@B-y zJimKFkN80YpAo?B?I1OsBRyaI>i94DPqu^Cp93Z^5B$|kWA5$=_f^VXfjbWxq-K`5 zaH%+PY&Jgzw&0@!an<%qsS}GZ zbNn)Mnf2t++588M!eBiM*sd}yOEP)*B6I1rR26;&C^rJf>rp&$`ttRs`#T?x1obD+ zq*s5hX5KKI7R&<} diff --git a/resources/images/toolbar/previousPage.png b/resources/images/toolbar/previousPage.png index 096c9d3bbf50883183af28be2cba2b5ad3a9417e..1df6a40f07df2dadd2a7d8e9b79e5f22c0a42410 100644 GIT binary patch delta 2228 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 Hu0mjf2r*p6 diff --git a/resources/images/toolbar/previousPageOn.png b/resources/images/toolbar/previousPageOn.png index bbcdc40f9872312b13088e03d8e60ea70f50c885..7f9f5b6cb14ca23e4d5952dae1f64ad6c9f8eeca 100644 GIT binary patch delta 2166 zcmV-+2#NQV4wn&-IDY^jV@Og>004Rm004lS009MJ004i_002>w009Dx0027=000>u zE&;m#000ObNklJsZ@CS>8J61 zpX2THKKttKjMcvNt;Q340<$;)i(2w)=bsk+T`IxNpLC8Ba6n!6y({fax8LZKFPS$# z@hl(pLu11C|9`e-)fdzg_dcZ2M=T0OqfSZ$ip3(v7)%%vwuUhVtpkEU0|J5l-L;p? zCw~5bfwlzu-&P1or8(9A8}h>=AcSCO(ZcKMwdw_d)~PTI12FiWOC%EKlCNH)U;F#E zo^LE2xpc!lQ6LG!f>No5tFxb9uyEc}w$##?P_$+Q41X9iy?|6oxuc__+b8mecS?wM zwVQv77SrVwU%&jXXP@_ic`845=XsVp3t zDzotgLn;=g%)^rh3Rzg9yKHh10H_)HK!$a*py+*xDu zzXGG;vFP0M&R=%j!ZXif$(e)4{G)-jH?1b|-YWn4Aodw!nB23vdbwxA^gh zm#Ih!Q!YY!p30>= z2tO|MHH5lFLa9{Rwj)ICCPQtdn8;6Z$9Gopsn}-jU)O>EPA4VDLn;A*;Djv@O_&5I z9RyMb0a`bK3x(j$wKpS1Hgo@zIU4`yp`>dlB{2FVEDoS8FyezNVZH8=oi)IY5!m`% zo_}b+L&S>_`T~6G#D`~rFCi2lOv?drl(CcJqg=W28Wt|Ug_S>sXSW|9yP$z`6X>8B z1*5GK8Uz-`G*eSe=Zk6OY-cXVDRbwt=<$cSGtKfs#h zgRm=$6SyQJ7PZV2f7(4peJVsskP^ZWba=D^S`u^sp#iNy#-UJzw3PCHB2cYXTYn8m zU|UV-~IW$Br97Pj>8eIIE_q->^j7=~!A zQMQfNhFC0$5D}8`2&1)^hL34R7(t;>pkA*dguwTG9LFJ%h;!}Lml1}V2Y>Pd>Wzb} zzXUkcOW}yiMHen-^}64n8%6RH<9{R)3F7etVDLPjYPCvxdlujG>F?{sPIj>Q`7QkH zp{YqV-83xGtmCt0&&E~?&-18MD&%sVBocAJ;v?KzlaJ zxr@4iZVnu<>FDSnlgR*3tJN4A8)IN#0AmbNN?Z+2ag?*qI5naGq?FX^E`Pa91Y61( zO_**=kch|F@zyZeY>Heu&YGL9qQAe7TUTF8XY6g3%!7DY5dxmuz;PU+(I`qOj4?Ql zgX1_e&?XZx9M=$rAwdu{vmh3WGMUeF_~1S+SbF{pUH>!uHh+8RP4*6tkZsS<+uhC? z^9Q)}i_6Gv{3G|=aRa~o!+-0nSY2$&4Qb85X;~J=7=#cr_cMtQHj98Urs;qIIy*9K zdSNp!@7TxCf+Uw{6|rf0VxEsOr% zZnBvag+hr~EJ`#Qg)m_M@F5NzK0;S#C)eNkCeR4=MAI8#=9em-TMyG)sbPM*kG`~huPij z#G?vKNW=5M7^DCTdzuqM2_d8q7D_3S$vBSNAP5DPwCS7O&3|COLI}`0#BF#~9hX|Y zf$MrWu7~USctO~zejZ~JdEOlz=hdBY=Jxe4t1C;=hD0=i9|VBGl9E7&7-N)j8(ytc zoTTRZ^!Co7QgslPL>veVwoyD?cOBp&NLZi{Z5+Cu< zBwA@F1ePU`mT2`8g9!~f45>GKD%Co%c#MJrue`dQsj+tmboghbb+~8SwynP!JayiU zp69Xf^hHE$)jFJ-6Ba+sI-pST3}rXu~G%n;$ sFc_p|`IeN2tF`)z6B84!O~3r_08`-jYu|YytpET307*qoM6N<$g2NsZWB>pF delta 1777 zcmV z$3Jg6p->W`xV9mnJUpbKBw=g?w+J=aB;Cd=>oQH6KNMs$`*wHC%k21Oc56!!2}qA^ zJ&Kq9p?E0bNpkSu$sR-k*6Jk)9;*n&LN8L*!|b04ZE1fn@PB!~-|u~Ye+C{5d|M7f zZAsV+V&mp>a%FW*?*D}Wh8P4Wdr>%DDir|AVW`<_0v`W{0Jt~tjQERe$gHfcfsjC^ zmhjs^Wi+P-<8!hnY0-%z{%HP-%owtS_F4)!{O1sZ)_M|TZZl9 zecvM&0f<98QT6z-WNU*t82F>zel!aEzkny#+U@^twA)W^!oFSjL3>Tp>h4(l3`xJ; zoo~BcdLAb;0g#33r(yX3EPM`M{s~9EfmgqS(hw}3z<>IT?iZ_1Vt|=Oc)|F!dMuAQ z&O35C47HN;fj2oW%UVn0*XnU3jf#|Msmdgqy6JW59Rvnduyh6(1?y84&2?C8Rm!sq zz$A#jDr$BP7zgon)ju^4i~+kPM|J zb6x*O<$w1}zz7I;qp{!uhrpV;SYKRDSm=xOnPP{3HBEO3coVE!p)M7Y-mD*4MWgTu zPy|R^^5mEx#L%FMkB`PDk0L-}@QK)XW~Qc;Vo9C{1U$gt^D#{n5|^{&ifoPd6r}UJ z^N(}ix$fL@{=PcW9P3B6%!j_WbLAl=6sD)!iGOx_O7uM%Orz1%P;B;Qic+1Xx~m3P zNBTP@xx+|NtjSN0qBTlT!2wND`J_v|VAq&;hA?RV`$@5T}VKIc&wBFbn2E+F^( zzkhBn$=d=zCa(fzd{4UhoGh6})z>QZ%)KD|lJ-Bia1GyYDSE~L001CkNK#Dz0Bx86 z0CSE20P;=%0EHd^0B()|0OdUZ05dKC02tA|5{Q2Q00VkSL_t(|+QgSlY#T)whM)cM zf12j+P(+e#n^vmez=az`@ z!QsQSR^XHzS8bL+1^(J0TBJl41pva8N;3p1@K^f?2^ZHYBi-Hkdmct$q`k{GdTOYT zpe+yu2iF$3YY7B>+B_iZoZkV@0q73{kGy<lPJ2T{E$)UgSQrm}F) zId=ZN-vOrdE#ZR)2<9C`v0Q@#NPox0EtI#Bxk68O2;kU*5~#pW?I&QC5Y|TcPKUHb z?fZTLZ?<>&&h|$P{L95%hXWf9uzo-Iz<`1GZwpb_eK-J{2vp$xy?E{x5Cx|(@J$jp z+TP_mI}kDOWb=r8xWqA4gIb@Qt@8a7I?>11Z=O6L9N6}0%+ z!f+(gOF-rkt4{3%s{tLo(~lO?>ylGEDybrrh5UZgVpNs*^5;zK1x3;0@zhYHzZV~7 zO+s(?@yS%0+>%{)3T9FKYT06J%eFi=o%93yjvw83`td`1UgJLgL^qQ zafgeSZx7C;t!y290c3!ADP?Y}hNJ|fKc7jD9tSNxaeJ`;#U4D1tF Date: Mon, 15 Feb 2016 14:26:34 +0100 Subject: [PATCH 098/243] New previous/next page icons (kept old ones for web browser back/forward) --- resources/OpenBoard.qrc | 4 ++-- resources/forms/mainWindow.ui | 6 ++---- resources/images/toolbar/next.png | Bin 0 -> 1803 bytes resources/images/toolbar/nextPage.png | Bin 2311 -> 0 bytes resources/images/toolbar/nextPageOn.png | Bin 2245 -> 1665 bytes resources/images/toolbar/previous.png | Bin 0 -> 1813 bytes resources/images/toolbar/previousPage.png | Bin 2260 -> 0 bytes resources/images/toolbar/previousPageOn.png | Bin 2199 -> 1648 bytes 8 files changed, 4 insertions(+), 6 deletions(-) create mode 100644 resources/images/toolbar/next.png delete mode 100644 resources/images/toolbar/nextPage.png mode change 100644 => 100755 resources/images/toolbar/nextPageOn.png create mode 100644 resources/images/toolbar/previous.png delete mode 100644 resources/images/toolbar/previousPage.png mode change 100644 => 100755 resources/images/toolbar/previousPageOn.png diff --git a/resources/OpenBoard.qrc b/resources/OpenBoard.qrc index e1a44529..07f0d10a 100644 --- a/resources/OpenBoard.qrc +++ b/resources/OpenBoard.qrc @@ -60,9 +60,9 @@ images/toolbar/background.png images/toolbar/documents.png images/toolbar/newPage.png - images/toolbar/nextPage.png + images/toolbar/next.png images/toolbar/nextPageOn.png - images/toolbar/previousPage.png + images/toolbar/previous.png images/toolbar/previousPageOn.png images/toolbar/redo.png images/toolbar/redoOn.png diff --git a/resources/forms/mainWindow.ui b/resources/forms/mainWindow.ui index a56f509d..c08f3b8b 100644 --- a/resources/forms/mainWindow.ui +++ b/resources/forms/mainWindow.ui @@ -456,8 +456,7 @@
- - :/images/toolbar/previousPageOn.png:/images/toolbar/previousPageOn.png + Back @@ -471,8 +470,7 @@ - - :/images/toolbar/nextPageOn.png:/images/toolbar/nextPageOn.png + Forward diff --git a/resources/images/toolbar/next.png b/resources/images/toolbar/next.png new file mode 100644 index 0000000000000000000000000000000000000000..0c7989e5cd3c380cb2788ee36edad1da879aa5bc GIT binary patch literal 1803 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 h{!+QTcWV3}0|3ykApmy5cJ-n)C9xw~h3ce#DZ zX{K}Tf1J59-+=dJ{s(b(9ymc(m}M8ajWY$K9vWGN9XNs=^4PaUnTt$k!0#MAm} zdPWmkY|ymW$)%+$iV7Eb=}pId672 z96vs_Z4bQ5N>Q=044%AP(n}f6vM)o%MLhs-e@+P$6M-<9$(4kP{INy&^Li)xx&yd$ z@pmYST0vStjzl^Fx~841+rAI$YO1lV_Ho2wF&KuCCN?Xc6Nv=5m(dmpqbdJsz?IB1s^T+rFGsd)g-;$E0IXUhE)48T;oHx^;;8yD_OVHnL ze^)d9i4CJX?uU}_kP1iae$t_1hw>~MHf=zeuM+Wie1otjlAI?ya^QA3g?!%J1t-o< zo`QF5IlZIL`rfeT7F=!*MRGb~0szv*FslihMXHU(iN&ak)MCZ(Y8!=VkzJjp0Zgkc ze5O(<4Mc{q@zQ2`d3tyAvGhOyxF|hJe;)SUdl^mVcVlgEJ^9q;u?fSY92g+`L(S>%az z@Lj+ZjYiE&NpQZP1Zld4Z(sQgp9GFjO*m5klEr8^0AG+UJWc}>17Vske*n%u?DmFnVe};BHn;-P`Cbx{QcCWgbbxk-)01s^q5{ry)XQb5GeeBF-a+*2=}4i2NMtiIQ(&n9))jfr=E9Chg;n>Zcr)HFe>jRgbVF)WI=put zMkqXz>;pEZAQQkWH6WY_r~F-*EfZ_CleKu^m)EfQuSTrCQH79)0B{6s0NAF$+6P1p za2;4l)PkrF!C79c6ywwSL%2|J2L3;&EtgRda1G2C0Oy#8m0R;Jpnnb+63YVdmV z9^5J#z@k_w5Vns%e>w#wxKs@U0_|+e9CrB^GFA|C!L2ekeXvee_oF1T6l00Ow61A5 z6%PR*oX}$kPepC}KI^iwQ0Iy%}P3WYAv3As)Y8znzx aBl!jmuq delta 2233 zcmV;q2uAmT4aE_VB!3BTNLh0L01FcU01FcV0GgZ_0000WV@Og>004Rm004lS009MJ z004i_002>w009Dx0027=000>uE&;m#000O}NklocA&_yR$np zd+Ci8N=vU;Y7j66q~Zq%fe&CKkOC6q4$%rli9)noMCBf1!hgjWP!dHUL7-qF(V)~8 zY74Yf#BSN{w%gfmXJ>b=@BJJ<%xu{bFr?+5JbCZ$`<(yvc?CykUs>W_KIs{E$8h+> zN3Yqo&6+i9$Y!(nz7K$u5+MYeHf>`2_U#yBTIY|HfbE)ZoOXiqc!zCW%~9A96BsS= z{*9ML+;fHXxPQRD5X5nUPGXEPXsr*y7)`BSKNNoeE8i(+H=ANbpa}~3*^B4R zoA<>eNirCd03gKS{Dd%xapKC@o-dat$6+K5iOu@&H-7IpD_Gmrr?HI-K%xyZNFE{~0Iea>f^t1z z^_hl6v%9F31^GS!T{Z4{#AoB^Ib3}G_i$uLWwL}Z2Bj2<)_BzkcD}Ra?LR*I+?n-y zqiU5KiGR3YmCd44I-!_+e4wVui0OR;RtI54Q5#c8%TOK_E*L5g9$4Y3A@u&N~ZOZPifkKkQx)UGNXLZ z(Cznd&sxRp4?e?9mjwLssb}f#{4m!~UOIs9pMOGe-|$!ev2o+c647!i3FriLVm>v{ z1`~@zkOC@G3BjHMcdzYXfqI_vzji9cgG~UUs1^663y-6B&H#m6Zj}UsFalx)i99;Q z5{aNzPw;l-S$|_c=P%mEcP>4H;o*JQw$tv4;Mgug%B&Ouj1iCsOd>xMNCfpDqQ1S4 zTYqnx!vcF7Yp=NkKW>LkYrtT%maX7uAe0ap5Qd{QBMi!S>0Icu{qN(v_8u%db1{v2 zgH*1gb&oL^K(;blz-O|0fldUXk*2UPVe{~AF1RBhxBOBrzv?=w<*{~Eiy5t07>pL+ zTj)R^<^ge7>3xg|5K7Oe3V{k;3QGe1`hWf)SNZRcs+{7h!Vt<|I z-Wue)j|wik@qX^Q^JXHyL9JHDbzP*CVDw>K)*5T%K6s=0CF%zaf&kA8P)ZWVAyO)o zk{AOu$LQ9r_fD2e2#) z*KM`=v{N`d2V{0(>C|(+$?6L)M1MwAhW6~mO}UiIWzy+1>2w-n3_%c5tJUb~DUj)& z!xN8uo67jp(A7!z@(CV$eUKkLZFAZ6cXI7j7gL=ar?{_)=XqF`g%ASEvgqr{BjgMM zE0!&A8k0o|T^5~AfjRx%D5V%08X}+1lgs5W#?WjwIdI?r^XJb;2*IrW9)H|nU`3hx z{;-Q*yprSQ+aKWSD=#A7-2oVaAYgpFL?+W(NEAg#r4S^C65ER7*4%D-O)|=+UT=y;jZ#3b+U9^s_L$Fg+s@gQ0~Z}Xe~0y{${lL5qsl1xd3 z?|GC;Wo+BV^E|56YFo*)-0689<#HKg3_bmG=vls;Z{7AVikhVT+rj6T9M9a@{p=ndrBd3@>eXLoc+U(?DB7YU(VA(cqO~TDW1=X+7(*C_ z2n?B&O}$oS(P9^HzNU zH6sa{DIF>{S zL&^f>D0;iPaO?tU*QO)wl1aOCWKyJE2g_1mAc|vxFeXYgj_cCdk;ZWxq9_Jql$Fcp zD_*nCWVJ!hF@N2R9VqeMu3`2cm|&_>Lkc*iH%)487RORJj)iMmIF5y5TPUU4Ib(>E zge1{Ki6)G7dy0ux?MsOeFfcGcWF(bx3E%e{*6_&QzX_q(x^)}*+$z%P424|C=jQg2 zNjWGbkx~Gnt@91qn6`2@pFAl)su7IFwry~8Y}@)ayMO-u76&KFuc^Vo-JauENq=6H?*WisIfOHg0_V)$KcWUNU1Ux2#ae zFYC%?&oVMb59mZYANeadN&-R|WBf|Bwxe3D{jR0M;eP`F#-XRivvn#O00000NkvXX Hu0mjf_GdPK diff --git a/resources/images/toolbar/previous.png b/resources/images/toolbar/previous.png new file mode 100644 index 0000000000000000000000000000000000000000..bbcdc40f9872312b13088e03d8e60ea70f50c885 GIT binary patch literal 1813 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

i8Rf1Y_0iDSK;Mq< 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 N07*qoL Date: Mon, 15 Feb 2016 15:27:27 +0100 Subject: [PATCH 099/243] Fixed crash upon saving a pen stroke with an uninitialized strokesGroup --- src/adaptors/UBSvgSubsetAdaptor.cpp | 4 +++- src/domain/UBGraphicsPolygonItem.cpp | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/adaptors/UBSvgSubsetAdaptor.cpp b/src/adaptors/UBSvgSubsetAdaptor.cpp index 21c57dfe..1c05f4ca 100644 --- a/src/adaptors/UBSvgSubsetAdaptor.cpp +++ b/src/adaptors/UBSvgSubsetAdaptor.cpp @@ -1116,8 +1116,9 @@ bool UBSvgSubsetAdaptor::UBSvgSubsetWriter::persistScene(int pageIndex) { QColor colorOnDarkBackground = polygonItem->colorOnDarkBackground(); QColor colorOnLightBackground = polygonItem->colorOnLightBackground(); + UBGraphicsStrokesGroup * sg = polygonItem->strokesGroup(); - if (colorOnDarkBackground.isValid() && colorOnLightBackground.isValid()) + if (colorOnDarkBackground.isValid() && colorOnLightBackground.isValid() && sg) { mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "z-value" , QString("%1").arg(polygonItem->strokesGroup()->zValue())); @@ -1126,6 +1127,7 @@ bool UBSvgSubsetAdaptor::UBSvgSubsetWriter::persistScene(int pageIndex) , "fill-on-dark-background", colorOnDarkBackground.name()); mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri , "fill-on-light-background", colorOnLightBackground.name()); + qDebug() << "Attributes written"; groupHoldsInfo = true; } diff --git a/src/domain/UBGraphicsPolygonItem.cpp b/src/domain/UBGraphicsPolygonItem.cpp index 48530b97..af64c660 100644 --- a/src/domain/UBGraphicsPolygonItem.cpp +++ b/src/domain/UBGraphicsPolygonItem.cpp @@ -40,6 +40,7 @@ UBGraphicsPolygonItem::UBGraphicsPolygonItem (QGraphicsItem * parent) , mOriginalWidth(-1) , mIsNominalLine(false) , mStroke(0) + , mpGroup(NULL) { // NOOP initialize(); @@ -64,6 +65,7 @@ UBGraphicsPolygonItem::UBGraphicsPolygonItem (const QLineF& pLine, qreal pWidth) , mOriginalWidth(pWidth) , mIsNominalLine(true) , mStroke(0) + , mpGroup(NULL) { // NOOP initialize(); @@ -75,6 +77,7 @@ UBGraphicsPolygonItem::UBGraphicsPolygonItem (const QLineF& pLine, qreal pStartW , mOriginalWidth(pEndWidth) , mIsNominalLine(true) , mStroke(0) + , mpGroup(NULL) { // NOOP initialize(); From c65457e962812362e83ff52e6d22f33b67cf111c Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Tue, 16 Feb 2016 14:02:52 +0100 Subject: [PATCH 100/243] Added "preview" dotted circle around eraser tool --- src/board/UBBoardView.cpp | 7 ++++++- src/domain/UBGraphicsScene.cpp | 27 +++++++++++++++++++++------ src/domain/UBGraphicsScene.h | 3 ++- src/gui/UBResources.cpp | 2 +- 4 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/board/UBBoardView.cpp b/src/board/UBBoardView.cpp index 670ee9e3..2d2d29cc 100644 --- a/src/board/UBBoardView.cpp +++ b/src/board/UBBoardView.cpp @@ -1691,9 +1691,14 @@ void UBBoardView::setToolCursor (int tool) controlViewport->setCursor (UBResources::resources ()->penCursor); break; case UBStylusTool::Eraser: + { controlViewport->setCursor (UBResources::resources ()->eraserCursor); - scene()->hideEraser(); + UBStylusTool::Enum currentTool = (UBStylusTool::Enum)UBDrawingController::drawingController()->stylusTool(); + if (currentTool != UBStylusTool::Eraser) + // Avoid hiding the eraser after a click with the eraser + scene()->hideEraser(); break; + } case UBStylusTool::Marker: controlViewport->setCursor (UBResources::resources ()->markerCursor); break; diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index 27bd0560..83d480d8 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -424,7 +424,7 @@ bool UBGraphicsScene::inputDevicePress(const QPointF& scenePos, const qreal& pre eraserWidth /= UBApplication::boardController->currentZoom(); eraseLineTo(scenePos, eraserWidth); - drawEraser(scenePos, true); + drawEraser(scenePos, mInputDeviceIsPressed); accepted = true; } @@ -453,7 +453,7 @@ bool UBGraphicsScene::inputDeviceMove(const QPointF& scenePos, const qreal& pres if (currentTool == UBStylusTool::Eraser) { - drawEraser(position); + drawEraser(position, mInputDeviceIsPressed); accepted = true; } @@ -541,6 +541,12 @@ bool UBGraphicsScene::inputDeviceRelease() accepted = true; } + UBStylusTool::Enum currentTool = (UBStylusTool::Enum)UBDrawingController::drawingController()->stylusTool(); + + if (currentTool == UBStylusTool::Eraser) + redrawEraser(false); + + UBDrawingController *dc = UBDrawingController::drawingController(); if (dc->isDrawingTool() || mDrawWithCompass) @@ -624,7 +630,7 @@ bool UBGraphicsScene::inputDeviceRelease() return accepted; } -void UBGraphicsScene::drawEraser(const QPointF &pPoint, bool isFirstDraw) +void UBGraphicsScene::drawEraser(const QPointF &pPoint, bool pressed) { qreal eraserWidth = UBSettings::settings()->currentEraserWidth(); eraserWidth /= UBApplication::boardController->systemScaleFactor(); @@ -635,10 +641,19 @@ void UBGraphicsScene::drawEraser(const QPointF &pPoint, bool isFirstDraw) // TODO UB 4.x optimize - no need to do that every time we move it if (mEraser) { mEraser->setRect(QRectF(pPoint.x() - eraserRadius, pPoint.y() - eraserRadius, eraserWidth, eraserWidth)); + redrawEraser(pressed); + } +} - if(isFirstDraw) { - mEraser->show(); - } +void UBGraphicsScene::redrawEraser(bool pressed) +{ + if (mEraser) { + if(pressed) + mEraser->setPen(QPen(Qt::SolidLine)); + else + mEraser->setPen(QPen(Qt::DotLine)); + + mEraser->show(); } } diff --git a/src/domain/UBGraphicsScene.h b/src/domain/UBGraphicsScene.h index a114d06c..9a3f009d 100644 --- a/src/domain/UBGraphicsScene.h +++ b/src/domain/UBGraphicsScene.h @@ -359,7 +359,8 @@ public slots: void initPolygonItem(UBGraphicsPolygonItem*); - void drawEraser(const QPointF& pEndPoint, bool isFirstDraw = false); + void drawEraser(const QPointF& pEndPoint, bool pressed = true); + void redrawEraser(bool pressed); void drawPointer(const QPointF& pEndPoint, bool isFirstDraw = false); void DisposeMagnifierQWidgets(); diff --git a/src/gui/UBResources.cpp b/src/gui/UBResources.cpp index 5a974873..9402e238 100644 --- a/src/gui/UBResources.cpp +++ b/src/gui/UBResources.cpp @@ -65,7 +65,7 @@ void UBResources::init() { // Cursors penCursor = QCursor(Qt::CrossCursor); - eraserCursor = QCursor(QPixmap(":/images/cursors/eraser.png"), 21, 21); + eraserCursor = QCursor(QPixmap(":/images/cursors/eraser.png"), 5, 25); markerCursor = QCursor(QPixmap(":/images/cursors/marker.png"), 3, 30); pointerCursor = QCursor(QPixmap(":/images/cursors/laser.png"), 2, 1); handCursor = QCursor(Qt::OpenHandCursor); From 3171da0d39b4a715165df4bf6a4e0d1778725917 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Tue, 16 Feb 2016 14:34:48 +0100 Subject: [PATCH 101/243] Clean-up after last commit (c65457e) --- src/board/UBBoardView.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/board/UBBoardView.cpp b/src/board/UBBoardView.cpp index 2d2d29cc..8e63c31e 100644 --- a/src/board/UBBoardView.cpp +++ b/src/board/UBBoardView.cpp @@ -1691,14 +1691,8 @@ void UBBoardView::setToolCursor (int tool) controlViewport->setCursor (UBResources::resources ()->penCursor); break; case UBStylusTool::Eraser: - { controlViewport->setCursor (UBResources::resources ()->eraserCursor); - UBStylusTool::Enum currentTool = (UBStylusTool::Enum)UBDrawingController::drawingController()->stylusTool(); - if (currentTool != UBStylusTool::Eraser) - // Avoid hiding the eraser after a click with the eraser - scene()->hideEraser(); break; - } case UBStylusTool::Marker: controlViewport->setCursor (UBResources::resources ()->markerCursor); break; From 0879179c73e97ed20b94123f3144054997e7666b Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Wed, 17 Feb 2016 13:40:27 +0100 Subject: [PATCH 102/243] Fixed pen strokes not being loaded in right position - Modified UBvgSubsetAdaptor to correctly save and load strokes, so the transform matrices that were saved are now loaded correctly. - Added handling of mousePress / Move / Release events to UBGraphicsStrokesGroup, so that the transform matrix is calculated and stored after moving a pen stroke directly (by clicking on it, and not on its frame). Note: this duplicates quite a bit of code that is in UBGraphicsDelegateFrame. It may be best to go back and modify both classes so that the same functions can be called when moving a stroke. --- src/adaptors/UBSvgSubsetAdaptor.cpp | 40 ++++++++- src/board/UBBoardView.cpp | 5 +- src/domain/UBGraphicsStrokesGroup.cpp | 123 ++++++++++++++++++++++---- src/domain/UBGraphicsStrokesGroup.h | 28 ++++++ 4 files changed, 175 insertions(+), 21 deletions(-) diff --git a/src/adaptors/UBSvgSubsetAdaptor.cpp b/src/adaptors/UBSvgSubsetAdaptor.cpp index 1c05f4ca..2a93e0fd 100644 --- a/src/adaptors/UBSvgSubsetAdaptor.cpp +++ b/src/adaptors/UBSvgSubsetAdaptor.cpp @@ -498,6 +498,18 @@ UBGraphicsScene* UBSvgSubsetAdaptor::UBSvgSubsetReader::loadScene() { mGroupLightBackgroundColor.setNamedColor(ubFillOnLightBackground.toString()); } + + QStringRef ubUuid = mXmlReader.attributes().value(mNamespaceUri, "uuid"); + + if (!ubUuid.isNull()) + strokesGroup->setUuid(ubUuid.toString()); + else + strokesGroup->setUuid(QUuid::createUuid()); + + QString uuid_stripped = strokesGroup->uuid().toString().replace("}","").replace("{",""); + + if (!mStrokesList.contains(uuid_stripped)) + mStrokesList.insert(uuid_stripped, strokesGroup); } else if (mXmlReader.name() == "polygon" || mXmlReader.name() == "line") { @@ -524,13 +536,15 @@ UBGraphicsScene* UBSvgSubsetAdaptor::UBSvgSubsetReader::loadScene() if(!mStrokesList.contains(parentId)){ group = new UBGraphicsStrokesGroup(); mStrokesList.insert(parentId,group); - currentStroke = new UBGraphicsStroke(); group->setTransform(polygonItem->transform()); UBGraphicsItem::assignZValue(group, polygonItem->zValue()); } else group = mStrokesList.value(parentId); + if (!currentStroke) + currentStroke = new UBGraphicsStroke(); + if(polygonItem->transform().isIdentity()) polygonItem->setTransform(group->transform()); @@ -546,23 +560,33 @@ UBGraphicsScene* UBSvgSubsetAdaptor::UBSvgSubsetReader::loadScene() { QList polygonItems = polygonItemsFromPolylineSvg(mScene->isDarkBackground() ? Qt::white : Qt::black); - QString parentId = QUuid::createUuid().toString(); + QString parentId = mXmlReader.attributes().value(mNamespaceUri, "parent").toString(); + qDebug() << "parentID = " << parentId; + + if(parentId.isEmpty() && strokesGroup) + parentId = strokesGroup->uuid().toString(); + + if(parentId.isEmpty()) + parentId = QUuid::createUuid().toString(); foreach(UBGraphicsPolygonItem* polygonItem, polygonItems) { polygonItem->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Graphic)); UBGraphicsStrokesGroup* group; + if(!mStrokesList.contains(parentId)){ group = new UBGraphicsStrokesGroup(); mStrokesList.insert(parentId,group); - currentStroke = new UBGraphicsStroke(); group->setTransform(polygonItem->transform()); UBGraphicsItem::assignZValue(group, polygonItem->zValue()); } else group = mStrokesList.value(parentId); + if (!currentStroke) + currentStroke = new UBGraphicsStroke(); + if(polygonItem->transform().isIdentity()) polygonItem->setTransform(group->transform()); @@ -861,6 +885,8 @@ UBGraphicsScene* UBSvgSubsetAdaptor::UBSvgSubsetReader::loadScene() mGroupHasInfo = false; mGroupDarkBackgroundColor = QColor(); mGroupLightBackgroundColor = QColor(); + strokesGroup = NULL; + currentStroke = NULL; } } } @@ -1127,6 +1153,9 @@ bool UBSvgSubsetAdaptor::UBSvgSubsetWriter::persistScene(int pageIndex) , "fill-on-dark-background", colorOnDarkBackground.name()); mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri , "fill-on-light-background", colorOnLightBackground.name()); + + mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "uuid", UBStringUtils::toCanonicalUuid(sg->uuid())); + qDebug() << "Attributes written"; groupHoldsInfo = true; @@ -1442,6 +1471,11 @@ void UBSvgSubsetAdaptor::UBSvgSubsetWriter::strokeToSvgPolyline(UBGraphicsStroke , "fill-on-light-background", firstPolygonItem->colorOnLightBackground().name()); } + mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "uuid", UBStringUtils::toCanonicalUuid(firstPolygonItem->uuid())); + if (firstPolygonItem->parentItem()) { + mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "parent", UBStringUtils::toCanonicalUuid(UBGraphicsItem::getOwnUuid(firstPolygonItem->strokesGroup()))); + } + mXmlWriter.writeEndElement(); } } diff --git a/src/board/UBBoardView.cpp b/src/board/UBBoardView.cpp index 8e63c31e..7c5cf039 100644 --- a/src/board/UBBoardView.cpp +++ b/src/board/UBBoardView.cpp @@ -561,7 +561,7 @@ Here we determines cases when items should to get mouse press event at pressing break; case UBGraphicsItemType::StrokeItemType: - if (currentTool == UBStylusTool::Play) + if (currentTool == UBStylusTool::Play || currentTool == UBStylusTool::Selector) return true; break; // Groups shouldn't reacts on any presses and moves for Play tool. @@ -664,7 +664,7 @@ bool UBBoardView::itemShouldBeMoved(QGraphicsItem *item) return false; case UBGraphicsMediaItem::Type: case UBGraphicsStrokesGroup::Type: - return true; + return false; case UBGraphicsTextItem::Type: return !item->isSelected(); } @@ -1254,6 +1254,7 @@ void UBBoardView::mouseReleaseEvent (QMouseEvent *event) if (isUBItem(movingItem) && DelegateButton::Type != movingItem->type() && UBGraphicsDelegateFrame::Type != movingItem->type() && + UBGraphicsStrokesGroup::Type != movingItem->type() && UBGraphicsCache::Type != movingItem->type() && QGraphicsWebView::Type != movingItem->type() && // for W3C widgets as Tools. !(!isMultipleSelectionEnabled() && movingItem->parentItem() && UBGraphicsWidgetItem::Type == movingItem->type() && UBGraphicsGroupContainerItem::Type == movingItem->parentItem()->type())) diff --git a/src/domain/UBGraphicsStrokesGroup.cpp b/src/domain/UBGraphicsStrokesGroup.cpp index e5aa0884..a6dbc2a8 100644 --- a/src/domain/UBGraphicsStrokesGroup.cpp +++ b/src/domain/UBGraphicsStrokesGroup.cpp @@ -111,30 +111,44 @@ QColor UBGraphicsStrokesGroup::color(colorType pColorType) const void UBGraphicsStrokesGroup::mousePressEvent(QGraphicsSceneMouseEvent *event) { - if (Delegate()->mousePressEvent(event)) - { - //NOOP - } - else - { -// QGraphicsItemGroup::mousePressEvent(event); - } + Delegate()->startUndoStep(); + + mStartingPoint = event->scenePos(); + + initializeTransform(); + + mTranslateX = 0; + mTranslateY = 0; + mAngleOffset = 0; + + mInitialTransform = buildTransform(); + + event->accept(); } void UBGraphicsStrokesGroup::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { - if (Delegate()->mouseMoveEvent(event)) - { - // NOOP; - } - else - { - QGraphicsItemGroup::mouseMoveEvent(event); - } + QLineF move = QLineF(mStartingPoint, event->scenePos()); + + mTranslateX = move.dx(); + mTranslateY = move.dy(); + //Delegate()->frame()->moveLinkedItems(move); + + setTransform(buildTransform()); + + event->accept(); + } void UBGraphicsStrokesGroup::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { + Delegate()->commitUndoStep(); + + mTotalTranslateX += mTranslateX; + mTotalTranslateY += mTranslateY; + + event->accept(); + Delegate()->mouseReleaseEvent(event); QGraphicsItemGroup::mouseReleaseEvent(event); } @@ -226,3 +240,80 @@ QPainterPath UBGraphicsStrokesGroup::shape() const return path; } + +void UBGraphicsStrokesGroup::initializeTransform() +{ + + QTransform itemTransform = sceneTransform(); + QRectF itemRect = boundingRect(); + QPointF topLeft = itemTransform.map(itemRect.topLeft()); + QPointF topRight = itemTransform.map(itemRect.topRight()); + QPointF bottomLeft = itemTransform.map(itemRect.bottomLeft()); + + qreal horizontalFlip = (topLeft.x() > topRight.x()) ? -1 : 1; + mMirrorX = horizontalFlip < 0 ; + if(horizontalFlip < 0){ + // why this is because of the way of calculating the translations that checks which side is the most is the + // nearest instead of checking which one is the left side. + QPointF tmp = topLeft; + topLeft = topRight; + topRight = tmp; + + // because of the calculation of the height is done by lenght and not deltaY + bottomLeft = itemTransform.map(itemRect.bottomRight()); + } + + qreal verticalFlip = (bottomLeft.y() < topLeft.y()) ? -1 : 1; + // not sure that is usefull + mMirrorY = verticalFlip < 0; + if(verticalFlip < 0 && !mMirrorX){ + topLeft = itemTransform.map(itemRect.bottomLeft()); + topRight = itemTransform.map(itemRect.bottomRight()); + bottomLeft = itemTransform.map(itemRect.topLeft()); + } + + QLineF topLine(topLeft, topRight); + QLineF leftLine(topLeft, bottomLeft); + qreal width = topLine.length(); + qreal height = leftLine.length(); + + mAngle = topLine.angle(); + + // the fact the the length is used we loose the horizontalFlip information + // a better way to do this is using DeltaX that preserve the direction information. + mTotalScaleX = (width / itemRect.width()) * horizontalFlip; + mTotalScaleY = height / itemRect.height() * verticalFlip; + + + + QTransform tr; + QPointF center = boundingRect().center(); + tr.translate(center.x() * mTotalScaleX, center.y() * mTotalScaleY); + tr.rotate(-mAngle); + tr.translate(-center.x() * mTotalScaleX, -center.y() * mTotalScaleY); + tr.scale(mTotalScaleX, mTotalScaleY); + + mTotalTranslateX = transform().dx() - tr.dx(); + mTotalTranslateY = transform().dy() - tr.dy(); + + +} + +QTransform UBGraphicsStrokesGroup::buildTransform() +{ + QTransform tr; + QPointF center = boundingRect().center(); + + // Translate + tr.translate(mTotalTranslateX + mTranslateX, mTotalTranslateY + mTranslateY); + + // Set angle + tr.translate(center.x() * mTotalScaleX, center.y() * mTotalScaleY); + tr.rotate(-mAngle); + tr.translate(-center.x() * mTotalScaleX, -center.y() * mTotalScaleY); + + // Scale + tr.scale(mTotalScaleX, mTotalScaleY ); + + return tr; +} diff --git a/src/domain/UBGraphicsStrokesGroup.h b/src/domain/UBGraphicsStrokesGroup.h index 5ddf789e..545c8c9d 100644 --- a/src/domain/UBGraphicsStrokesGroup.h +++ b/src/domain/UBGraphicsStrokesGroup.h @@ -66,6 +66,34 @@ protected: virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value); + + private: + qreal mTranslateX; + qreal mTranslateY; + qreal mTotalTranslateX; + qreal mTotalTranslateY; + + qreal mAngle; + qreal mAngleOffset; + + qreal mTotalScaleX; + qreal mTotalScaleY; + qreal mScaleX; + qreal mScaleY; + + bool mFlippedX; + bool mFlippedY; + bool mMirrorX; + bool mMirrorY; + bool mResizing; + bool mMirroredXAtStart; + bool mMirroredYAtStart; + + QPointF mStartingPoint; + QTransform mInitialTransform; + + QTransform buildTransform (); + void initializeTransform (); }; #endif // UBGRAPHICSSTROKESGROUP_H From c619a9db709ecfa43220a6afe2951655d2e40896 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Wed, 17 Feb 2016 15:53:44 +0100 Subject: [PATCH 103/243] Removed forgotten debug message --- src/adaptors/UBSvgSubsetAdaptor.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/adaptors/UBSvgSubsetAdaptor.cpp b/src/adaptors/UBSvgSubsetAdaptor.cpp index 2a93e0fd..b3126501 100644 --- a/src/adaptors/UBSvgSubsetAdaptor.cpp +++ b/src/adaptors/UBSvgSubsetAdaptor.cpp @@ -561,7 +561,6 @@ UBGraphicsScene* UBSvgSubsetAdaptor::UBSvgSubsetReader::loadScene() QList polygonItems = polygonItemsFromPolylineSvg(mScene->isDarkBackground() ? Qt::white : Qt::black); QString parentId = mXmlReader.attributes().value(mNamespaceUri, "parent").toString(); - qDebug() << "parentID = " << parentId; if(parentId.isEmpty() && strokesGroup) parentId = strokesGroup->uuid().toString(); From 8e9327fb4209fb39749caedcf2b7616cf098232e Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Thu, 18 Feb 2016 10:50:46 +0100 Subject: [PATCH 104/243] Fixed copying of Qt libs to .deb package --- buildDebianPackage.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/buildDebianPackage.sh b/buildDebianPackage.sh index 5251cf17..97c1edc7 100755 --- a/buildDebianPackage.sh +++ b/buildDebianPackage.sh @@ -98,8 +98,9 @@ checkExecutable(){ copyQtLibrary(){ if ls "$QT_LIBRARY_SOURCE_PATH/$1.so" &> /dev/null; then - cp $QT_LIBRARY_SOURCE_PATH/$1.so.? "$QT_LIBRARY_DEST_PATH/" - cp $QT_LIBRARY_SOURCE_PATH/$1.so.?.?.? "$QT_LIBRARY_DEST_PATH/" + cp -P $QT_LIBRARY_SOURCE_PATH/$1.so.? "$QT_LIBRARY_DEST_PATH/" + cp -P $QT_LIBRARY_SOURCE_PATH/$1.so.?.? "$QT_LIBRARY_DEST_PATH/" + cp -P $QT_LIBRARY_SOURCE_PATH/$1.so.?.?.? "$QT_LIBRARY_DEST_PATH/" else notifyError "$1 library not found in path: $QT_LIBRARY_SOURCE_PATH" fi From 82983ca2a657f7e0fc7eef8c25bb6674cb680bff Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Thu, 18 Feb 2016 10:51:36 +0100 Subject: [PATCH 105/243] Updated version number (1.10a8) --- OpenBoard.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenBoard.pro b/OpenBoard.pro index cd13a96d..d08951c9 100644 --- a/OpenBoard.pro +++ b/OpenBoard.pro @@ -11,7 +11,7 @@ CONFIG += debug_and_release \ VERSION_MAJ = 1 VERSION_MIN = 10 VERSION_TYPE = a # a = alpha, b = beta, rc = release candidate, r = release, other => error -VERSION_PATCH = 7 +VERSION_PATCH = 8 VERSION = "$${VERSION_MAJ}.$${VERSION_MIN}.$${VERSION_TYPE}.$${VERSION_PATCH}" VERSION = $$replace(VERSION, "\\.r", "") From dd24e3ada3d322394ba3233e4322b563a89683c6 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Thu, 18 Feb 2016 12:43:40 +0100 Subject: [PATCH 106/243] Don't update color palette when Selector tool is picked This makes it possible e.g to use the colorPicker app in conjunction with the compass. Colors will still be updated when one clicks the pen or marker tools. --- src/board/UBDrawingController.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/board/UBDrawingController.cpp b/src/board/UBDrawingController.cpp index 8d103dd7..318a0d08 100644 --- a/src/board/UBDrawingController.cpp +++ b/src/board/UBDrawingController.cpp @@ -147,7 +147,8 @@ void UBDrawingController::setStylusTool(int tool) UBApplication::mainWindow->actionCapture->setChecked(true); emit stylusToolChanged(tool); - emit colorPaletteChanged(); + if (mStylusTool != UBStylusTool::Selector) + emit colorPaletteChanged(); } } From e9398f55ee8afd441ccab12adc17453413268acd Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Thu, 18 Feb 2016 15:31:35 +0100 Subject: [PATCH 107/243] Compass: replaced hard-coded constants in drawing methods The size of the various parts of the compass can now be easily modified --- src/tools/UBGraphicsCompass.cpp | 100 +++++++++++++++++--------------- src/tools/UBGraphicsCompass.h | 18 +++++- 2 files changed, 69 insertions(+), 49 deletions(-) diff --git a/src/tools/UBGraphicsCompass.cpp b/src/tools/UBGraphicsCompass.cpp index 660025c4..cfedb870 100644 --- a/src/tools/UBGraphicsCompass.cpp +++ b/src/tools/UBGraphicsCompass.cpp @@ -144,7 +144,7 @@ void UBGraphicsCompass::paint(QPainter *painter, const QStyleOptionGraphicsItem resizeButtonRect().center().y() - mResizeSvgItem->boundingRect().height() * mAntiScaleRatio / 2); painter->setPen(drawColor()); - painter->drawRoundedRect(hingeRect(), 4, 4); + painter->drawRoundedRect(hingeRect(), sCornerRadius, sCornerRadius); painter->fillPath(hingeShape(), middleFillColor()); painter->fillPath(needleShape(), middleFillColor()); @@ -615,28 +615,30 @@ QPainterPath UBGraphicsCompass::needleShape() const { QPainterPath path; path.moveTo(rect().left(), rect().center().y()); - path.lineTo(rect().left() + sNeedleLength, rect().center().y() - 2); - path.lineTo(rect().left() + sNeedleLength, rect().center().y() + 2); + path.lineTo(rect().left() + sNeedleLength, rect().center().y() - sNeedleWidth/2); + path.lineTo(rect().left() + sNeedleLength, rect().center().y() + sNeedleWidth/2); path.closeSubpath(); return path; } QPainterPath UBGraphicsCompass::needleBaseShape() const { + int smallHalfSide = sNeedleBaseWidth/2 - sCornerRadius; + QPainterPath path; - path.moveTo(rect().left() + sNeedleLength, rect().center().y() - 4); + path.moveTo(rect().left() + sNeedleLength, rect().center().y() - smallHalfSide); path.arcTo( rect().left() + sNeedleLength, - rect().center().y() - 8, - 8, 8, + rect().center().y() - smallHalfSide - sCornerRadius, + sCornerRadius*2, sCornerRadius*2, 180, -90); - path.lineTo(rect().left() + sNeedleLength + sNeedleBaseLength, rect().center().y() - 8); - path.lineTo(rect().left() + sNeedleLength + sNeedleBaseLength, rect().center().y() + 8); - path.lineTo(rect().left() + sNeedleLength + 4, rect().center().y() + 8); + path.lineTo(rect().left() + sNeedleLength + sNeedleBaseLength, rect().center().y() - sNeedleBaseWidth/2); + path.lineTo(rect().left() + sNeedleLength + sNeedleBaseLength, rect().center().y() + sNeedleBaseWidth/2); + path.lineTo(rect().left() + sNeedleLength + sCornerRadius, rect().center().y() + smallHalfSide + sCornerRadius); path.arcTo( rect().left() + sNeedleLength, - rect().center().y(), - 8, 8, + rect().center().y() + smallHalfSide - sCornerRadius, + sCornerRadius*2, sCornerRadius*2, -90, -90); path.closeSubpath(); @@ -645,20 +647,22 @@ QPainterPath UBGraphicsCompass::needleBaseShape() const QPainterPath UBGraphicsCompass::needleArmShape() const { + int smallHalfSide = sNeedleArmLeftWidth/2 - sCornerRadius; + QPainterPath path; - path.moveTo(rect().left() + sNeedleLength + sNeedleBaseLength, rect().center().y() - 8); + path.moveTo(rect().left() + sNeedleLength + sNeedleBaseLength, rect().center().y() - smallHalfSide); path.arcTo( rect().left() + sNeedleLength + sNeedleBaseLength, - rect().center().y() - 12, - 8, 8, + rect().center().y() - sNeedleArmLeftWidth/2, + sCornerRadius*2, sCornerRadius*2, 180, -90); - path.lineTo(hingeRect().left(), rect().center().y() - 16); - path.lineTo(hingeRect().left(), rect().center().y() + 16); - path.lineTo(rect().left() + sNeedleLength + sNeedleBaseLength + 4, rect().center().y() + 12); + path.lineTo(hingeRect().left(), rect().center().y() - sNeedleArmRigthWidth/2); + path.lineTo(hingeRect().left(), rect().center().y() + sNeedleArmRigthWidth/2); + path.lineTo(rect().left() + sNeedleLength + sNeedleBaseLength + sCornerRadius, rect().center().y() + sNeedleArmLeftWidth/2); path.arcTo( rect().left() + sNeedleLength + sNeedleBaseLength, - rect().center().y() + 4, - 8, 8, + rect().center().y() + smallHalfSide - sCornerRadius, + sCornerRadius*2, sCornerRadius*2, -90, -90); path.closeSubpath(); return path; @@ -667,30 +671,30 @@ QPainterPath UBGraphicsCompass::needleArmShape() const QPainterPath UBGraphicsCompass::hingeShape() const { QPainterPath path; - path.moveTo(hingeRect().left() + 4, hingeRect().top()); - path.lineTo(hingeRect().right() - 4, hingeRect().top()); + path.moveTo(hingeRect().left() + sCornerRadius, hingeRect().top()); + path.lineTo(hingeRect().right() - sCornerRadius, hingeRect().top()); path.arcTo( - hingeRect().right() - 8, + hingeRect().right() - sCornerRadius*2, hingeRect().top(), - 8, 8, + sCornerRadius*2, sCornerRadius*2, 90, -90); - path.lineTo(hingeRect().right(), hingeRect().bottom() - 4); + path.lineTo(hingeRect().right(), hingeRect().bottom() - sCornerRadius); path.arcTo( - hingeRect().right() - 8, - hingeRect().bottom() - 8, - 8, 8, + hingeRect().right() - sCornerRadius*2, + hingeRect().bottom() - sCornerRadius*2, + sCornerRadius*2, sCornerRadius*2, 0, -90); - path.lineTo(hingeRect().left() + 4, hingeRect().bottom()); + path.lineTo(hingeRect().left() + sCornerRadius, hingeRect().bottom()); path.arcTo( hingeRect().left(), - hingeRect().bottom() - 8, - 8, 8, + hingeRect().bottom() - sCornerRadius*2, + sCornerRadius*2, sCornerRadius*2, -90, -90); - path.lineTo(hingeRect().left(), hingeRect().top() + 4); + path.lineTo(hingeRect().left(), hingeRect().top() + sCornerRadius); path.arcTo( hingeRect().left(), hingeRect().top(), - 8, 8, + sCornerRadius*2, sCornerRadius*2, -180, -90); path.closeSubpath(); return path; @@ -713,18 +717,18 @@ QPainterPath UBGraphicsCompass::pencilShape() const QPainterPath UBGraphicsCompass::pencilBaseShape() const { QPainterPath path; - path.moveTo(rect().right() - sPencilLength - sPencilBaseLength, rect().center().y() - 8); - path.lineTo(rect().right() - sPencilLength - 4, rect().center().y() - 8); + path.moveTo(rect().right() - sPencilLength - sPencilBaseLength, rect().center().y() - sPencilBaseWidth/2); + path.lineTo(rect().right() - sPencilLength - sCornerRadius, rect().center().y() - sPencilBaseWidth/2); path.arcTo( - rect().right() - sPencilLength - 8, rect().center().y() - 8, - 8, 8, + rect().right() - sPencilLength - sCornerRadius*2, rect().center().y() - sPencilBaseWidth/2, + sCornerRadius*2, sCornerRadius*2, 90, -90); - path.lineTo(rect().right() - sPencilLength, rect().center().y() + 4); + path.lineTo(rect().right() - sPencilLength, rect().center().y() + sPencilBaseWidth/2 - sCornerRadius); path.arcTo( - rect().right() - sPencilLength - 8, rect().center().y(), - 8, 8, + rect().right() - sPencilLength - sCornerRadius*2, rect().center().y() + sPencilBaseWidth/2 - sCornerRadius*2, + sCornerRadius*2, sCornerRadius*2, 0, -90); - path.lineTo(rect().right() - sPencilLength - sPencilBaseLength, rect().center().y() + 8); + path.lineTo(rect().right() - sPencilLength - sPencilBaseLength, rect().center().y() + sPencilBaseWidth/2); path.closeSubpath(); return path; @@ -733,18 +737,18 @@ QPainterPath UBGraphicsCompass::pencilBaseShape() const QPainterPath UBGraphicsCompass::pencilArmShape() const { QPainterPath path; - path.moveTo(hingeRect().right(), rect().center().y() - 16); - path.lineTo(rect().right() - sPencilLength - sPencilBaseLength - 4, rect().center().y() - 12); + path.moveTo(hingeRect().right(), rect().center().y() - sPencilArmLeftWidth/2); + path.lineTo(rect().right() - sPencilLength - sPencilBaseLength - sCornerRadius, rect().center().y() - sPencilArmRightWidth/2); path.arcTo( - rect().right() - sPencilLength - sPencilBaseLength - 8, rect().center().y() - 12, - 8, 8, + rect().right() - sPencilLength - sPencilBaseLength - sCornerRadius*2, rect().center().y() - sPencilArmRightWidth/2, + sCornerRadius*2, sCornerRadius*2, 90, -90); - path.lineTo(rect().right() - sPencilLength - sPencilBaseLength, rect().center().y() + 8); + path.lineTo(rect().right() - sPencilLength - sPencilBaseLength, rect().center().y() + sPencilArmRightWidth/2 - sCornerRadius); path.arcTo( - rect().right() - sPencilLength - sPencilBaseLength - 8, rect().center().y() + 4, - 8, 8, + rect().right() - sPencilLength - sPencilBaseLength - sCornerRadius*2, rect().center().y() + sPencilArmRightWidth/2 - sCornerRadius*2, + sCornerRadius*2, sCornerRadius*2, 0, -90); - path.lineTo(hingeRect().right(), rect().center().y() + 16); + path.lineTo(hingeRect().right(), rect().center().y() + sPencilArmLeftWidth/2); path.closeSubpath(); return path; } diff --git a/src/tools/UBGraphicsCompass.h b/src/tools/UBGraphicsCompass.h index 651bc455..425a789e 100644 --- a/src/tools/UBGraphicsCompass.h +++ b/src/tools/UBGraphicsCompass.h @@ -124,11 +124,27 @@ class UBGraphicsCompass: public QObject, public QGraphicsRectItem, public UBItem int mPixelsPerMillimeter; // Constants - static const QRect sDefaultRect; static const int sNeedleLength = 24; + static const int sNeedleWidth = 4; + static const int sNeedleBaseLength = 16; + static const int sNeedleBaseWidth = 16; + + static const int sNeedleArmLeftWidth = 24; + static const int sNeedleArmRigthWidth = 32; + static const int sPencilLength = 16; + static const int sPencilWidth = 4; + static const int sPencilBaseLength = 24; + static const int sPencilBaseWidth = 16; + + static const int sPencilArmLeftWidth = 32; + static const int sPencilArmRightWidth = 24; + + static const int sCornerRadius = 4; + + static const QRect sDefaultRect; static const int sMinRadius; static const int sDegreeToQtAngleUnit = 16; static const int sFillTransparency = 127; From 75a23aa76f1a8a291df55d2ff84142f7d40914fb Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Thu, 18 Feb 2016 15:39:27 +0100 Subject: [PATCH 108/243] Shrunk compass size by 25% --- src/tools/UBGraphicsCompass.cpp | 4 ++-- src/tools/UBGraphicsCompass.h | 26 +++++++++++++------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/tools/UBGraphicsCompass.cpp b/src/tools/UBGraphicsCompass.cpp index cfedb870..0bdc58a1 100644 --- a/src/tools/UBGraphicsCompass.cpp +++ b/src/tools/UBGraphicsCompass.cpp @@ -37,7 +37,7 @@ #include "core/memcheck.h" -const QRect UBGraphicsCompass::sDefaultRect = QRect(0, -20, 300, 48); +const QRect UBGraphicsCompass::sDefaultRect = QRect(0, -20, 300, 36); const QColor UBGraphicsCompass::sLightBackgroundMiddleFillColor = QColor(0x72, 0x72, 0x72, sFillTransparency); const QColor UBGraphicsCompass::sLightBackgroundEdgeFillColor = QColor(0xc3, 0xc3, 0xc3, sFillTransparency); const QColor UBGraphicsCompass::sLightBackgroundDrawColor = QColor(0x33, 0x33, 0x33, sDrawTransparency); @@ -46,7 +46,7 @@ const QColor UBGraphicsCompass::sDarkBackgroundEdgeFillColor = QColor(0xdd, 0xdd const QColor UBGraphicsCompass::sDarkBackgroundDrawColor = QColor(0xff, 0xff, 0xff, sDrawTransparency); const int UBGraphicsCompass::sMinRadius = UBGraphicsCompass::sNeedleLength + UBGraphicsCompass::sNeedleBaseLength - + 32 + UBGraphicsCompass::sDefaultRect.height() + 32 + UBGraphicsCompass::sPencilBaseLength + + 24 + UBGraphicsCompass::sDefaultRect.height() + 24 + UBGraphicsCompass::sPencilBaseLength + UBGraphicsCompass::sPencilLength; UBGraphicsCompass::UBGraphicsCompass() diff --git a/src/tools/UBGraphicsCompass.h b/src/tools/UBGraphicsCompass.h index 425a789e..0962bbac 100644 --- a/src/tools/UBGraphicsCompass.h +++ b/src/tools/UBGraphicsCompass.h @@ -124,25 +124,25 @@ class UBGraphicsCompass: public QObject, public QGraphicsRectItem, public UBItem int mPixelsPerMillimeter; // Constants - static const int sNeedleLength = 24; - static const int sNeedleWidth = 4; + static const int sNeedleLength = 18; + static const int sNeedleWidth = 3; - static const int sNeedleBaseLength = 16; - static const int sNeedleBaseWidth = 16; + static const int sNeedleBaseLength = 12; + static const int sNeedleBaseWidth = 12; - static const int sNeedleArmLeftWidth = 24; - static const int sNeedleArmRigthWidth = 32; + static const int sNeedleArmLeftWidth = 18; + static const int sNeedleArmRigthWidth = 24; - static const int sPencilLength = 16; - static const int sPencilWidth = 4; + static const int sPencilLength = 12; + static const int sPencilWidth = 3; - static const int sPencilBaseLength = 24; - static const int sPencilBaseWidth = 16; + static const int sPencilBaseLength = 18; + static const int sPencilBaseWidth = 12; - static const int sPencilArmLeftWidth = 32; - static const int sPencilArmRightWidth = 24; + static const int sPencilArmLeftWidth = 24; + static const int sPencilArmRightWidth = 18; - static const int sCornerRadius = 4; + static const int sCornerRadius = 3; static const QRect sDefaultRect; static const int sMinRadius; From 2356656f5c87fb50fb2c2a0de286b2849cf62453 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Mon, 22 Feb 2016 11:56:13 +0100 Subject: [PATCH 109/243] Added missing semicolon to .desktop entry --- buildDebianPackage.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildDebianPackage.sh b/buildDebianPackage.sh index 97c1edc7..8cd2bddc 100755 --- a/buildDebianPackage.sh +++ b/buildDebianPackage.sh @@ -409,7 +409,7 @@ echo "Icon=/usr/local/$APPLICATION_DIRECTORY_NAME/${APPLICATION_NAME}.png" >> $A echo "StartupNotify=true" >> $APPLICATION_SHORTCUT echo "Terminal=false" >> $APPLICATION_SHORTCUT echo "Type=Application" >> $APPLICATION_SHORTCUT -echo "Categories=Education" >> $APPLICATION_SHORTCUT +echo "Categories=Education;" >> $APPLICATION_SHORTCUT cp "resources/images/${APPLICATION_NAME}.png" "$PACKAGE_DIRECTORY/${APPLICATION_NAME}.png" chmod 755 "$BASE_WORKING_DIR/DEBIAN" chmod 755 "$BASE_WORKING_DIR/DEBIAN/prerm" From 61e898acc6d6dc2de683a3aa1da1eb64867f25c8 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Mon, 22 Feb 2016 11:58:29 +0100 Subject: [PATCH 110/243] Added support for deleting multiple documents --- src/document/UBDocumentController.cpp | 298 +++++++++++++++++++------- src/document/UBDocumentController.h | 15 +- 2 files changed, 230 insertions(+), 83 deletions(-) diff --git a/src/document/UBDocumentController.cpp b/src/document/UBDocumentController.cpp index a5a6685c..87042f6c 100644 --- a/src/document/UBDocumentController.cpp +++ b/src/document/UBDocumentController.cpp @@ -263,9 +263,13 @@ UBDocumentGroupTreeItem* UBDocumentController::selectedDocumentGroupTreeItem() void UBDocumentController::itemSelectionChanged() { + updateCurrentSelection(); + reloadThumbnails(); - if (selectedDocumentProxy()) + if (multipleSelection()) + mSelectionType = Multiple; + else if (selectedDocumentProxy()) mSelectionType = Document; else if (selectedDocumentGroupTreeItem()) mSelectionType = Folder; @@ -366,7 +370,7 @@ void UBDocumentController::setupViews() loadDocumentProxies(); - mDocumentUI->documentTreeWidget->setSelectionMode(QAbstractItemView::SingleSelection); + mDocumentUI->documentTreeWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); mDocumentUI->documentTreeWidget->setDragEnabled(true); mDocumentUI->documentTreeWidget->viewport()->setAcceptDrops(true); mDocumentUI->documentTreeWidget->setDropIndicatorShown(true); @@ -695,90 +699,121 @@ void UBDocumentController::moveFolderToTrash(UBDocumentGroupTreeItem* groupTi) reloadThumbnails(); } -void UBDocumentController::deleteSelectedItem() +/** + * @brief Empty the trash folder, deleting all contents permanently. + * @param showConfirmationDialog If set to true, prompts confirmation from the user + */ +void UBDocumentController::emptyTrash(bool showConfirmationDialog) { - if (mSelectionType == Page) - { - QList selectedItems = mDocumentUI->thumbnailWidget->selectedItems(); + if (showConfirmationDialog && + !UBApplication::mainWindow->yesNoQuestion(tr("Empty Trash"), tr("Are you sure you want to empty trash?"))) + return; - deletePages(selectedItems); + QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + QList toBeDeleted; + + for (int i(0); i < mTrashTi->childCount(); ++i) { + UBDocumentProxyTreeItem* proxyTi = dynamic_cast(mTrashTi->child(i)); + if (proxyTi && proxyTi->proxy()){ + if(proxyTi->proxy() == mBoardController->selectedDocument()){ + selectADocumentOnTrashingSelectedOne(dynamic_cast(mDocumentUI->documentTreeWidget),proxyTi); + } + toBeDeleted << proxyTi; + } } - else - { - UBDocumentProxyTreeItem *proxyTi = selectedDocumentProxyTreeItem(); + showMessage(tr("Emptying trash")); - UBDocumentGroupTreeItem* groupTi = selectedDocumentGroupTreeItem(); + for (int i(0); i < toBeDeleted.count(); ++i) { + UBDocumentProxyTreeItem* proxyTi = toBeDeleted.at(i); - if (proxyTi && proxyTi->proxy() && proxyTi->parent()) - { - if(UBApplication::mainWindow->yesNoQuestion(tr("Remove Document"), tr("Are you sure you want to remove the document '%1'?").arg(proxyTi->proxy()->metaData(UBSettings::documentName).toString()))) - { - if (proxyTi->parent() != mTrashTi) - { - moveDocumentToTrash(groupTi, proxyTi); - } - else - { - // We have to physically delete document - proxyTi->parent()->removeChild(proxyTi); - UBPersistenceManager::persistenceManager()->deleteDocument(proxyTi->proxy()); - - if (mTrashTi->childCount()==0) - selectDocument(NULL); - else - selectDocument(((UBDocumentProxyTreeItem*)mTrashTi->child(0))->proxy()); - reloadThumbnails(); - } - } - } - else if (groupTi) - { - if (groupTi == mTrashTi) - { - if(UBApplication::mainWindow->yesNoQuestion(tr("Empty Trash"), tr("Are you sure you want to empty trash?"))) - { - QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); - QList toBeDeleted; + proxyTi->parent()->removeChild(proxyTi); + UBPersistenceManager::persistenceManager()->deleteDocument(proxyTi->proxy()); + } - for (int i = 0; i < groupTi->childCount(); i++) - { - UBDocumentProxyTreeItem* proxyTi = dynamic_cast(groupTi->child(i)); - if (proxyTi && proxyTi->proxy()){ - if(proxyTi->proxy() == mBoardController->selectedDocument()){ - selectADocumentOnTrashingSelectedOne(dynamic_cast(mDocumentUI->documentTreeWidget),proxyTi); - } - toBeDeleted << proxyTi; - } - } + showMessage(tr("Emptied trash")); - showMessage(tr("Emptying trash")); + QApplication::restoreOverrideCursor(); + mMainWindow->actionDelete->setEnabled(false); +} - for (int i = 0; i < toBeDeleted.count(); i++) - { - UBDocumentProxyTreeItem* proxyTi = toBeDeleted.at(i); +/** + * @brief Delete an item (document or folder) from the document list + * @param item The document or folder to delete + * @param showConfirmationDialog If set to true, the user will be asked for confirmation + * + * If the item passed as parameter is a document that is in the trash, then it is deleted + * permanently. If the trash folder is passed, then all its contents are deleted. + * Finally, if a folder is passed, all its contents are moved to trash. + */ +void UBDocumentController::deleteTreeItem(QTreeWidgetItem * item, bool showConfirmationDialog) +{ + UBDocumentProxyTreeItem * document = dynamic_cast(item); + UBDocumentGroupTreeItem * folder = dynamic_cast(item); - proxyTi->parent()->removeChild(proxyTi); - UBPersistenceManager::persistenceManager()->deleteDocument(proxyTi->proxy()); - } + if (document) { + if (showConfirmationDialog && + !UBApplication::mainWindow->yesNoQuestion(tr("Remove Document"), + tr("Are you sure you want to remove the document '%1'?").arg(document->proxy()->metaData(UBSettings::documentName).toString()))) + return; - showMessage(tr("Emptied trash")); + if (!isDocumentInTrash(document)) + moveDocumentToTrash(dynamic_cast(document->parent()), document); - QApplication::restoreOverrideCursor(); - mMainWindow->actionDelete->setEnabled(false); - } - } + else { + document->parent()->removeChild(document); + UBPersistenceManager::persistenceManager()->deleteDocument(document->proxy()); + + if (mTrashTi->childCount()==0) + selectDocument(NULL); else - { - if(UBApplication::mainWindow->yesNoQuestion(tr("Remove Folder"), tr("Are you sure you want to remove the folder '%1' and all its content?").arg(groupTi->groupName()))) - { - QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); - moveFolderToTrash(groupTi); - QApplication::restoreOverrideCursor(); - } - } + selectDocument(((UBDocumentProxyTreeItem*)mTrashTi->child(0))->proxy()); + + reloadThumbnails(); + } + } + + else if (folder) { + if (folder == mTrashTi) + emptyTrash(showConfirmationDialog); + + else { + if (showConfirmationDialog && + !UBApplication::mainWindow->yesNoQuestion(tr("Remove Folder"), + tr("Are you sure you want to remove the folder '%1' and all its content?").arg(folder->groupName()))) + return; + + QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + moveFolderToTrash(folder); + QApplication::restoreOverrideCursor(); + } + } +} + + + +void UBDocumentController::deleteSelectedItem() +{ + if (mSelectionType == Page) { + QList selectedItems = mDocumentUI->thumbnailWidget->selectedItems(); + deletePages(selectedItems); + } + + else if (mSelectionType == Multiple) { + if (!UBApplication::mainWindow->yesNoQuestion(tr("Remove mutliple documents"), + tr("Are you sure you want to remove all selected documents?"))) + return; + + foreach (QTreeWidgetItem * item, mCurrentSelection) { + deleteTreeItem(item, false); } } + + else if (mSelectionType == Document || mSelectionType == Folder) { + QTreeWidgetItem * item = mCurrentSelection.first(); + if (item) + deleteTreeItem(item, true); + } } @@ -897,14 +932,17 @@ void UBDocumentController::loadDocumentProxies() mDocumentUI->documentTreeWidget->addTopLevelItem(emptyGroupNameTi); mDocumentUI->documentTreeWidget->addTopLevelItem(mTrashTi); - } +} + void UBDocumentController::itemClicked(QTreeWidgetItem * item, int column ) { Q_UNUSED(item); Q_UNUSED(column); + /* selectDocument(selectedDocumentProxy(), false); itemSelectionChanged(); + */ } void UBDocumentController::itemChanged(QTreeWidgetItem * item, int column) @@ -1119,6 +1157,90 @@ void UBDocumentController::pageSelectionChanged() selectionChanged(); } +bool UBDocumentController::isDocumentInTrash(UBDocumentProxyTreeItem * document) +{ + return dynamic_cast(document->parent())->isTrashFolder(); +} + +bool UBDocumentController::isCurrentSelectionInTrash() +{ + bool selectionIsInTrash = false; + foreach (QTreeWidgetItem* item, mCurrentSelection) { + // Find the first valid element; no need to check all of them + UBDocumentProxyTreeItem * document = dynamic_cast(item); + if (document) { + selectionIsInTrash = isDocumentInTrash(document); + break; + } + } + + return selectionIsInTrash; +} + +/** + * @brief Set the currently selected items, after checking the selection is valid + * + * This method compares the current selection with the previous one, and deselects + * the "incorrectly" selected items if necessary. For example, it shouldn't be possible + * to select items both in the trash and out; and the Trash folder shouldn't be + * included in multiple selections. + */ +void UBDocumentController::updateCurrentSelection() +{ + QList newSelection = mDocumentUI->documentTreeWidget->selectedItems(); + + // If the selection is of size 1 or 0, we don't need to do any checking, we just accept it. + if (newSelection.size() <= 1) { + mCurrentSelection = newSelection; + return; + } + + // We don't allow the Trash folder in multiple selections + // If it is currently selected, we deselect all the newly selected items + if (mCurrentSelection.size() == 1) { + UBDocumentGroupTreeItem* folder = dynamic_cast(mCurrentSelection.first()); + + if (folder && folder->isTrashFolder()) { + foreach (QTreeWidgetItem* item, newSelection) { + if (item != folder) + item->setSelected(false); + } + + return; + } + } + + // Find the elements of the new selection that aren't in the old one + QSet newItems = newSelection.toSet().subtract(mCurrentSelection.toSet()); + + bool selectionIsInTrash = isCurrentSelectionInTrash(); + + foreach (QTreeWidgetItem* item, newItems) { + bool addToSelection = true; + UBDocumentProxyTreeItem * document = dynamic_cast(item); + if (document) { + // No mix between trashed and non-trashed items + if (isDocumentInTrash(document) != selectionIsInTrash) + addToSelection = false; + } + + UBDocumentGroupTreeItem * folder = dynamic_cast(item); + if (folder) { + // Trash folder is not allowed in multiple selections + if (folder->isTrashFolder()) + addToSelection = false; + + // Don't add a folder when trash items are selected + if (selectionIsInTrash) + addToSelection = false; + } + + if (addToSelection) + mCurrentSelection.append(item); + else + item->setSelected(false); + } +} void UBDocumentController::selectionChanged() { @@ -1135,14 +1257,20 @@ void UBDocumentController::selectionChanged() bool pageSelected = (mSelectionType == Page); bool groupSelected = (mSelectionType == Folder); bool docSelected = (mSelectionType == Document); + bool multipleSelected = (mSelectionType == Multiple); + bool selectedItemsAreInTrash = isCurrentSelectionInTrash(); - bool trashSelected = false; + + bool trashSelected = false; // set to true if selected items are in trash or if trash folder is selected if (groupSelected && selectedDocumentGroupTreeItem()) trashSelected = selectedDocumentGroupTreeItem()->isTrashFolder(); if ((docSelected || pageSelected) && proxyTi) trashSelected = dynamic_cast(proxyTi->parent())->isTrashFolder(); + if (multipleSelected) + trashSelected = selectedItemsAreInTrash; + bool defaultGroupSelected = false; if (groupSelected && selectedDocumentGroupTreeItem()) defaultGroupSelected = selectedDocumentGroupTreeItem()->isDefaultFolder(); @@ -1179,7 +1307,7 @@ void UBDocumentController::selectionChanged() bool deleteEnabled = false; if (trashSelected) { - if (docSelected) + if (docSelected || multipleSelected) deleteEnabled = true; else if (groupSelected && selectedDocumentGroupTreeItem()) { @@ -1189,7 +1317,7 @@ void UBDocumentController::selectionChanged() } else { - deleteEnabled = groupSelected || docSelected || pageSelected; + deleteEnabled = groupSelected || docSelected || pageSelected || multipleSelected; // TODO: clean up. this is weirdly done } if (pageSelected && (pageCount == mDocumentUI->thumbnailWidget->selectedItems().count())) @@ -1204,7 +1332,7 @@ void UBDocumentController::selectionChanged() if (trashSelected) { - if (docSelected) + if (docSelected || multipleSelected) // TODO: clean this up. have only "selectedItemsAreInTrash" { mMainWindow->actionDelete->setIcon(QIcon(":/images/toolbar/deleteDocument.png")); mMainWindow->actionDelete->setText(tr("Delete")); @@ -1221,8 +1349,8 @@ void UBDocumentController::selectionChanged() mMainWindow->actionDelete->setText(tr("Trash")); } - mMainWindow->actionDocumentAdd->setEnabled((docSelected || pageSelected) && !trashSelected); - mMainWindow->actionImport->setEnabled(!trashSelected); + mMainWindow->actionDocumentAdd->setEnabled((docSelected || pageSelected) && !trashSelected && !multipleSelected); + mMainWindow->actionImport->setEnabled(!trashSelected && !multipleSelected); } @@ -1565,7 +1693,9 @@ void UBDocumentController::focusChanged(QWidget *old, QWidget *current) } else if (current == mDocumentUI->documentTreeWidget) { - if (selectedDocumentProxy()) + if (multipleSelection()) + mSelectionType = Multiple; + else if (selectedDocumentProxy()) mSelectionType = Document; else if (selectedDocumentGroupTreeItem()) mSelectionType = Folder; @@ -1652,6 +1782,10 @@ void UBDocumentController::refreshDocumentThumbnailsView(UBDocumentContainer*) UBDocumentProxy *proxy = selectedDocumentProxy(); QGraphicsPixmapItem *selection = 0; + // Don't display thumbnails if multiple documents are selected + if (multipleSelection()) + proxy = 0; + QStringList labels; if (proxy) @@ -1696,3 +1830,9 @@ void UBDocumentController::refreshDocumentThumbnailsView(UBDocumentContainer*) QApplication::restoreOverrideCursor(); } + +bool UBDocumentController::multipleSelection() +{ + QList items = mDocumentUI->documentTreeWidget->selectedItems(); + return (items.size() > 1); +} diff --git a/src/document/UBDocumentController.h b/src/document/UBDocumentController.h index 7fc70926..da2806a3 100644 --- a/src/document/UBDocumentController.h +++ b/src/document/UBDocumentController.h @@ -102,7 +102,7 @@ class UBDocumentController : public UBDocumentContainer enum LastSelectedElementType { - None = 0, Folder, Document, Page + None = 0, Folder, Document, Page, Multiple }; LastSelectedElementType mSelectionType; @@ -121,13 +121,20 @@ class UBDocumentController : public UBDocumentContainer UBDocumentToolsPalette *mToolsPalette; bool mToolsPalettePositionned; UBDocumentGroupTreeItem* mTrashTi; + QList mCurrentSelection; + QString mDocumentTrashGroupName; + QString mDefaultDocumentGroupName; void selectADocumentOnTrashingSelectedOne(UBDocumentGroupTreeItem* groupTi,UBDocumentProxyTreeItem *proxyTi); - void moveDocumentToTrash(UBDocumentGroupTreeItem* groupTi, UBDocumentProxyTreeItem *proxyTi); void moveFolderToTrash(UBDocumentGroupTreeItem* groupTi); - QString mDocumentTrashGroupName; - QString mDefaultDocumentGroupName; + void emptyTrash(bool showConfirmationDialog); + void deleteTreeItem(QTreeWidgetItem * item, bool showConfirmationDialog); + + void updateCurrentSelection(); + bool multipleSelection(); + bool isDocumentInTrash(UBDocumentProxyTreeItem * document); + bool isCurrentSelectionInTrash(); private slots: void documentZoomSliderValueChanged (int value); From 4b97816db9b4aaa3f3fd47d21706ee6f4fb24930 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Mon, 22 Feb 2016 12:01:21 +0100 Subject: [PATCH 111/243] Removed UBDocumentController::itemClicked slot --- src/document/UBDocumentController.cpp | 12 ------------ src/document/UBDocumentController.h | 1 - 2 files changed, 13 deletions(-) diff --git a/src/document/UBDocumentController.cpp b/src/document/UBDocumentController.cpp index 87042f6c..ef6f3ede 100644 --- a/src/document/UBDocumentController.cpp +++ b/src/document/UBDocumentController.cpp @@ -379,7 +379,6 @@ void UBDocumentController::setupViews() connect(mDocumentUI->documentTreeWidget, SIGNAL(itemSelectionChanged()), this, SLOT(itemSelectionChanged())); connect(mDocumentUI->documentTreeWidget, SIGNAL(itemChanged(QTreeWidgetItem *, int)), this, SLOT(itemChanged(QTreeWidgetItem *, int))); - connect(mDocumentUI->documentTreeWidget, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this, SLOT(itemClicked(QTreeWidgetItem *, int))); connect(mDocumentUI->thumbnailWidget, SIGNAL(sceneDropped(UBDocumentProxy*, int, int)), this, SLOT(moveSceneToIndex ( UBDocumentProxy*, int, int))); connect(mDocumentUI->thumbnailWidget, SIGNAL(resized()), this, SLOT(thumbnailViewResized())); @@ -934,17 +933,6 @@ void UBDocumentController::loadDocumentProxies() mDocumentUI->documentTreeWidget->addTopLevelItem(mTrashTi); } -void UBDocumentController::itemClicked(QTreeWidgetItem * item, int column ) -{ - Q_UNUSED(item); - Q_UNUSED(column); - - /* - selectDocument(selectedDocumentProxy(), false); - itemSelectionChanged(); - */ -} - void UBDocumentController::itemChanged(QTreeWidgetItem * item, int column) { UBDocumentProxyTreeItem* proxyItem = dynamic_cast(item); diff --git a/src/document/UBDocumentController.h b/src/document/UBDocumentController.h index da2806a3..a946f0fe 100644 --- a/src/document/UBDocumentController.h +++ b/src/document/UBDocumentController.h @@ -148,7 +148,6 @@ class UBDocumentController : public UBDocumentContainer void documentSceneChanged(UBDocumentProxy* proxy, int pSceneIndex); void pageDoubleClicked(QGraphicsItem* item, int index); void pageClicked(QGraphicsItem* item, int index); - void itemClicked(QTreeWidgetItem * item, int column ); void addToDocument(); void addDocumentInTree(UBDocumentProxy* pDocument); void updateDocumentInTree(UBDocumentProxy* pDocument); From 49a9c61647fec8d2b3bde753890518d0530bf358 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Mon, 22 Feb 2016 12:02:14 +0100 Subject: [PATCH 112/243] Removed debug message --- src/frameworks/UBCoreGraphicsScene.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/frameworks/UBCoreGraphicsScene.cpp b/src/frameworks/UBCoreGraphicsScene.cpp index e955ee60..3d3c69c4 100644 --- a/src/frameworks/UBCoreGraphicsScene.cpp +++ b/src/frameworks/UBCoreGraphicsScene.cpp @@ -80,7 +80,6 @@ void UBCoreGraphicsScene::removeItem(QGraphicsItem* item, bool forceDelete) QGraphicsScene::removeItem(item); if (forceDelete) { - qDebug() << "force delete is " << forceDelete; deleteItem(item); } setModified(true); From 6cc9394f0dad2852bab5873f682837e1063fe324 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Mon, 22 Feb 2016 13:02:10 +0100 Subject: [PATCH 113/243] Updated version number (1.10a9) --- OpenBoard.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenBoard.pro b/OpenBoard.pro index d08951c9..ea6ccacf 100644 --- a/OpenBoard.pro +++ b/OpenBoard.pro @@ -11,7 +11,7 @@ CONFIG += debug_and_release \ VERSION_MAJ = 1 VERSION_MIN = 10 VERSION_TYPE = a # a = alpha, b = beta, rc = release candidate, r = release, other => error -VERSION_PATCH = 8 +VERSION_PATCH = 9 VERSION = "$${VERSION_MAJ}.$${VERSION_MIN}.$${VERSION_TYPE}.$${VERSION_PATCH}" VERSION = $$replace(VERSION, "\\.r", "") From 2c5793b54e79ba324f44b721f863d22f79a48bc7 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Tue, 23 Feb 2016 11:39:06 +0100 Subject: [PATCH 114/243] Corrected stroke movement - When clicking a stroke, they aren't moved immediately anymore; a certain drag distance is necessary, which makes it easy (again) to select a stroke with a stylus (which tends to move a little as it is clicked, hence the problem). - Removed duplicate code; the movement is now managed by QGraphicsItemGroup::mouseMoveEvent. This prevents use of the transform() method to get the stroke's transformation matrix; so sceneTransform() is used instead when copying a strokes group. - Also fixed an oversight in UBBoardView: Media items couldn't be moved directly anymore. --- src/board/UBBoardView.cpp | 1 + src/domain/UBGraphicsStrokesGroup.cpp | 106 ++------------------------ src/domain/UBGraphicsStrokesGroup.h | 28 ------- 3 files changed, 7 insertions(+), 128 deletions(-) diff --git a/src/board/UBBoardView.cpp b/src/board/UBBoardView.cpp index 7c5cf039..fb9ec7f2 100644 --- a/src/board/UBBoardView.cpp +++ b/src/board/UBBoardView.cpp @@ -663,6 +663,7 @@ bool UBBoardView::itemShouldBeMoved(QGraphicsItem *item) if (item->isSelected()) return false; case UBGraphicsMediaItem::Type: + return true; case UBGraphicsStrokesGroup::Type: return false; case UBGraphicsTextItem::Type: diff --git a/src/domain/UBGraphicsStrokesGroup.cpp b/src/domain/UBGraphicsStrokesGroup.cpp index a6dbc2a8..b624946c 100644 --- a/src/domain/UBGraphicsStrokesGroup.cpp +++ b/src/domain/UBGraphicsStrokesGroup.cpp @@ -113,40 +113,23 @@ void UBGraphicsStrokesGroup::mousePressEvent(QGraphicsSceneMouseEvent *event) { Delegate()->startUndoStep(); - mStartingPoint = event->scenePos(); - - initializeTransform(); - - mTranslateX = 0; - mTranslateY = 0; - mAngleOffset = 0; - - mInitialTransform = buildTransform(); - + QGraphicsItemGroup::mousePressEvent(event); event->accept(); + + setSelected(false); } void UBGraphicsStrokesGroup::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { - QLineF move = QLineF(mStartingPoint, event->scenePos()); - - mTranslateX = move.dx(); - mTranslateY = move.dy(); - //Delegate()->frame()->moveLinkedItems(move); + QGraphicsItemGroup::mouseMoveEvent(event); - setTransform(buildTransform()); - event->accept(); - + setSelected(false); } void UBGraphicsStrokesGroup::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { Delegate()->commitUndoStep(); - - mTotalTranslateX += mTranslateX; - mTotalTranslateY += mTranslateY; - event->accept(); Delegate()->mouseReleaseEvent(event); @@ -183,7 +166,7 @@ UBItem* UBGraphicsStrokesGroup::deepCopy() const } } const_cast(this)->setTransform(groupTransform); - copy->setTransform(groupTransform); + copy->setTransform(sceneTransform()); return copy; } @@ -240,80 +223,3 @@ QPainterPath UBGraphicsStrokesGroup::shape() const return path; } - -void UBGraphicsStrokesGroup::initializeTransform() -{ - - QTransform itemTransform = sceneTransform(); - QRectF itemRect = boundingRect(); - QPointF topLeft = itemTransform.map(itemRect.topLeft()); - QPointF topRight = itemTransform.map(itemRect.topRight()); - QPointF bottomLeft = itemTransform.map(itemRect.bottomLeft()); - - qreal horizontalFlip = (topLeft.x() > topRight.x()) ? -1 : 1; - mMirrorX = horizontalFlip < 0 ; - if(horizontalFlip < 0){ - // why this is because of the way of calculating the translations that checks which side is the most is the - // nearest instead of checking which one is the left side. - QPointF tmp = topLeft; - topLeft = topRight; - topRight = tmp; - - // because of the calculation of the height is done by lenght and not deltaY - bottomLeft = itemTransform.map(itemRect.bottomRight()); - } - - qreal verticalFlip = (bottomLeft.y() < topLeft.y()) ? -1 : 1; - // not sure that is usefull - mMirrorY = verticalFlip < 0; - if(verticalFlip < 0 && !mMirrorX){ - topLeft = itemTransform.map(itemRect.bottomLeft()); - topRight = itemTransform.map(itemRect.bottomRight()); - bottomLeft = itemTransform.map(itemRect.topLeft()); - } - - QLineF topLine(topLeft, topRight); - QLineF leftLine(topLeft, bottomLeft); - qreal width = topLine.length(); - qreal height = leftLine.length(); - - mAngle = topLine.angle(); - - // the fact the the length is used we loose the horizontalFlip information - // a better way to do this is using DeltaX that preserve the direction information. - mTotalScaleX = (width / itemRect.width()) * horizontalFlip; - mTotalScaleY = height / itemRect.height() * verticalFlip; - - - - QTransform tr; - QPointF center = boundingRect().center(); - tr.translate(center.x() * mTotalScaleX, center.y() * mTotalScaleY); - tr.rotate(-mAngle); - tr.translate(-center.x() * mTotalScaleX, -center.y() * mTotalScaleY); - tr.scale(mTotalScaleX, mTotalScaleY); - - mTotalTranslateX = transform().dx() - tr.dx(); - mTotalTranslateY = transform().dy() - tr.dy(); - - -} - -QTransform UBGraphicsStrokesGroup::buildTransform() -{ - QTransform tr; - QPointF center = boundingRect().center(); - - // Translate - tr.translate(mTotalTranslateX + mTranslateX, mTotalTranslateY + mTranslateY); - - // Set angle - tr.translate(center.x() * mTotalScaleX, center.y() * mTotalScaleY); - tr.rotate(-mAngle); - tr.translate(-center.x() * mTotalScaleX, -center.y() * mTotalScaleY); - - // Scale - tr.scale(mTotalScaleX, mTotalScaleY ); - - return tr; -} diff --git a/src/domain/UBGraphicsStrokesGroup.h b/src/domain/UBGraphicsStrokesGroup.h index 545c8c9d..5ddf789e 100644 --- a/src/domain/UBGraphicsStrokesGroup.h +++ b/src/domain/UBGraphicsStrokesGroup.h @@ -66,34 +66,6 @@ protected: virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value); - - private: - qreal mTranslateX; - qreal mTranslateY; - qreal mTotalTranslateX; - qreal mTotalTranslateY; - - qreal mAngle; - qreal mAngleOffset; - - qreal mTotalScaleX; - qreal mTotalScaleY; - qreal mScaleX; - qreal mScaleY; - - bool mFlippedX; - bool mFlippedY; - bool mMirrorX; - bool mMirrorY; - bool mResizing; - bool mMirroredXAtStart; - bool mMirroredYAtStart; - - QPointF mStartingPoint; - QTransform mInitialTransform; - - QTransform buildTransform (); - void initializeTransform (); }; #endif // UBGRAPHICSSTROKESGROUP_H From 19dd4d1fc7684ce0539ac51a8fba6ef583153824 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Tue, 23 Feb 2016 12:35:25 +0100 Subject: [PATCH 115/243] Fixed documents being accidentally permanently deleted in some cases When both a folder and items it contained were selected, and trashed, the documents could sometimes be deleted twice and thus, permanently deleted when one just intended to move them to the trash. --- src/document/UBDocumentController.cpp | 25 +++++++++++++++++++++++++ src/document/UBDocumentController.h | 1 + 2 files changed, 26 insertions(+) diff --git a/src/document/UBDocumentController.cpp b/src/document/UBDocumentController.cpp index ef6f3ede..b00ee4a4 100644 --- a/src/document/UBDocumentController.cpp +++ b/src/document/UBDocumentController.cpp @@ -803,7 +803,19 @@ void UBDocumentController::deleteSelectedItem() tr("Are you sure you want to remove all selected documents?"))) return; + QList foldersToDelete; + foreach (QTreeWidgetItem * item, mCurrentSelection) { + LastSelectedElementType type = itemType(item); + if (type == Document) + deleteTreeItem(item, false); + + else if (type == Folder) + // Delete folders later, to avoid deleting a document twice + foldersToDelete << item; + } + + foreach (QTreeWidgetItem * item, foldersToDelete) { deleteTreeItem(item, false); } } @@ -1824,3 +1836,16 @@ bool UBDocumentController::multipleSelection() QList items = mDocumentUI->documentTreeWidget->selectedItems(); return (items.size() > 1); } + +UBDocumentController::LastSelectedElementType UBDocumentController::itemType(QTreeWidgetItem * item) +{ + UBDocumentProxyTreeItem * document = dynamic_cast(item); + if (document) + return Document; + + UBDocumentGroupTreeItem * folder = dynamic_cast(item); + if (folder) + return Folder; + + return None; +} diff --git a/src/document/UBDocumentController.h b/src/document/UBDocumentController.h index a946f0fe..fc28af0c 100644 --- a/src/document/UBDocumentController.h +++ b/src/document/UBDocumentController.h @@ -135,6 +135,7 @@ class UBDocumentController : public UBDocumentContainer bool multipleSelection(); bool isDocumentInTrash(UBDocumentProxyTreeItem * document); bool isCurrentSelectionInTrash(); + LastSelectedElementType itemType(QTreeWidgetItem * item); private slots: void documentZoomSliderValueChanged (int value); From ca7e8e92540752f6a0a38f18a3324f668934e48b Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Tue, 23 Feb 2016 14:18:01 +0100 Subject: [PATCH 116/243] Quick fix: Ctrl-A no longer selects same document mutliple times Also quick code clean-up in UBDocumentController --- src/document/UBDocumentController.cpp | 21 +++++++++++---------- src/gui/UBDocumentTreeWidget.cpp | 11 +++++++++++ src/gui/UBDocumentTreeWidget.h | 2 ++ 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/document/UBDocumentController.cpp b/src/document/UBDocumentController.cpp index b00ee4a4..bc8b0fdf 100644 --- a/src/document/UBDocumentController.cpp +++ b/src/document/UBDocumentController.cpp @@ -756,7 +756,7 @@ void UBDocumentController::deleteTreeItem(QTreeWidgetItem * item, bool showConfi tr("Are you sure you want to remove the document '%1'?").arg(document->proxy()->metaData(UBSettings::documentName).toString()))) return; - if (!isDocumentInTrash(document)) + if (!document->isInTrash()) moveDocumentToTrash(dynamic_cast(document->parent()), document); else { @@ -1157,11 +1157,6 @@ void UBDocumentController::pageSelectionChanged() selectionChanged(); } -bool UBDocumentController::isDocumentInTrash(UBDocumentProxyTreeItem * document) -{ - return dynamic_cast(document->parent())->isTrashFolder(); -} - bool UBDocumentController::isCurrentSelectionInTrash() { bool selectionIsInTrash = false; @@ -1169,7 +1164,7 @@ bool UBDocumentController::isCurrentSelectionInTrash() // Find the first valid element; no need to check all of them UBDocumentProxyTreeItem * document = dynamic_cast(item); if (document) { - selectionIsInTrash = isDocumentInTrash(document); + selectionIsInTrash = document->isInTrash(); break; } } @@ -1220,7 +1215,7 @@ void UBDocumentController::updateCurrentSelection() UBDocumentProxyTreeItem * document = dynamic_cast(item); if (document) { // No mix between trashed and non-trashed items - if (isDocumentInTrash(document) != selectionIsInTrash) + if (document->isInTrash() != selectionIsInTrash) addToSelection = false; } @@ -1234,9 +1229,15 @@ void UBDocumentController::updateCurrentSelection() if (selectionIsInTrash) addToSelection = false; } + if (!folder && !document) + addToSelection = false; - if (addToSelection) - mCurrentSelection.append(item); + if (addToSelection) { + if (!mCurrentSelection.contains(item)) { + // the .subtract() above doesn't seem to work all the time... + mCurrentSelection.append(item); + } + } else item->setSelected(false); } diff --git a/src/gui/UBDocumentTreeWidget.cpp b/src/gui/UBDocumentTreeWidget.cpp index 7fc34e8f..ea660133 100644 --- a/src/gui/UBDocumentTreeWidget.cpp +++ b/src/gui/UBDocumentTreeWidget.cpp @@ -419,6 +419,17 @@ UBDocumentProxyTreeItem::UBDocumentProxyTreeItem(QTreeWidgetItem * parent, UBDoc parent->insertChild(i, this); } +bool UBDocumentProxyTreeItem::isInTrash() +{ + UBDocumentGroupTreeItem * parentFolder = dynamic_cast(this->parent()); + if (parentFolder) + return parentFolder->isTrashFolder(); + else { + qWarning() << "UBDocumentProxyTreeItem::isInTrash: document has no parent folder. Assuming it is in trash."; + return true; + } +} + UBDocumentGroupTreeItem::UBDocumentGroupTreeItem(QTreeWidgetItem *parent, bool isEditable) : QTreeWidgetItem(parent) diff --git a/src/gui/UBDocumentTreeWidget.h b/src/gui/UBDocumentTreeWidget.h index af78fe56..4856b06c 100644 --- a/src/gui/UBDocumentTreeWidget.h +++ b/src/gui/UBDocumentTreeWidget.h @@ -77,6 +77,8 @@ class UBDocumentProxyTreeItem : public QTreeWidgetItem return mProxy; } + bool isInTrash(); + QPointer mProxy; }; From 1925add46054fb5ff3adb917832c952768827a98 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Tue, 23 Feb 2016 15:32:40 +0100 Subject: [PATCH 117/243] Fixed video not hiding on 2nd screen when asked to --- src/domain/UBGraphicsItemDelegate.h | 4 +++- src/domain/UBGraphicsMediaItemDelegate.cpp | 10 ++++++++++ src/domain/UBGraphicsMediaItemDelegate.h | 1 + 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/domain/UBGraphicsItemDelegate.h b/src/domain/UBGraphicsItemDelegate.h index b2096b45..c18bf0b1 100644 --- a/src/domain/UBGraphicsItemDelegate.h +++ b/src/domain/UBGraphicsItemDelegate.h @@ -40,6 +40,7 @@ #include #include #include +#include #include "core/UB.h" #include "core/UBSettings.h" @@ -320,6 +321,8 @@ class UBGraphicsItemDelegate : public QObject virtual void decorateMenu(QMenu *menu); virtual void updateMenuActionState(); + void showHideRecurs(const QVariant &pShow, QGraphicsItem *pItem); + QList buttons() {return mButtons;} QGraphicsItem* mDelegated; @@ -352,7 +355,6 @@ protected slots: private: void updateFrame(); void updateButtons(bool showUpdated = false); - inline void showHideRecurs(const QVariant &pShow, QGraphicsItem *pItem); QPointF mOffset; QTransform mPreviousTransform; diff --git a/src/domain/UBGraphicsMediaItemDelegate.cpp b/src/domain/UBGraphicsMediaItemDelegate.cpp index 839ad434..8f023706 100644 --- a/src/domain/UBGraphicsMediaItemDelegate.cpp +++ b/src/domain/UBGraphicsMediaItemDelegate.cpp @@ -310,3 +310,13 @@ void UBGraphicsMediaItemDelegate::totalTimeChanged(qint64 newTotalTime) { mMediaControl->totalTimeChanged(newTotalTime); } + +void UBGraphicsMediaItemDelegate::showHide(bool show) +{ + QVariant showFlag = QVariant(show ? UBItemLayerType::Object : UBItemLayerType::Control); + showHideRecurs(showFlag, mDelegated); + showHideRecurs(showFlag, delegated()->videoItem()); + mDelegated->update(); + + emit showOnDisplayChanged(show); +} diff --git a/src/domain/UBGraphicsMediaItemDelegate.h b/src/domain/UBGraphicsMediaItemDelegate.h index 8cb47b3b..3031a738 100644 --- a/src/domain/UBGraphicsMediaItemDelegate.h +++ b/src/domain/UBGraphicsMediaItemDelegate.h @@ -54,6 +54,7 @@ class UBGraphicsMediaItemDelegate : public UBGraphicsItemDelegate void toggleMute(); void updateTicker(qint64 time); + virtual void showHide(bool show); protected slots: From e1674dc8a2fdbfe0505b90995526738bd85c8b80 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Tue, 23 Feb 2016 15:33:20 +0100 Subject: [PATCH 118/243] Fixed video not getting removed from scene when asked to --- src/domain/UBGraphicsMediaItemDelegate.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/domain/UBGraphicsMediaItemDelegate.cpp b/src/domain/UBGraphicsMediaItemDelegate.cpp index 8f023706..8ad719ef 100644 --- a/src/domain/UBGraphicsMediaItemDelegate.cpp +++ b/src/domain/UBGraphicsMediaItemDelegate.cpp @@ -198,6 +198,11 @@ void UBGraphicsMediaItemDelegate::remove(bool canUndo) if (delegated() && delegated()->mediaObject()) delegated()->mediaObject()->stop(); + if (delegated()->videoItem()) { + UBGraphicsScene* scene = dynamic_cast(mDelegated->scene()); + scene->removeItem(delegated()->videoItem()); + } + UBGraphicsItemDelegate::remove(canUndo); } From c987dabbafc7078fd845de974b3eb3525e595bd0 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Tue, 23 Feb 2016 15:45:15 +0100 Subject: [PATCH 119/243] Fixed wikipedia widget --- resources/library/applications/Wikipedia.wgt/index.html | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/resources/library/applications/Wikipedia.wgt/index.html b/resources/library/applications/Wikipedia.wgt/index.html index 72350606..d9283346 100644 --- a/resources/library/applications/Wikipedia.wgt/index.html +++ b/resources/library/applications/Wikipedia.wgt/index.html @@ -1,4 +1,3 @@ - @@ -15,7 +14,7 @@ - - - - - - - - -

- - diff --git a/resources/library/search/Google images.wgs/locales/locales.js b/resources/library/search/Google images.wgs/locales/locales.js deleted file mode 100755 index fda34947..00000000 --- a/resources/library/search/Google images.wgs/locales/locales.js +++ /dev/null @@ -1,80 +0,0 @@ -var locales = { - 'en': { - 'def_opts_val_size': 'Any', - 'def_opts_val_type': 'Any', - 'def_opts_val_image': 'Any', - 'def_opts_val_copyright': 'Any', - 'size_title': 'Size', - 'size_small': 'Small', - 'size_medium': 'Medium', - 'size_large': 'Large', - 'size_extra_large': 'Extra large', - 'colorization_title': 'Colorization', - 'coloriz_grayscale': 'Grayscale', - 'coloriz_color': 'Color', - 'main_color_title': 'Main color', - 'm_color_black': 'Black', - 'm_color_blue': 'Blue', - 'm_color_brown': 'Brown', - 'm_color_gray': 'Gray', - 'm_color_green': 'Green', - 'm_color_orange': 'Orange', - 'm_color_pink': 'Pink', - 'm_color_purple': 'Purple', - 'm_color_red': 'Red', - 'm_color_teal': 'Teal', - 'm_color_white': 'White', - 'm_color_yellow': 'Yellow', - 'file_type_title': 'File type', - 'image_type_title': 'Image type', - 'image_type_faces': 'Faces', - 'image_type_photo': 'Photo', - 'image_type_clipart': 'Clipart', - 'image_type_lineart': 'Lineart', - 'image_license_title': 'Licence', - 'image_license_reuse': 'Reuse', - 'image_license_comm_reuse': 'Commercial reuse', - 'image_license_modif': 'Modification', - 'image_license_comm_modif': 'Commercial modification', - 'disclaimer_title': 'This API is based on Google Image. Please refer to terms of use of this service.' - }, - 'fr': { - 'def_opts_val_size': 'Toutes', - 'def_opts_val_type': 'Tous', - 'def_opts_val_image': 'Toutes', - 'def_opts_val_copyright': 'Tous', - 'size_title': 'Tailles', - 'size_small': 'Petite', - 'size_medium': 'Moyenne', - 'size_large': 'Grande', - 'size_extra_large': 'Extra large', - 'colorization_title': 'Couleurs de l\'image', - 'coloriz_grayscale': 'Noir et blanc', - 'coloriz_color': 'En couleur', - 'main_color_title': 'Couleur électronique', - 'm_color_black': 'Noir', - 'm_color_blue': 'Bleu', - 'm_color_brown': 'Brun', - 'm_color_gray': 'Gris', - 'm_color_green': 'Vert', - 'm_color_orange': 'Orange', - 'm_color_pink': 'Rose', - 'm_color_purple': 'Pourpre', - 'm_color_red': 'Rouge', - 'm_color_teal': 'Sarcelle', - 'm_color_white': 'Blanc', - 'm_color_yellow': 'Jaune', - 'file_type_title': 'Types de fichier', - 'image_type_title': 'Types d\'image', - 'image_type_faces': 'Visages', - 'image_type_photo': 'Photo', - 'image_type_clipart': 'Images clipart', - 'image_type_lineart': 'Dessins au trait', - 'image_license_title': 'Droits d\'usage', - 'image_license_reuse': 'Usage, distribution', - 'image_license_comm_reuse': 'Usage, distribution, commercial', - 'image_license_modif': 'Usage, distribution, modification', - 'image_license_comm_modif': 'Usage, distribution, modification, commercial', - 'disclaimer_title': 'Cette recherche utilise les services de Google Images. Veuillez vous référer aux conditions d\'utilisation de ce service.' - } -}; diff --git a/resources/library/search/Google images.wgs/scripts/jquery-1.6.2.min.js b/resources/library/search/Google images.wgs/scripts/jquery-1.6.2.min.js deleted file mode 100755 index e67db747..00000000 --- a/resources/library/search/Google images.wgs/scripts/jquery-1.6.2.min.js +++ /dev/null @@ -1,18 +0,0 @@ -/*! - * jQuery JavaScript Library v1.6.2 - * http://jquery.com/ - * - * Copyright 2011, John Resig - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * Copyright 2011, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * - * Date: Thu Jun 30 14:16:56 2011 -0400 - */ -(function(a,b){function cv(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cs(a){if(!cg[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ch||(ch=c.createElement("iframe"),ch.frameBorder=ch.width=ch.height=0),b.appendChild(ch);if(!ci||!ch.createElement)ci=(ch.contentWindow||ch.contentDocument).document,ci.write((c.compatMode==="CSS1Compat"?"":"")+""),ci.close();d=ci.createElement(a),ci.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ch)}cg[a]=e}return cg[a]}function cr(a,b){var c={};f.each(cm.concat.apply([],cm.slice(0,b)),function(){c[this]=a});return c}function cq(){cn=b}function cp(){setTimeout(cq,0);return cn=f.now()}function cf(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ce(){try{return new a.XMLHttpRequest}catch(b){}}function b$(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g0){c!=="border"&&f.each(e,function(){c||(d-=parseFloat(f.css(a,"padding"+this))||0),c==="margin"?d+=parseFloat(f.css(a,c+this))||0:d-=parseFloat(f.css(a,"border"+this+"Width"))||0});return d+"px"}d=bx(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0,c&&f.each(e,function(){d+=parseFloat(f.css(a,"padding"+this))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+this+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+this))||0)});return d+"px"}function bm(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(be,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bl(a){f.nodeName(a,"input")?bk(a):"getElementsByTagName"in a&&f.grep(a.getElementsByTagName("input"),bk)}function bk(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bj(a){return"getElementsByTagName"in a?a.getElementsByTagName("*"):"querySelectorAll"in a?a.querySelectorAll("*"):[]}function bi(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bh(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c=f.expando,d=f.data(a),e=f.data(b,d);if(d=d[c]){var g=d.events;e=e[c]=f.extend({},d);if(g){delete e.handle,e.events={};for(var h in g)for(var i=0,j=g[h].length;i=0===c})}function V(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function N(a,b){return(a&&a!=="*"?a+".":"")+b.replace(z,"`").replace(A,"&")}function M(a){var b,c,d,e,g,h,i,j,k,l,m,n,o,p=[],q=[],r=f._data(this,"events");if(!(a.liveFired===this||!r||!r.live||a.target.disabled||a.button&&a.type==="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var s=r.live.slice(0);for(i=0;ic)break;a.currentTarget=e.elem,a.data=e.handleObj.data,a.handleObj=e.handleObj,o=e.handleObj.origHandler.apply(e.elem,arguments);if(o===!1||a.isPropagationStopped()){c=e.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function K(a,c,d){var e=f.extend({},d[0]);e.type=a,e.originalEvent={},e.liveFired=b,f.event.handle.call(c,e),e.isDefaultPrevented()&&d[0].preventDefault()}function E(){return!0}function D(){return!1}function m(a,c,d){var e=c+"defer",g=c+"queue",h=c+"mark",i=f.data(a,e,b,!0);i&&(d==="queue"||!f.data(a,g,b,!0))&&(d==="mark"||!f.data(a,h,b,!0))&&setTimeout(function(){!f.data(a,g,b,!0)&&!f.data(a,h,b,!0)&&(f.removeData(a,e,!0),i.resolve())},0)}function l(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function k(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(j,"$1-$2").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNaN(d)?i.test(d)?f.parseJSON(d):d:parseFloat(d)}catch(g){}f.data(a,c,d)}else d=b}return d}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/\d/,n=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,o=/^[\],:{}\s]*$/,p=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,q=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,r=/(?:^|:|,)(?:\s*\[)+/g,s=/(webkit)[ \/]([\w.]+)/,t=/(opera)(?:.*version)?[ \/]([\w.]+)/,u=/(msie) ([\w.]+)/,v=/(mozilla)(?:.*? rv:([\w.]+))?/,w=/-([a-z])/ig,x=function(a,b){return b.toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=n.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.6.2",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;A.resolveWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!A){A=e._Deferred();if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNaN:function(a){return a==null||!m.test(a)||isNaN(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1;var c;for(c in a);return c===b||D.call(a,c)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(o.test(b.replace(p,"@").replace(q,"]").replace(r,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(b,c,d){a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b)),d=c.documentElement,(!d||!d.nodeName||d.nodeName==="parsererror")&&e.error("Invalid XML: "+b);return c},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i1?h.call(arguments,0):c,--e||g.resolveWith(g,h.call(b,0))}}var b=arguments,c=0,d=b.length,e=d,g=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred();if(d>1){for(;c
a",d=a.getElementsByTagName("*"),e=a.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=a.getElementsByTagName("input")[0],k={leadingWhitespace:a.firstChild.nodeType===3,tbody:!a.getElementsByTagName("tbody").length,htmlSerialize:!!a.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55$/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:a.className!=="t",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,k.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,k.optDisabled=!h.disabled;try{delete a.test}catch(v){k.deleteExpando=!1}!a.addEventListener&&a.attachEvent&&a.fireEvent&&(a.attachEvent("onclick",function(){k.noCloneEvent=!1}),a.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),k.radioValue=i.value==="t",i.setAttribute("checked","checked"),a.appendChild(i),l=c.createDocumentFragment(),l.appendChild(a.firstChild),k.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,a.innerHTML="",a.style.width=a.style.paddingLeft="1px",m=c.getElementsByTagName("body")[0],o=c.createElement(m?"div":"body"),p={visibility:"hidden",width:0,height:0,border:0,margin:0},m&&f.extend(p,{position:"absolute",left:-1e3,top:-1e3});for(t in p)o.style[t]=p[t];o.appendChild(a),n=m||b,n.insertBefore(o,n.firstChild),k.appendChecked=i.checked,k.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,k.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="
",k.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="
t
",q=a.getElementsByTagName("td"),u=q[0].offsetHeight===0,q[0].style.display="",q[1].style.display="none",k.reliableHiddenOffsets=u&&q[0].offsetHeight===0,a.innerHTML="",c.defaultView&&c.defaultView.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",a.appendChild(j),k.reliableMarginRight=(parseInt((c.defaultView.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0),o.innerHTML="",n.removeChild(o);if(a.attachEvent)for(t in{submit:1,change:1,focusin:1})s="on"+t,u=s in a,u||(a.setAttribute(s,"return;"),u=typeof a[s]=="function"),k[t+"Bubbles"]=u;o=l=g=h=m=j=a=i=null;return k}(),f.boxModel=f.support.boxModel;var i=/^(?:\{.*\}|\[.*\])$/,j=/([a-z])([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!l(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g=f.expando,h=typeof c=="string",i,j=a.nodeType,k=j?f.cache:a,l=j?a[f.expando]:a[f.expando]&&f.expando;if((!l||e&&l&&!k[l][g])&&h&&d===b)return;l||(j?a[f.expando]=l=++f.uuid:l=f.expando),k[l]||(k[l]={},j||(k[l].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?k[l][g]=f.extend(k[l][g],c):k[l]=f.extend(k[l],c);i=k[l],e&&(i[g]||(i[g]={}),i=i[g]),d!==b&&(i[f.camelCase(c)]=d);if(c==="events"&&!i[c])return i[g]&&i[g].events;return h?i[f.camelCase(c)]||i[c]:i}},removeData:function(b,c,d){if(!!f.acceptData(b)){var e=f.expando,g=b.nodeType,h=g?f.cache:b,i=g?b[f.expando]:f.expando;if(!h[i])return;if(c){var j=d?h[i][e]:h[i];if(j){delete j[c];if(!l(j))return}}if(d){delete h[i][e];if(!l(h[i]))return}var k=h[i][e];f.support.deleteExpando||h!=a?delete h[i]:h[i]=null,k?(h[i]={},g||(h[i].toJSON=f.noop),h[i][e]=k):g&&(f.support.deleteExpando?delete b[f.expando]:b.removeAttribute?b.removeAttribute(f.expando):b[f.expando]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d=null;if(typeof a=="undefined"){if(this.length){d=f.data(this[0]);if(this[0].nodeType===1){var e=this[0].attributes,g;for(var h=0,i=e.length;h-1)return!0;return!1},val:function(a){var c,d,e=this[0];if(!arguments.length){if(e){c=f.valHooks[e.nodeName.toLowerCase()]||f.valHooks[e.type];if(c&&"get"in c&&(d=c.get(e,"value"))!==b)return d;d=e.value;return typeof d=="string"?d.replace(p,""):d==null?"":d}return b}var g=f.isFunction(a);return this.each(function(d){var e=f(this),h;if(this.nodeType===1){g?h=a.call(this,d,e.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c=a.selectedIndex,d=[],e=a.options,g=a.type==="select-one";if(c<0)return null;for(var h=g?c:0,i=g?c+1:e.length;h=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attrFix:{tabindex:"tabIndex"},attr:function(a,c,d,e){var g=a.nodeType;if(!a||g===3||g===8||g===2)return b;if(e&&c in f.attrFn)return f(a)[c](d);if(!("getAttribute"in a))return f.prop(a,c,d);var h,i,j=g!==1||!f.isXMLDoc(a);j&&(c=f.attrFix[c]||c,i=f.attrHooks[c],i||(t.test(c)?i=w:v&&c!=="className"&&(f.nodeName(a,"form")||u.test(c))&&(i=v)));if(d!==b){if(d===null){f.removeAttr(a,c);return b}if(i&&"set"in i&&j&&(h=i.set(a,d,c))!==b)return h;a.setAttribute(c,""+d);return d}if(i&&"get"in i&&j&&(h=i.get(a,c))!==null)return h;h=a.getAttribute(c);return h===null?b:h},removeAttr:function(a,b){var c;a.nodeType===1&&(b=f.attrFix[b]||b,f.support.getSetAttribute?a.removeAttribute(b):(f.attr(a,b,""),a.removeAttributeNode(a.getAttributeNode(b))),t.test(b)&&(c=f.propFix[b]||b)in a&&(a[c]=!1))},attrHooks:{type:{set:function(a,b){if(q.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},tabIndex:{get:function(a){var c=a.getAttributeNode("tabIndex");return c&&c.specified?parseInt(c.value,10):r.test(a.nodeName)||s.test(a.nodeName)&&a.href?0:b}},value:{get:function(a,b){if(v&&f.nodeName(a,"button"))return v.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(v&&f.nodeName(a,"button"))return v.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e=a.nodeType;if(!a||e===3||e===8||e===2)return b;var g,h,i=e!==1||!f.isXMLDoc(a);i&&(c=f.propFix[c]||c,h=f.propHooks[c]);return d!==b?h&&"set"in h&&(g=h.set(a,d,c))!==b?g:a[c]=d:h&&"get"in h&&(g=h.get(a,c))!==b?g:a[c]},propHooks:{}}),w={get:function(a,c){return f.prop(a,c)?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},f.support.getSetAttribute||(f.attrFix=f.propFix,v=f.attrHooks.name=f.attrHooks.title=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&d.nodeValue!==""?d.nodeValue:b},set:function(a,b,c){var d=a.getAttributeNode(c);if(d){d.nodeValue=b;return b}}},f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})})),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}})),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var x=/\.(.*)$/,y=/^(?:textarea|input|select)$/i,z=/\./g,A=/ /g,B=/[^\w\s.|`]/g,C=function(a){return a.replace(B,"\\$&")};f.event={add:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){if(d===!1)d=D;else if(!d)return;var g,h;d.handler&&(g=d,d=g.handler),d.guid||(d.guid=f.guid++);var i=f._data(a);if(!i)return;var j=i.events,k=i.handle;j||(i.events=j={}),k||(i.handle=k=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.handle.apply(k.elem,arguments):b}),k.elem=a,c=c.split(" ");var l,m=0,n;while(l=c[m++]){h=g?f.extend({},g):{handler:d,data:e},l.indexOf(".")>-1?(n=l.split("."),l=n.shift(),h.namespace=n.slice(0).sort().join(".")):(n=[],h.namespace=""),h.type=l,h.guid||(h.guid=d.guid);var o=j[l],p=f.event.special[l]||{};if(!o){o=j[l]=[];if(!p.setup||p.setup.call(a,e,n,k)===!1)a.addEventListener?a.addEventListener(l,k,!1):a.attachEvent&&a.attachEvent("on"+l,k)}p.add&&(p.add.call(a,h),h.handler.guid||(h.handler.guid=d.guid)),o.push(h),f.event.global[l]=!0}a=null}},global:{},remove:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){d===!1&&(d=D);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=f.hasData(a)&&f._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(d=c.handler,c=c.type);if(!c||typeof c=="string"&&c.charAt(0)==="."){c=c||"";for(h in t)f.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+f.map(m.slice(0).sort(),C).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!d){for(j=0;j=0&&(h=h.slice(0,-1),j=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i. -shift(),i.sort());if(!!e&&!f.event.customEvent[h]||!!f.event.global[h]){c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.exclusive=j,c.namespace=i.join("."),c.namespace_re=new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)");if(g||!e)c.preventDefault(),c.stopPropagation();if(!e){f.each(f.cache,function(){var a=f.expando,b=this[a];b&&b.events&&b.events[h]&&f.event.trigger(c,d,b.handle.elem)});return}if(e.nodeType===3||e.nodeType===8)return;c.result=b,c.target=e,d=d!=null?f.makeArray(d):[],d.unshift(c);var k=e,l=h.indexOf(":")<0?"on"+h:"";do{var m=f._data(k,"handle");c.currentTarget=k,m&&m.apply(k,d),l&&f.acceptData(k)&&k[l]&&k[l].apply(k,d)===!1&&(c.result=!1,c.preventDefault()),k=k.parentNode||k.ownerDocument||k===c.target.ownerDocument&&a}while(k&&!c.isPropagationStopped());if(!c.isDefaultPrevented()){var n,o=f.event.special[h]||{};if((!o._default||o._default.call(e.ownerDocument,c)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)){try{l&&e[h]&&(n=e[l],n&&(e[l]=null),f.event.triggered=h,e[h]())}catch(p){}n&&(e[l]=n),f.event.triggered=b}}return c.result}},handle:function(c){c=f.event.fix(c||a.event);var d=((f._data(this,"events")||{})[c.type]||[]).slice(0),e=!c.exclusive&&!c.namespace,g=Array.prototype.slice.call(arguments,0);g[0]=c,c.currentTarget=this;for(var h=0,i=d.length;h-1?f.map(a.options,function(a){return a.selected}).join("-"):"":f.nodeName(a,"select")&&(c=a.selectedIndex);return c},J=function(c){var d=c.target,e,g;if(!!y.test(d.nodeName)&&!d.readOnly){e=f._data(d,"_change_data"),g=I(d),(c.type!=="focusout"||d.type!=="radio")&&f._data(d,"_change_data",g);if(e===b||g===e)return;if(e!=null||g)c.type="change",c.liveFired=b,f.event.trigger(c,arguments[1],d)}};f.event.special.change={filters:{focusout:J,beforedeactivate:J,click:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(c==="radio"||c==="checkbox"||f.nodeName(b,"select"))&&J.call(this,a)},keydown:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(a.keyCode===13&&!f.nodeName(b,"textarea")||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&J.call(this,a)},beforeactivate:function(a){var b=a.target;f._data(b,"_change_data",I(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in H)f.event.add(this,c+".specialChange",H[c]);return y.test(this.nodeName)},teardown:function(a){f.event.remove(this,".specialChange");return y.test(this.nodeName)}},H=f.event.special.change.filters,H.focus=H.beforeactivate}f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){function e(a){var c=f.event.fix(a);c.type=b,c.originalEvent={},f.event.trigger(c,null,c.target),c.isDefaultPrevented()&&a.preventDefault()}var d=0;f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.each(["bind","one"],function(a,c){f.fn[c]=function(a,d,e){var g;if(typeof a=="object"){for(var h in a)this[c](h,d,a[h],e);return this}if(arguments.length===2||d===!1)e=d,d=b;c==="one"?(g=function(a){f(this).unbind(a,g);return e.apply(this,arguments)},g.guid=e.guid||f.guid++):g=e;if(a==="unload"&&c!=="one")this.one(a,d,e);else for(var i=0,j=this.length;i0?this.bind(b,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d=0,e=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,f,g){f=f||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return f;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(e.call(n)==="[object Array]")if(!u)f.push.apply(f,n);else if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&f.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&f.push(j[t]);else p(n,f);o&&(k(o,h,f,g),k.uniqueSort(f));return f};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=d++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(e.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var f=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(e||!l.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return k(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="
";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g0)for(h=g;h0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(d=0,e=a.length;d-1:f(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=T.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a||typeof a=="string")return f.inArray(this[0],a?f(a):this.parent().children());return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(V(c[0])||V(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c),g=S.call(arguments);O.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!U[a]?f.unique(e):e,(this.length>1||Q.test(d))&&P.test(a)&&(e=e.reverse());return this.pushStack(e,a,g.join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var X=/ jQuery\d+="(?:\d+|null)"/g,Y=/^\s+/,Z=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,$=/<([\w:]+)/,_=/",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]};bf.optgroup=bf.option,bf.tbody=bf.tfoot=bf.colgroup=bf.caption=bf.thead,bf.th=bf.td,f.support.htmlSerialize||(bf._default=[1,"div
","
"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){f(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(X,""):null;if(typeof a=="string"&&!bb.test(a)&&(f.support.leadingWhitespace||!Y.test(a))&&!bf[($.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Z,"<$1>");try{for(var c=0,d=this.length;c1&&l0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j -)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d=a.cloneNode(!0),e,g,h;if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bi(a,d),e=bj(a),g=bj(d);for(h=0;e[h];++h)bi(e[h],g[h])}if(b){bh(a,d);if(c){e=bj(a),g=bj(d);for(h=0;e[h];++h)bh(e[h],g[h])}}e=g=null;return d},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!ba.test(k))k=b.createTextNode(k);else{k=k.replace(Z,"<$1>");var l=($.exec(k)||["",""])[1].toLowerCase(),m=bf[l]||bf._default,n=m[0],o=b.createElement("div");o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=_.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]===""&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&Y.test(k)&&o.insertBefore(b.createTextNode(Y.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bo.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle;c.zoom=1;var e=f.isNaN(b)?"":"alpha(opacity="+b*100+")",g=d&&d.filter||c.filter||"";c.filter=bn.test(g)?g.replace(bn,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bx(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(by=function(a,c){var d,e,g;c=c.replace(bp,"-$1").toLowerCase();if(!(e=a.ownerDocument.defaultView))return b;if(g=e.getComputedStyle(a,null))d=g.getPropertyValue(c),d===""&&!f.contains(a.ownerDocument.documentElement,a)&&(d=f.style(a,c));return d}),c.documentElement.currentStyle&&(bz=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bq.test(d)&&br.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bx=by||bz,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bB=/%20/g,bC=/\[\]$/,bD=/\r?\n/g,bE=/#.*$/,bF=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bG=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bH=/^(?:about|app|app\-storage|.+\-extension|file|widget):$/,bI=/^(?:GET|HEAD)$/,bJ=/^\/\//,bK=/\?/,bL=/)<[^<]*)*<\/script>/gi,bM=/^(?:select|textarea)/i,bN=/\s+/,bO=/([?&])_=[^&]*/,bP=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bQ=f.fn.load,bR={},bS={},bT,bU;try{bT=e.href}catch(bV){bT=c.createElement("a"),bT.href="",bT=bT.href}bU=bP.exec(bT.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bQ)return bQ.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("
").append(c.replace(bL,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bM.test(this.nodeName)||bG.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bD,"\r\n")}}):{name:b.name,value:c.replace(bD,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.bind(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?f.extend(!0,a,f.ajaxSettings,b):(b=a,a=f.extend(!0,f.ajaxSettings,b));for(var c in{context:1,url:1})c in b?a[c]=b[c]:c in f.ajaxSettings&&(a[c]=f.ajaxSettings[c]);return a},ajaxSettings:{url:bT,isLocal:bH.test(bU[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":"*/*"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML}},ajaxPrefilter:bW(bR),ajaxTransport:bW(bS),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a?4:0;var o,r,u,w=l?bZ(d,v,l):b,x,y;if(a>=200&&a<300||a===304){if(d.ifModified){if(x=v.getResponseHeader("Last-Modified"))f.lastModified[k]=x;if(y=v.getResponseHeader("Etag"))f.etag[k]=y}if(a===304)c="notmodified",o=!0;else try{r=b$(d,w),c="success",o=!0}catch(z){c="parsererror",u=z}}else{u=c;if(!c||a)c="error",a<0&&(a=0)}v.status=a,v.statusText=c,o?h.resolveWith(e,[r,c,v]):h.rejectWith(e,[v,c,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.resolveWith(e,[v,c]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f._Deferred(),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bF.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.done,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bE,"").replace(bJ,bU[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bN),d.crossDomain==null&&(r=bP.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bU[1]&&r[2]==bU[2]&&(r[3]||(r[1]==="http:"?80:443))==(bU[3]||(bU[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bX(bR,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bI.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bK.test(d.url)?"&":"?")+d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bO,"$1_="+x);d.url=y+(y===d.url?(bK.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", */*; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bX(bS,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){status<2?w(-1,z):f.error(z)}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)bY(g,a[g],c,e);return d.join("&").replace(bB,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var b_=f.now(),ca=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+b_++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ca.test(b.url)||e&&ca.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ca,l),b.url===j&&(e&&(k=k.replace(ca,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cb=a.ActiveXObject?function(){for(var a in cd)cd[a](0,1)}:!1,cc=0,cd;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ce()||cf()}:ce,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cb&&delete cd[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cc,cb&&(cd||(cd={},f(a).unload(cb)),cd[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cg={},ch,ci,cj=/^(?:toggle|show|hide)$/,ck=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cl,cm=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cn,co=a.webkitRequestAnimationFrame||a.mozRequestAnimationFrame||a.oRequestAnimationFrame;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cr("show",3),a,b,c);for(var g=0,h=this.length;g=e.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),e.animatedProperties[this.prop]=!0;for(g in e.animatedProperties)e.animatedProperties[g]!==!0&&(c=!1);if(c){e.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){d.style["overflow"+b]=e.overflow[a]}),e.hide&&f(d).hide();if(e.hide||e.show)for(var i in e.animatedProperties)f.style(d,i,e.orig[i]);e.complete.call(d)}return!1}e.duration==Infinity?this.now=b:(h=b-this.startTime,this.state=h/e.duration,this.pos=f.easing[e.animatedProperties[this.prop]](this.state,h,0,1,e.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){for(var a=f.timers,b=0;b
";f.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),d=b.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,this.doesNotAddBorder=e.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,e.style.position="fixed",e.style.top="20px",this.supportsFixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",this.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),f.offset.initialize=f.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.offset.initialize(),f.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cu.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cu.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cv(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cv(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a&&a.style?parseFloat(f.css(a,d,"padding")):null},f.fn["outer"+c]=function(a){var b=this[0];return b&&b.style?parseFloat(f.css(b,d,a?"margin":"border")):null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c];return e.document.compatMode==="CSS1Compat"&&g||e.document.body["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var h=f.css(e,d),i=parseFloat(h);return f.isNaN(i)?h:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f})(window); \ No newline at end of file diff --git a/resources/library/search/Google images.wgs/select/jquery.selectBox-arrow.gif b/resources/library/search/Google images.wgs/select/jquery.selectBox-arrow.gif deleted file mode 100755 index 2796795f32d6d81fa787880dc5f02bf16842ac0e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 64 zcmZ?wbhEHbjEB<5wG8q|kKzxu41Cw|U^YQ~-cX;OHJGF1VcU5h^ N#}y&Vg@FtV)&TF!5w!pS diff --git a/resources/library/search/Google images.wgs/select/jquery.selectBox.css b/resources/library/search/Google images.wgs/select/jquery.selectBox.css deleted file mode 100755 index 61a88661..00000000 --- a/resources/library/search/Google images.wgs/select/jquery.selectBox.css +++ /dev/null @@ -1,150 +0,0 @@ -/* Dropdown control */ -.selectBox-dropdown { - min-width: 60px; - position: relative; - /*border: solid 1px #BBB;*/ - line-height: 1.5; - text-decoration: none; - text-align: left; - color: #000; - outline: none; - vertical-align: middle; - background: #F2F2F2; - background: -moz-linear-gradient(top, #F8F8F8 1%, #E1E1E1 100%); - background: -webkit-gradient(linear, left top, left bottom, color-stop(1%, #F8F8F8), color-stop(100%, #E1E1E1)); - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#F8F8F8', endColorstr='#E1E1E1', GradientType=0); - -moz-box-shadow: 0 1px 0 rgba(255, 255, 255, .75); - -webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, .75); - box-shadow: 0 1px 0 rgba(255, 255, 255, .75); - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - display: inline-block; - cursor: default; -} - -.selectBox-dropdown:focus, -.selectBox-dropdown:focus .selectBox-arrow { - border-color: #666; -} - -.selectBox-dropdown.selectBox-menuShowing { - -moz-border-radius-bottomleft: 0; - -moz-border-radius-bottomright: 0; - -webkit-border-bottom-left-radius: 0; - -webkit-border-bottom-right-radius: 0; - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; -} - -.selectBox-dropdown .selectBox-label { - padding: 2px 8px; - display: inline-block; - white-space: nowrap; - overflow: hidden; -} - -.selectBox-dropdown .selectBox-arrow { - position: absolute; - top: 0; - right: 0; - width: 23px; - height: 100%; - background: url(jquery.selectBox-arrow.gif) 50% center no-repeat; - border-left: solid 1px #BBB; -} - - -/* Dropdown menu */ -.selectBox-dropdown-menu { - position: absolute; - z-index: 99999; - max-height: 200px; - min-height: 1em; - border: solid 1px #BBB; /* should be the same border width as .selectBox-dropdown */ - background: #FFF; - -moz-box-shadow: 0 2px 6px rgba(0, 0, 0, .2); - -webkit-box-shadow: 0 2px 6px rgba(0, 0, 0, .2); - box-shadow: 0 2px 6px rgba(0, 0, 0, .2); - overflow: auto; -} - - -/* Inline control */ -.selectBox-inline { - min-width: 150px; - outline: none; - border: solid 1px #BBB; - background: #FFF; - display: inline-block; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - overflow: auto; -} - -.selectBox-inline:focus { - border-color: #666; -} - - -/* Options */ -.selectBox-options, -.selectBox-options LI, -.selectBox-options LI A { - list-style: none; - display: block; - cursor: default; - padding: 0; - margin: 0; -} - -.selectBox-options LI A { - line-height: 1.5; - padding: 0 .5em; - white-space: nowrap; - overflow: hidden; - background: 6px center no-repeat; -} - -.selectBox-options LI.selectBox-hover A { - background-color: #EEE; -} - -.selectBox-options LI.selectBox-disabled A { - color: #888; - background-color: transparent; -} - -.selectBox-options LI.selectBox-selected A { - background-color: #C8DEF4; -} - -.selectBox-options .selectBox-optgroup { - color: #666; - background: #EEE; - font-weight: bold; - line-height: 1.5; - padding: 0 .3em; - white-space: nowrap; -} - - -/* Disabled state */ -.selectBox.selectBox-disabled { - color: #888 !important; -} - -.selectBox-dropdown.selectBox-disabled .selectBox-arrow { - opacity: .5; - filter: alpha(opacity=50); - border-color: #666; -} - -.selectBox-inline.selectBox-disabled { - color: #888 !important; -} - -.selectBox-inline.selectBox-disabled .selectBox-options A { - background-color: transparent !important; -} \ No newline at end of file diff --git a/resources/library/search/Google images.wgs/select/jquery.selectBox.js b/resources/library/search/Google images.wgs/select/jquery.selectBox.js deleted file mode 100755 index a45e3f60..00000000 --- a/resources/library/search/Google images.wgs/select/jquery.selectBox.js +++ /dev/null @@ -1,916 +0,0 @@ -/* - * jQuery selectBox - A cosmetic, styleable replacement for SELECT elements - * - * Copyright 2012 Cory LaViska for A Beautiful Site, LLC. - * - * https://github.com/claviska/jquery-selectBox - * - * Licensed under both the MIT license and the GNU GPLv2 (same as jQuery: http://jquery.org/license) - * - */ -if(jQuery) (function($) { - - $.extend($.fn, { - - selectBox: function(method, data) { - - var typeTimer, - typeSearch = '', - isMac = navigator.platform.match(/mac/i); - - // - // Private methods - // - - var init = function(select, data) { - - var options; - - // Disable for iOS devices (their native controls are more suitable for a touch device) - if( navigator.userAgent.match(/iPad|iPhone|Android|IEMobile|BlackBerry/i) ) return false; - - // Element must be a select control - if( select.tagName.toLowerCase() !== 'select' ) return false; - - select = $(select); - if( select.data('selectBox-control') ) return false; - - var control = $(''), - inline = select.attr('multiple') || parseInt(select.attr('size')) > 1; - - var settings = data || {}; - - control - .width(select.outerWidth()) - .addClass(select.attr('class')) - .attr('title', select.attr('title') || '') - .attr('tabindex', parseInt(select.attr('tabindex'))) - .css('display', 'inline-block') - .bind('focus.selectBox', function() { - if( this !== document.activeElement && document.body !== document.activeElement ) $(document.activeElement).blur(); - if( control.hasClass('selectBox-active') ) return; - control.addClass('selectBox-active'); - select.trigger('focus'); - }) - .bind('blur.selectBox', function() { - if( !control.hasClass('selectBox-active') ) return; - control.removeClass('selectBox-active'); - select.trigger('blur'); - }); - - if( !$(window).data('selectBox-bindings') ) { - $(window) - .data('selectBox-bindings', true) - .bind('scroll.selectBox', hideMenus) - .bind('resize.selectBox', hideMenus); - } - - if( select.attr('disabled') ) control.addClass('selectBox-disabled'); - - // Focus on control when label is clicked - select.bind('click.selectBox', function(event) { - control.focus(); - event.preventDefault(); - }); - - // Generate control - if( inline ) { - - // - // Inline controls - // - options = getOptions(select, 'inline'); - - control - .append(options) - .data('selectBox-options', options) - .addClass('selectBox-inline selectBox-menuShowing') - .bind('keydown.selectBox', function(event) { - handleKeyDown(select, event); - }) - .bind('keypress.selectBox', function(event) { - handleKeyPress(select, event); - }) - .bind('mousedown.selectBox', function(event) { - if( $(event.target).is('A.selectBox-inline') ) event.preventDefault(); - if( !control.hasClass('selectBox-focus') ) control.focus(); - }) - .insertAfter(select); - - // Auto-height based on size attribute - if( !select[0].style.height ) { - - var size = select.attr('size') ? parseInt(select.attr('size')) : 5; - - // Draw a dummy control off-screen, measure, and remove it - var tmp = control - .clone() - .removeAttr('id') - .css({ - position: 'absolute', - top: '-9999em' - }) - .show() - .appendTo('body'); - tmp.find('.selectBox-options').html('
  • \u00A0
  • '); - var optionHeight = parseInt(tmp.find('.selectBox-options A:first').html(' ').outerHeight()); - tmp.remove(); - - control.height(optionHeight * size); - - } - - disableSelection(control); - - } else { - - // - // Dropdown controls - // - var label = $(''), - arrow = $(''); - - // Update label - label - .attr('class', getLabelClass(select)) - .text(getLabelText(select)); - - options = getOptions(select, 'dropdown'); - options.appendTo('BODY'); - - control - .data('selectBox-options', options) - .addClass('selectBox-dropdown') - .append(label) - .append(arrow) - .bind('mousedown.selectBox', function(event) { - if( control.hasClass('selectBox-menuShowing') ) { - hideMenus(); - } else { - event.stopPropagation(); - // Webkit fix to prevent premature selection of options - options.data('selectBox-down-at-x', event.screenX).data('selectBox-down-at-y', event.screenY); - showMenu(select); - } - }) - .bind('keydown.selectBox', function(event) { - handleKeyDown(select, event); - }) - .bind('keypress.selectBox', function(event) { - handleKeyPress(select, event); - }) - .bind('open.selectBox', function(event, triggerData) { - if(triggerData && triggerData._selectBox === true) return; - showMenu(select); - }) - .bind('close.selectBox', function(event, triggerData) { - if(triggerData && triggerData._selectBox === true) return; - hideMenus(); - }) - .insertAfter(select); - - // Set label width - var labelWidth = control.width() - arrow.outerWidth() - parseInt(label.css('paddingLeft')) - parseInt(label.css('paddingLeft')); - label.width(labelWidth); - - disableSelection(control); - - } - - // Store data for later use and show the control - select - .addClass('selectBox') - .data('selectBox-control', control) - .data('selectBox-settings', settings) - .hide(); - - }; - - - var getOptions = function(select, type) { - var options; - - // Private function to handle recursion in the getOptions function. - var _getOptions = function(select, options) { - // Loop through the set in order of element children. - select.children('OPTION, OPTGROUP').each( function() { - // If the element is an option, add it to the list. - if ($(this).is('OPTION')) { - // Check for a value in the option found. - if($(this).length > 0) { - // Create an option form the found element. - generateOptions($(this), options); - } - else { - // No option information found, so add an empty. - options.append('
  • \u00A0
  • '); - } - } - else { - // If the element is an option group, add the group and call this function on it. - var optgroup = $('
  • '); - optgroup.text($(this).attr('label')); - options.append(optgroup); - options = _getOptions($(this), options); - } - }); - // Return the built strin - return options; - }; - - switch( type ) { - - case 'inline': - - options = $('